-function common_avatar_filename($id, $extension, $size=NULL, $extra=NULL) {
- global $config;
-
- if ($size) {
- return $id . '-' . $size . (($extra) ? ('-' . $extra) : '') . $extension;
- } else {
- return $id . '-original' . (($extra) ? ('-' . $extra) : '') . $extension;
- }
-}
-
-function common_avatar_path($filename) {
- global $config;
- return INSTALLDIR . '/avatar/' . $filename;
-}
-
-function common_avatar_url($filename) {
- return common_path('avatar/'.$filename);
-}
-
-function common_avatar_display_url($avatar) {
- $server = common_config('avatar', 'server');
- if ($server) {
- return 'http://'.$server.'/'.$avatar->filename;
- } else {
- return $avatar->url;
- }
-}
-
-function common_default_avatar($size) {
- static $sizenames = array(AVATAR_PROFILE_SIZE => 'profile',
- AVATAR_STREAM_SIZE => 'stream',
- AVATAR_MINI_SIZE => 'mini');
- return theme_path('default-avatar-'.$sizenames[$size].'.png');
-}
-
-function common_local_url($action, $args=NULL) {
- global $config;
- if ($config['site']['fancy']) {
- return common_fancy_url($action, $args);
- } else {
- return common_simple_url($action, $args);
- }
-}
-
-function common_fancy_url($action, $args=NULL) {
- switch (strtolower($action)) {
- case 'public':
- if ($args && $args['page']) {
- return common_path('?page=' . $args['page']);
- } else {
- return common_path('');
- }
- case 'publicrss':
- return common_path('rss');
- case 'publicxrds':
- return common_path('xrds');
- case 'doc':
- return common_path('doc/'.$args['title']);
- case 'login':
- case 'logout':
- case 'register':
- case 'subscribe':
- case 'unsubscribe':
- return common_path('main/'.$action);
- case 'remotesubscribe':
- if ($args && $args['nickname']) {
- return common_path('main/remote?nickname=' . $args['nickname']);
- } else {
- return common_path('main/remote');
- }
- case 'openidlogin':
- return common_path('main/openid');
- case 'avatar':
- case 'password':
- return common_path('settings/'.$action);
- case 'profilesettings':
- return common_path('settings/profile');
- case 'openidsettings':
- return common_path('settings/openid');
- case 'newnotice':
- if ($args && $args['replyto']) {
- return common_path('notice/new?replyto='.$args['replyto']);
- } else {
- return common_path('notice/new');
- }
- case 'shownotice':
- return common_path('notice/'.$args['notice']);
- case 'xrds':
- case 'foaf':
- return common_path($args['nickname'].'/'.$action);
- case 'subscriptions':
- case 'subscribers':
- case 'all':
- case 'replies':
- if ($args && $args['page']) {
- return common_path($args['nickname'].'/'.$action.'?page=' . $args['page']);
- } else {
- return common_path($args['nickname'].'/'.$action);
- }
- case 'allrss':
- return common_path($args['nickname'].'/all/rss');
- case 'repliesrss':
- return common_path($args['nickname'].'/replies/rss');
- case 'userrss':
- return common_path($args['nickname'].'/rss');
- case 'showstream':
- if ($args && $args['page']) {
- return common_path($args['nickname'].'?page=' . $args['page']);
- } else {
- return common_path($args['nickname']);
- }
- case 'confirmaddress':
- return common_path('main/confirmaddress/'.$args['code']);
- case 'userbyid':
- return common_path('user/'.$args['id']);
- case 'recoverpassword':
- $path = 'main/recoverpassword';
- if ($args['code']) {
- $path .= '/' . $args['code'];
- }
- return common_path($path);
- case 'imsettings':
- return common_path('settings/im');
- case 'peoplesearch':
- return common_path('search/people' . (($args) ? ('?' . http_build_query($args)) : ''));
- case 'noticesearch':
- return common_path('search/notice' . (($args) ? ('?' . http_build_query($args)) : ''));
- case 'noticesearchrss':
- return common_path('search/notice/rss' . (($args) ? ('?' . http_build_query($args)) : ''));
- case 'avatarbynickname':
- return common_path($args['nickname'].'/avatar/'.$args['size']);
- default:
- return common_simple_url($action, $args);
- }
-}
-
-function common_simple_url($action, $args=NULL) {
- global $config;
- /* XXX: pretty URLs */
- $extra = '';
- if ($args) {
- foreach ($args as $key => $value) {
- $extra .= "&${key}=${value}";
- }
- }
- return common_path("index.php?action=${action}${extra}");
-}
-
-function common_path($relative) {
- global $config;
- $pathpart = ($config['site']['path']) ? $config['site']['path']."/" : '';
- return "http://".$config['site']['server'].'/'.$pathpart.$relative;
-}
-
-function common_date_string($dt) {
- // XXX: do some sexy date formatting
- // return date(DATE_RFC822, $dt);
- $t = strtotime($dt);
- $now = time();
- $diff = $now - $t;
-
- if ($now < $t) { # that shouldn't happen!
- return common_exact_date($dt);
- } else if ($diff < 60) {
- return _t('a few seconds ago');
- } else if ($diff < 92) {
- return _t('about a minute ago');
- } else if ($diff < 3300) {
- return _t('about ') . round($diff/60) . _t(' minutes ago');
- } else if ($diff < 5400) {
- return _t('about an hour ago');
- } else if ($diff < 22 * 3600) {
- return _t('about ') . round($diff/3600) . _t(' hours ago');
- } else if ($diff < 37 * 3600) {
- return _t('about a day ago');
- } else if ($diff < 24 * 24 * 3600) {
- return _t('about ') . round($diff/(24*3600)) . _t(' days ago');
- } else if ($diff < 46 * 24 * 3600) {
- return _t('about a month ago');
- } else if ($diff < 330 * 24 * 3600) {
- return _t('about ') . round($diff/(30*24*3600)) . _t(' months ago');
- } else if ($diff < 480 * 24 * 3600) {
- return _t('about a year ago');
- } else {
- return common_exact_date($dt);
- }
-}
-
-function common_exact_date($dt) {
- $t = strtotime($dt);
- return date(DATE_RFC850, $t);
-}
-
-function common_date_w3dtf($dt) {
- $t = strtotime($dt);
- return date(DATE_W3C, $t);
-}
-
-function common_redirect($url, $code=307) {
- static $status = array(301 => "Moved Permanently",
- 302 => "Found",
- 303 => "See Other",
- 307 => "Temporary Redirect");
- header("Status: ${code} $status[$code]");
- header("Location: $url");
-
- common_start_xml('a',
- '-//W3C//DTD XHTML 1.0 Strict//EN',
- 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd');
- common_element('a', array('href' => $url), $url);
- common_end_xml();
-}
-
-function common_save_replies($notice) {
- # extract all @messages
- $cnt = preg_match_all('/(?:^|\s)@([a-z0-9]{1,64})/', $notice->content, $match);
- if (!$cnt) {
- return true;
- }
- $sender = Profile::staticGet($notice->profile_id);
- # store replied only for first @ (what user/notice what the reply directed,
- # we assume first @ is it)
- for ($i=0; $i<count($match[1]); $i++) {
- $nickname = $match[1][$i];
- $recipient = common_relative_profile($sender, $nickname, $notice->created);
- if (!$recipient) {
- continue;
- }
- if ($i == 0 && ($recipient->id != $sender->id)) { # Don't save reply to self
- $reply_for = $recipient;
- $recipient_notice = $reply_for->getCurrentNotice();
- $orig = clone($notice);
- $notice->reply_to = $recipient_notice->id;
- $notice->update($orig);
- }
- $reply = new Reply();
- $reply->notice_id = $notice->id;
- $reply->profile_id = $recipient->id;
- $id = $reply->insert();
- if (!$id) {
- $last_error = &PEAR::getStaticProperty('DB_DataObject','lastError');
- common_log(LOG_ERROR, 'DB error inserting reply: ' . $last_error->message);
- common_server_error('DB error inserting reply: ' . $last_error->message);
- return;
- }
- }
-}
-
-function common_broadcast_notice($notice, $remote=false) {
- if (common_config('queue', 'enabled')) {
- # Do it later!
- return common_enqueue_notice($notice);
- } else {
- return common_real_broadcast($notice, $remote);
- }
-}
-
-# Stick the notice on the queue
-
-function common_enqueue_notice($notice) {
- $qi = new Queue_item();
- $qi->notice_id = $notice->id;
- $qi->created = $notice->created;
+function common_avatar_filename($id, $extension, $size=null, $extra=null)
+{
+ global $config;
+
+ if ($size) {
+ return $id . '-' . $size . (($extra) ? ('-' . $extra) : '') . $extension;
+ } else {
+ return $id . '-original' . (($extra) ? ('-' . $extra) : '') . $extension;
+ }
+}
+
+function common_avatar_path($filename)
+{
+ global $config;
+ return INSTALLDIR . '/avatar/' . $filename;
+}
+
+function common_avatar_url($filename)
+{
+ return common_path('avatar/'.$filename);
+}
+
+function common_avatar_display_url($avatar)
+{
+ $server = common_config('avatar', 'server');
+ if ($server) {
+ return 'http://'.$server.'/'.$avatar->filename;
+ } else {
+ return $avatar->url;
+ }
+}
+
+function common_default_avatar($size)
+{
+ static $sizenames = array(AVATAR_PROFILE_SIZE => 'profile',
+ AVATAR_STREAM_SIZE => 'stream',
+ AVATAR_MINI_SIZE => 'mini');
+ return theme_path('default-avatar-'.$sizenames[$size].'.png');
+}
+
+function common_local_url($action, $args=null, $fragment=null)
+{
+ $url = null;
+ if (common_config('site','fancy')) {
+ $url = common_fancy_url($action, $args);
+ } else {
+ $url = common_simple_url($action, $args);
+ }
+ if (!is_null($fragment)) {
+ $url .= '#'.$fragment;
+ }
+ return $url;
+}
+
+function common_fancy_url($action, $args=null)
+{
+ switch (strtolower($action)) {
+ case 'public':
+ if ($args && isset($args['page'])) {
+ return common_path('?page=' . $args['page']);
+ } else {
+ return common_path('');
+ }
+ case 'featured':
+ if ($args && isset($args['page'])) {
+ return common_path('featured?page=' . $args['page']);
+ } else {
+ return common_path('featured');
+ }
+ case 'favorited':
+ if ($args && isset($args['page'])) {
+ return common_path('favorited?page=' . $args['page']);
+ } else {
+ return common_path('favorited');
+ }
+ case 'publicrss':
+ return common_path('rss');
+ case 'publicatom':
+ return common_path("api/statuses/public_timeline.atom");
+ case 'publicxrds':
+ return common_path('xrds');
+ case 'featuredrss':
+ return common_path('featuredrss');
+ case 'favoritedrss':
+ return common_path('favoritedrss');
+ case 'opensearch':
+ if ($args && $args['type']) {
+ return common_path('opensearch/'.$args['type']);
+ } else {
+ return common_path('opensearch/people');
+ }
+ case 'doc':
+ return common_path('doc/'.$args['title']);
+ case 'block':
+ case 'login':
+ case 'logout':
+ case 'subscribe':
+ case 'unsubscribe':
+ case 'invite':
+ return common_path('main/'.$action);
+ case 'tagother':
+ return common_path('main/tagother?id='.$args['id']);
+ case 'register':
+ if ($args && $args['code']) {
+ return common_path('main/register/'.$args['code']);
+ } else {
+ return common_path('main/register');
+ }
+ case 'remotesubscribe':
+ if ($args && $args['nickname']) {
+ return common_path('main/remote?nickname=' . $args['nickname']);
+ } else {
+ return common_path('main/remote');
+ }
+ case 'nudge':
+ return common_path($args['nickname'].'/nudge');
+ case 'openidlogin':
+ return common_path('main/openid');
+ case 'profilesettings':
+ return common_path('settings/profile');
+ case 'emailsettings':
+ return common_path('settings/email');
+ case 'openidsettings':
+ return common_path('settings/openid');
+ case 'smssettings':
+ return common_path('settings/sms');
+ case 'twittersettings':
+ return common_path('settings/twitter');
+ case 'othersettings':
+ return common_path('settings/other');
+ case 'deleteprofile':
+ return common_path('settings/delete');
+ case 'newnotice':
+ if ($args && $args['replyto']) {
+ return common_path('notice/new?replyto='.$args['replyto']);
+ } else {
+ return common_path('notice/new');
+ }
+ case 'shownotice':
+ return common_path('notice/'.$args['notice']);
+ case 'deletenotice':
+ if ($args && $args['notice']) {
+ return common_path('notice/delete/'.$args['notice']);
+ } else {
+ return common_path('notice/delete');
+ }
+ case 'microsummary':
+ case 'xrds':
+ case 'foaf':
+ return common_path($args['nickname'].'/'.$action);
+ case 'all':
+ case 'replies':
+ case 'inbox':
+ case 'outbox':
+ if ($args && isset($args['page'])) {
+ return common_path($args['nickname'].'/'.$action.'?page=' . $args['page']);
+ } else {
+ return common_path($args['nickname'].'/'.$action);
+ }
+ case 'subscriptions':
+ case 'subscribers':
+ $nickname = $args['nickname'];
+ unset($args['nickname']);
+ if (isset($args['tag'])) {
+ $tag = $args['tag'];
+ unset($args['tag']);
+ }
+ $params = http_build_query($args);
+ if ($params) {
+ return common_path($nickname.'/'.$action . (($tag) ? '/' . $tag : '') . '?' . $params);
+ } else {
+ return common_path($nickname.'/'.$action . (($tag) ? '/' . $tag : ''));
+ }
+ case 'allrss':
+ return common_path($args['nickname'].'/all/rss');
+ case 'repliesrss':
+ return common_path($args['nickname'].'/replies/rss');
+ case 'userrss':
+ if (isset($args['limit']))
+ return common_path($args['nickname'].'/rss?limit=' . $args['limit']);
+ return common_path($args['nickname'].'/rss');
+ case 'showstream':
+ if ($args && isset($args['page'])) {
+ return common_path($args['nickname'].'?page=' . $args['page']);
+ } else {
+ return common_path($args['nickname']);
+ }
+
+ case 'usertimeline':
+ return common_path("api/statuses/user_timeline/".$args['nickname'].".atom");
+ case 'confirmaddress':
+ return common_path('main/confirmaddress/'.$args['code']);
+ case 'userbyid':
+ return common_path('user/'.$args['id']);
+ case 'recoverpassword':
+ $path = 'main/recoverpassword';
+ if ($args['code']) {
+ $path .= '/' . $args['code'];
+ }
+ return common_path($path);
+ case 'imsettings':
+ return common_path('settings/im');
+ case 'peoplesearch':
+ return common_path('search/people' . (($args) ? ('?' . http_build_query($args)) : ''));
+ case 'noticesearch':
+ return common_path('search/notice' . (($args) ? ('?' . http_build_query($args)) : ''));
+ case 'noticesearchrss':
+ return common_path('search/notice/rss' . (($args) ? ('?' . http_build_query($args)) : ''));
+ case 'avatarbynickname':
+ return common_path($args['nickname'].'/avatar/'.$args['size']);
+ case 'tag':
+ if (isset($args['tag']) && $args['tag']) {
+ $path = 'tag/' . $args['tag'];
+ unset($args['tag']);
+ } else {
+ $path = 'tags';
+ }
+ return common_path($path . (($args) ? ('?' . http_build_query($args)) : ''));
+ case 'peopletag':
+ $path = 'peopletag/' . $args['tag'];
+ unset($args['tag']);
+ return common_path($path . (($args) ? ('?' . http_build_query($args)) : ''));
+ case 'tags':
+ return common_path('tags' . (($args) ? ('?' . http_build_query($args)) : ''));
+ case 'favor':
+ return common_path('main/favor');
+ case 'disfavor':
+ return common_path('main/disfavor');
+ case 'showfavorites':
+ if ($args && isset($args['page'])) {
+ return common_path($args['nickname'].'/favorites?page=' . $args['page']);
+ } else {
+ return common_path($args['nickname'].'/favorites');
+ }
+ case 'favoritesrss':
+ return common_path($args['nickname'].'/favorites/rss');
+ case 'showmessage':
+ return common_path('message/' . $args['message']);
+ case 'newmessage':
+ return common_path('message/new' . (($args) ? ('?' . http_build_query($args)) : ''));
+ case 'api':
+ // XXX: do fancy URLs for all the API methods
+ switch (strtolower($args['apiaction'])) {
+ case 'statuses':
+ switch (strtolower($args['method'])) {
+ case 'user_timeline.rss':
+ return common_path('api/statuses/user_timeline/'.$args['argument'].'.rss');
+ case 'user_timeline.atom':
+ return common_path('api/statuses/user_timeline/'.$args['argument'].'.atom');
+ case 'user_timeline.json':
+ return common_path('api/statuses/user_timeline/'.$args['argument'].'.json');
+ case 'user_timeline.xml':
+ return common_path('api/statuses/user_timeline/'.$args['argument'].'.xml');
+ default: return common_simple_url($action, $args);
+ }
+ default: return common_simple_url($action, $args);
+ }
+ case 'sup':
+ if ($args && isset($args['seconds'])) {
+ return common_path('main/sup?seconds='.$args['seconds']);
+ } else {
+ return common_path('main/sup');
+ }
+ default:
+ return common_simple_url($action, $args);
+ }
+}
+
+function common_simple_url($action, $args=null)
+{
+ global $config;
+ /* XXX: pretty URLs */
+ $extra = '';
+ if ($args) {
+ foreach ($args as $key => $value) {
+ $extra .= "&${key}=${value}";
+ }
+ }
+ return common_path("index.php?action=${action}${extra}");
+}
+
+function common_path($relative)
+{
+ global $config;
+ $pathpart = ($config['site']['path']) ? $config['site']['path']."/" : '';
+ return "http://".$config['site']['server'].'/'.$pathpart.$relative;
+}
+
+function common_date_string($dt)
+{
+ // XXX: do some sexy date formatting
+ // return date(DATE_RFC822, $dt);
+ $t = strtotime($dt);
+ $now = time();
+ $diff = $now - $t;
+
+ if ($now < $t) { // that shouldn't happen!
+ return common_exact_date($dt);
+ } else if ($diff < 60) {
+ return _('a few seconds ago');
+ } else if ($diff < 92) {
+ return _('about a minute ago');
+ } else if ($diff < 3300) {
+ return sprintf(_('about %d minutes ago'), round($diff/60));
+ } else if ($diff < 5400) {
+ return _('about an hour ago');
+ } else if ($diff < 22 * 3600) {
+ return sprintf(_('about %d hours ago'), round($diff/3600));
+ } else if ($diff < 37 * 3600) {
+ return _('about a day ago');
+ } else if ($diff < 24 * 24 * 3600) {
+ return sprintf(_('about %d days ago'), round($diff/(24*3600)));
+ } else if ($diff < 46 * 24 * 3600) {
+ return _('about a month ago');
+ } else if ($diff < 330 * 24 * 3600) {
+ return sprintf(_('about %d months ago'), round($diff/(30*24*3600)));
+ } else if ($diff < 480 * 24 * 3600) {
+ return _('about a year ago');
+ } else {
+ return common_exact_date($dt);
+ }
+}
+
+function common_exact_date($dt)
+{
+ static $_utc;
+ static $_siteTz;
+
+ if (!$_utc) {
+ $_utc = new DateTimeZone('UTC');
+ $_siteTz = new DateTimeZone(common_timezone());
+ }
+
+ $dateStr = date('d F Y H:i:s', strtotime($dt));
+ $d = new DateTime($dateStr, $_utc);
+ $d->setTimezone($_siteTz);
+ return $d->format(DATE_RFC850);
+}
+
+function common_date_w3dtf($dt)
+{
+ $dateStr = date('d F Y H:i:s', strtotime($dt));
+ $d = new DateTime($dateStr, new DateTimeZone('UTC'));
+ $d->setTimezone(new DateTimeZone(common_timezone()));
+ return $d->format(DATE_W3C);
+}
+
+function common_date_rfc2822($dt)
+{
+ $dateStr = date('d F Y H:i:s', strtotime($dt));
+ $d = new DateTime($dateStr, new DateTimeZone('UTC'));
+ $d->setTimezone(new DateTimeZone(common_timezone()));
+ return $d->format('r');
+}
+
+function common_date_iso8601($dt)
+{
+ $dateStr = date('d F Y H:i:s', strtotime($dt));
+ $d = new DateTime($dateStr, new DateTimeZone('UTC'));
+ $d->setTimezone(new DateTimeZone(common_timezone()));
+ return $d->format('c');
+}
+
+function common_sql_now()
+{
+ return strftime('%Y-%m-%d %H:%M:%S', time());
+}
+
+function common_redirect($url, $code=307)
+{
+ static $status = array(301 => "Moved Permanently",
+ 302 => "Found",
+ 303 => "See Other",
+ 307 => "Temporary Redirect");
+ header("Status: ${code} $status[$code]");
+ header("Location: $url");
+
+ common_start_xml('a',
+ '-//W3C//DTD XHTML 1.0 Strict//EN',
+ 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd');
+ common_element('a', array('href' => $url), $url);
+ common_end_xml();
+ exit;
+}
+
+function common_save_replies($notice)
+{
+ // Alternative reply format
+ $tname = false;
+ if (preg_match('/^T ([A-Z0-9]{1,64}) /', $notice->content, $match)) {
+ $tname = $match[1];
+ }
+ // extract all @messages
+ $cnt = preg_match_all('/(?:^|\s)@([a-z0-9]{1,64})/', $notice->content, $match);
+
+ $names = array();
+
+ if ($cnt || $tname) {
+ // XXX: is there another way to make an array copy?
+ $names = ($tname) ? array_unique(array_merge(array(strtolower($tname)), $match[1])) : array_unique($match[1]);
+ }
+
+ $sender = Profile::staticGet($notice->profile_id);
+
+ $replied = array();
+
+ // store replied only for first @ (what user/notice what the reply directed,
+ // we assume first @ is it)
+
+ for ($i=0; $i<count($names); $i++) {
+ $nickname = $names[$i];
+ $recipient = common_relative_profile($sender, $nickname, $notice->created);
+ if (!$recipient) {
+ continue;
+ }
+ if ($i == 0 && ($recipient->id != $sender->id) && !$notice->reply_to) { // Don't save reply to self
+ $reply_for = $recipient;
+ $recipient_notice = $reply_for->getCurrentNotice();
+ if ($recipient_notice) {
+ $orig = clone($notice);
+ $notice->reply_to = $recipient_notice->id;
+ $notice->update($orig);
+ }
+ }
+ // Don't save replies from blocked profile to local user
+ $recipient_user = User::staticGet('id', $recipient->id);
+ if ($recipient_user && $recipient_user->hasBlocked($sender)) {
+ continue;
+ }
+ $reply = new Reply();
+ $reply->notice_id = $notice->id;
+ $reply->profile_id = $recipient->id;
+ $id = $reply->insert();
+ if (!$id) {
+ $last_error = &PEAR::getStaticProperty('DB_DataObject','lastError');
+ common_log(LOG_ERR, 'DB error inserting reply: ' . $last_error->message);
+ common_server_error(sprintf(_('DB error inserting reply: %s'), $last_error->message));
+ return;
+ } else {
+ $replied[$recipient->id] = 1;
+ }
+ }
+
+ // Hash format replies, too
+ $cnt = preg_match_all('/(?:^|\s)@#([a-z0-9]{1,64})/', $notice->content, $match);
+ if ($cnt) {
+ foreach ($match[1] as $tag) {
+ $tagged = Profile_tag::getTagged($sender->id, $tag);
+ foreach ($tagged as $t) {
+ if (!$replied[$t->id]) {
+ // Don't save replies from blocked profile to local user
+ $t_user = User::staticGet('id', $t->id);
+ if ($t_user && $t_user->hasBlocked($sender)) {
+ continue;
+ }
+ $reply = new Reply();
+ $reply->notice_id = $notice->id;
+ $reply->profile_id = $t->id;
+ $id = $reply->insert();
+ if (!$id) {
+ common_log_db_error($reply, 'INSERT', __FILE__);
+ return;
+ }
+ }
+ }
+ }
+ }
+}
+
+function common_broadcast_notice($notice, $remote=false)
+{
+
+ // Check to see if notice should go to Twitter
+ $flink = Foreign_link::getByUserID($notice->profile_id, 1); // 1 == Twitter
+ if (($flink->noticesync & FOREIGN_NOTICE_SEND) == FOREIGN_NOTICE_SEND) {
+
+ // If it's not a Twitter-style reply, or if the user WANTS to send replies...
+
+ if (!preg_match('/^@[a-zA-Z0-9_]{1,15}\b/u', $notice->content) ||
+ (($flink->noticesync & FOREIGN_NOTICE_SEND_REPLY) == FOREIGN_NOTICE_SEND_REPLY)) {
+
+ $result = common_twitter_broadcast($notice, $flink);
+
+ if (!$result) {
+ common_debug('Unable to send notice: ' . $notice->id . ' to Twitter.', __FILE__);
+ }
+ }
+ }
+
+ if (common_config('queue', 'enabled')) {
+ // Do it later!
+ return common_enqueue_notice($notice);
+ } else {
+ return common_real_broadcast($notice, $remote);
+ }
+}
+
+function common_twitter_broadcast($notice, $flink)
+{
+ global $config;
+ $success = true;
+ $fuser = $flink->getForeignUser();
+ $twitter_user = $fuser->nickname;
+ $twitter_password = $flink->credentials;
+ $uri = 'http://www.twitter.com/statuses/update.json';
+
+ // XXX: Hack to get around PHP cURL's use of @ being a a meta character
+ $statustxt = preg_replace('/^@/', ' @', $notice->content);
+
+ $options = array(
+ CURLOPT_USERPWD => "$twitter_user:$twitter_password",
+ CURLOPT_POST => true,
+ CURLOPT_POSTFIELDS => array(
+ 'status' => $statustxt,
+ 'source' => $config['integration']['source']
+ ),
+ CURLOPT_RETURNTRANSFER => true,
+ CURLOPT_FAILONERROR => true,
+ CURLOPT_HEADER => false,
+ CURLOPT_FOLLOWLOCATION => true,
+ CURLOPT_USERAGENT => "Laconica",
+ CURLOPT_CONNECTTIMEOUT => 120, // XXX: Scary!!!! How long should this be?
+ CURLOPT_TIMEOUT => 120,
+
+ # Twitter is strict about accepting invalid "Expect" headers
+ CURLOPT_HTTPHEADER => array('Expect:')
+ );
+
+ $ch = curl_init($uri);
+ curl_setopt_array($ch, $options);
+ $data = curl_exec($ch);
+ $errmsg = curl_error($ch);
+
+ if ($errmsg) {
+ common_debug("cURL error: $errmsg - trying to send notice for $twitter_user.",
+ __FILE__);
+ $success = false;
+ }
+
+ curl_close($ch);
+
+ if (!$data) {
+ common_debug("No data returned by Twitter's API trying to send update for $twitter_user",
+ __FILE__);
+ $success = false;
+ }
+
+ // Twitter should return a status
+ $status = json_decode($data);
+
+ if (!$status->id) {
+ common_debug("Unexpected data returned by Twitter API trying to send update for $twitter_user",
+ __FILE__);
+ $success = false;
+ }
+
+ return $success;
+}
+
+// Stick the notice on the queue
+
+function common_enqueue_notice($notice)
+{
+ foreach (array('jabber', 'omb', 'sms', 'public') as $transport) {
+ $qi = new Queue_item();
+ $qi->notice_id = $notice->id;
+ $qi->transport = $transport;
+ $qi->created = $notice->created;