From 047038959c068364f2efa030ba63571a492b9cda Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 28 May 2009 17:37:17 -0400 Subject: [PATCH 01/24] Add any.io to sources --- db/notice_source.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/db/notice_source.sql b/db/notice_source.sql index ac73d3d13b..b1309acd64 100644 --- a/db/notice_source.sql +++ b/db/notice_source.sql @@ -3,6 +3,7 @@ INSERT INTO notice_source VALUES ('adium', 'Adium', 'http://www.adiumx.com/', now()), ('AgentSolo.com','AgentSolo.com','http://www.agentsolo.com/', now()), + ('anyio', 'Any.IO', 'http://any.io/', now()), ('betwittered','BeTwittered','http://www.32hours.com/betwitteredinfo/', now()), ('bti','bti','http://gregkh.github.com/bti/', now()), ('cliqset', 'Cliqset', 'http://www.cliqset.com/', now()), From 3532cd0490a70b54a92108549de6042459fd8469 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 28 May 2009 18:19:22 -0400 Subject: [PATCH 02/24] Only enqueue inbox-dependent transports after inboxes have been filled --- classes/Notice.php | 2 +- lib/util.php | 54 +++++++++++++++++++++++------------ scripts/inboxqueuehandler.php | 10 ++++++- 3 files changed, 46 insertions(+), 20 deletions(-) diff --git a/classes/Notice.php b/classes/Notice.php index 771a4e715f..8dd14b3b73 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -195,12 +195,12 @@ class Notice extends Memcached_DataObject $notice->saveReplies(); $notice->saveTags(); - $notice->saveGroups(); if (common_config('queue', 'enabled')) { $notice->addToAuthorInbox(); } else { $notice->addToInboxes(); + $notice->saveGroups(); } $notice->query('COMMIT'); diff --git a/lib/util.php b/lib/util.php index f862d7fcc2..214c332799 100644 --- a/lib/util.php +++ b/lib/util.php @@ -879,7 +879,27 @@ function common_broadcast_notice($notice, $remote=false) function common_enqueue_notice($notice) { - $transports = array('omb', 'sms', 'twitter', 'facebook', 'ping'); + $transports = array('twitter', 'facebook', 'ping'); + + // If inboxes are enabled, wait till inboxes are filled + // before doing inbox-dependent broadcasts + + if (common_config('inboxes', 'enabled') === true || + common_config('inboxes', 'enabled') === 'transitional') { + $transports[] = 'inbox'; + } else { + $transports = array_merge($transports, common_post_inbox_transports()); + } + + foreach ($transports as $transport) { + common_enqueue_notice_transport($notice, $transport); + } + return $result; +} + +function common_post_inbox_transports() +{ + $transports = array('omb', 'sms'); if (common_config('xmpp', 'enabled')) { $transports = array_merge($transports, array('jabber', 'public')); @@ -890,25 +910,23 @@ function common_enqueue_notice($notice) $transports[] = 'memcache'; } - if (common_config('inboxes', 'enabled') === true || - common_config('inboxes', 'enabled') === 'transitional') { - $transports[] = 'inbox'; - } + return $transports; +} - foreach ($transports as $transport) { - $qi = new Queue_item(); - $qi->notice_id = $notice->id; - $qi->transport = $transport; - $qi->created = $notice->created; - $result = $qi->insert(); - if (!$result) { - $last_error = &PEAR::getStaticProperty('DB_DataObject','lastError'); - common_log(LOG_ERR, 'DB error inserting queue item: ' . $last_error->message); - return false; - } - common_log(LOG_DEBUG, 'complete queueing notice ID = ' . $notice->id . ' for ' . $transport); +function common_enqueue_notice_transport($notice, $transport) +{ + $qi = new Queue_item(); + $qi->notice_id = $notice->id; + $qi->transport = $transport; + $qi->created = $notice->created; + $result = $qi->insert(); + if (!$result) { + $last_error = &PEAR::getStaticProperty('DB_DataObject','lastError'); + common_log(LOG_ERR, 'DB error inserting queue item: ' . $last_error->message); + throw new ServerException('DB error inserting queue item: ' . $last_error->message); } - return $result; + common_log(LOG_DEBUG, 'complete queueing notice ID = ' . $notice->id . ' for ' . $transport); + return true; } function common_real_broadcast($notice, $remote=false) diff --git a/scripts/inboxqueuehandler.php b/scripts/inboxqueuehandler.php index 73d31e8542..c7aab4fe16 100755 --- a/scripts/inboxqueuehandler.php +++ b/scripts/inboxqueuehandler.php @@ -41,7 +41,7 @@ class InboxQueueHandler extends QueueHandler } function start() { - $this->log(LOG_INFO, "INITIALIZE"); + $this->log(LOG_INFO, "Initialize inbox queue handler"); return true; } @@ -49,11 +49,19 @@ class InboxQueueHandler extends QueueHandler { $this->log(LOG_INFO, "Distributing notice to inboxes for $notice->id"); $notice->addToInboxes(); + $notice->saveGroups(); $notice->blowSubsCache(); + $transports = common_post_inbox_transports(); + + foreach ($transports as $transport) { + common_enqueue_notice_transport($notice, $transport); + } + return true; } function finish() { + $this->log(LOG_INFO, "Terminating inbox queue handler"); } } From 5e53a97a41038151959c0280d988c609c0834aa2 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 28 May 2009 16:18:58 -0700 Subject: [PATCH 03/24] Warning log msg when http basic auth fails --- actions/api.php | 1 + 1 file changed, 1 insertion(+) diff --git a/actions/api.php b/actions/api.php index 8762b4bcd3..b25ba99f30 100644 --- a/actions/api.php +++ b/actions/api.php @@ -67,6 +67,7 @@ class ApiAction extends Action $this->process_command(); } else { # basic authentication failed + common_log(LOG_WARNING, "Failed API auth attempt, nickname: $nickname."); $this->show_basic_auth_error(); } } From 6885f082ea4191702b525bd5ad693baa13de8879 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 28 May 2009 17:51:45 -0700 Subject: [PATCH 04/24] Added Afficheur to notice sources --- db/notice_source.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/db/notice_source.sql b/db/notice_source.sql index b1309acd64..cf4bd3db44 100644 --- a/db/notice_source.sql +++ b/db/notice_source.sql @@ -2,6 +2,7 @@ INSERT INTO notice_source (code, name, url, created) VALUES ('adium', 'Adium', 'http://www.adiumx.com/', now()), + ('Afficheur', 'Afficheur', 'http://afficheur.sourceforge.jp/', now()), ('AgentSolo.com','AgentSolo.com','http://www.agentsolo.com/', now()), ('anyio', 'Any.IO', 'http://any.io/', now()), ('betwittered','BeTwittered','http://www.32hours.com/betwitteredinfo/', now()), From f66e996073b296ecbcaa76ac2fdb2378508bc2ac Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 29 May 2009 16:28:39 -0400 Subject: [PATCH 05/24] Update version number to 0.7.4 Updated the version number to 0.7.4, added the new song title, and documented the changes since 0.7.3. --- README | 60 ++++++++++++++++++++++++++------------------------ lib/common.php | 2 +- 2 files changed, 32 insertions(+), 30 deletions(-) diff --git a/README b/README index 4649eb79ce..769c416d32 100644 --- a/README +++ b/README @@ -2,8 +2,8 @@ README ------ -Laconica 0.7.3 ("You Are The Everything") -7 April 2009 +Laconica 0.7.4 ("Can't Get There From Here") +29 May 2009 This is the README file for Laconica, the Open Source microblogging platform. It includes installation instructions, descriptions of @@ -71,29 +71,29 @@ for additional terms. New this version ================ -This is a minor bug-fix and feature release since version 0.7.2.1, -released Mar 11 2009. Notable changes this version: +This is a minor bug-fix and feature release since version 0.7.3, +released Apr 4 2009. Notable changes this version: -- A plugin to allow a templating language for customization -- A plugin for Piwik Analytics engine -- A bookmarklet for posting a notice about a Web page you're reading -- A welcome notice ('welcomebot') and default subscription for new users -- Support for SSL for some or all pages on the site -- Better handling of empty notice lists on many pages -- Major improvements to the Twitter friend-sync offline processing -- subscribers, subscriptions, groups are listed on the Personal page. -- "Invite" link restored to main menu -- Better memory handling in FOAF output -- Fix for SUP support (FriendFeed) -- Correct and intelligent redirect HTTP status codes -- Fix DB collations for search and sort -- Better H1s and Titles using user full names -- Fixes to make the linkback plugin operational -- Better indication that a notice is being published by Ajax (spinner) -- Better and unified Atom output -- Hiding "register" and "join now" messages when site is closed -- ping, twitter and facebook queuehandlers working better -- Updated RPM spec +- Improved handling of UTF-8 characters. The new code is *not* backwards + compatible by default; see "Upgrading" below for instructions on + converting existing databases to the correct character set. +- Unroll joins for large queries. This greatly enhanced database + performance -- up to 50x for some queries -- at the expense of making + an extra DB hit for some queries. +- Added an optional plugin to use WikiHashtags + (http://hashtags.wikia.com/) for the sidebar on hashtag pages. +- Optimized Twitter friend synchronization. +- Better error handling for Ajax posting of notices, including + HTTP errors and timeouts. +- Experimental Comet plugin -- supports the cometd and the Bayeux + protocol. Using this plugin, you can show "real time" updates on the + public and tag pages. However, server configuration is complex. +- If queues are enabled, update inboxes and memcached off-line. Speeds + up posting considerably. +- Correctly shorten links posted through XMPP. +- elements for pagination, supported by some browsers like Opera. +- Corrected date format in search API. +- Made the public XRDS file work correctly. Prerequisites ============= @@ -193,9 +193,9 @@ especially if you've previously installed PHP/MySQL packages. 1. Unpack the tarball you downloaded on your Web server. Usually a command like this will work: - tar zxf laconica-0.7.3.tar.gz + tar zxf laconica-0.7.4.tar.gz - ...which will make a laconica-0.7.3 subdirectory in your current + ...which will make a laconica-0.7.4 subdirectory in your current directory. (If you don't have shell access on your Web server, you may have to unpack the tarball on your local computer and FTP the files to the server.) @@ -203,7 +203,7 @@ especially if you've previously installed PHP/MySQL packages. 2. Move the tarball to a directory of your choosing in your Web root directory. Usually something like this will work: - mv laconica-0.7.3 /var/www/mublog + mv laconica-0.7.4 /var/www/mublog This will make your Laconica instance available in the mublog path of your server, like "http://example.net/mublog". "microblog" or @@ -700,7 +700,7 @@ with this situation. If you've been using Laconica 0.6, 0.5 or lower, or if you've been tracking the "git" version of the software, you will probably want to upgrade and keep your existing data. There is no automated upgrade -procedure in Laconica 0.7.3. Try these step-by-step instructions; read +procedure in Laconica 0.7.4. Try these step-by-step instructions; read to the end first before trying them. 0. Download Laconica and set up all the prerequisites as if you were @@ -1178,7 +1178,7 @@ repository (see below), and you get a compilation error ("unexpected T_STRING") in the browser, check to see that you don't have any conflicts in your code. -If you upgraded to Laconica 0.7.3 without reading the "Notice inboxes" +If you upgraded to Laconica 0.7.4 without reading the "Notice inboxes" section above, and all your users' 'Personal' tabs are empty, read the "Notice inboxes" section above. @@ -1269,6 +1269,8 @@ if anyone's been overlooked in error. * Ken Sedgwick * Brian Hendrickson * Tobias Diekershoff +* Dan Moore +* Fil Thanks also to the developers of our upstream library code and to the thousands of people who have tried out Identi.ca, installed Laconi.ca, diff --git a/lib/common.php b/lib/common.php index 8f95c23615..01d2c78eaa 100644 --- a/lib/common.php +++ b/lib/common.php @@ -19,7 +19,7 @@ if (!defined('LACONICA')) { exit(1); } -define('LACONICA_VERSION', '0.7.3'); +define('LACONICA_VERSION', '0.7.4'); define('AVATAR_PROFILE_SIZE', 96); define('AVATAR_STREAM_SIZE', 48); From eb76a3bbb36e1f73007cb9b602001ec14f6853c6 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 29 May 2009 16:32:55 -0700 Subject: [PATCH 06/24] Ticket #1567 - API: Change before_id parameter to max_id --- actions/twitapidirect_messages.php | 6 ++--- actions/twitapistatuses.php | 36 +++++++++++++----------------- classes/Fave.php | 6 ++--- classes/Notice_inbox.php | 10 ++++----- classes/Notice_tag.php | 6 ++--- classes/Reply.php | 10 ++++----- classes/User_group.php | 6 ++--- 7 files changed, 38 insertions(+), 42 deletions(-) diff --git a/actions/twitapidirect_messages.php b/actions/twitapidirect_messages.php index 7101db8df5..ab8f078106 100644 --- a/actions/twitapidirect_messages.php +++ b/actions/twitapidirect_messages.php @@ -43,7 +43,7 @@ class Twitapidirect_messagesAction extends TwitterapiAction $count = $this->arg('count'); $since = $this->arg('since'); $since_id = $this->arg('since_id'); - $before_id = $this->arg('before_id'); + $max_id = $this->arg('max_id'); $page = $this->arg('page'); @@ -74,8 +74,8 @@ class Twitapidirect_messagesAction extends TwitterapiAction $link = $server . $user->nickname . '/outbox'; } - if ($before_id) { - $message->whereAdd("id < $before_id"); + if ($max_id) { + $message->whereAdd("id < $max_id"); } if ($since_id) { diff --git a/actions/twitapistatuses.php b/actions/twitapistatuses.php index 3abeba3672..1fbde6639f 100644 --- a/actions/twitapistatuses.php +++ b/actions/twitapistatuses.php @@ -45,22 +45,21 @@ class TwitapistatusesAction extends TwitterapiAction $page = $this->arg('page'); $since_id = $this->arg('since_id'); - $before_id = $this->arg('before_id'); + $max_id = $this->arg('max_id'); - // NOTE: page, since_id, and before_id are extensions to Twitter API -- TB if (!$page) { $page = 1; } if (!$since_id) { $since_id = 0; } - if (!$before_id) { - $before_id = 0; + if (!$max_id) { + $max_id = 0; } $since = strtotime($this->arg('since')); - $notice = Notice::publicStream((($page-1)*$MAX_PUBSTATUSES), $MAX_PUBSTATUSES, $since_id, $before_id, $since); + $notice = Notice::publicStream((($page-1)*$MAX_PUBSTATUSES), $MAX_PUBSTATUSES, $since_id, $max_id, $since); if ($notice) { @@ -97,7 +96,7 @@ class TwitapistatusesAction extends TwitterapiAction $since_id = $this->arg('since_id'); $count = $this->arg('count'); $page = $this->arg('page'); - $before_id = $this->arg('before_id'); + $max_id = $this->arg('max_id'); if (!$page) { $page = 1; @@ -111,9 +110,8 @@ class TwitapistatusesAction extends TwitterapiAction $since_id = 0; } - // NOTE: before_id is an extension to Twitter API -- TB - if (!$before_id) { - $before_id = 0; + if (!$max_id) { + $max_id = 0; } $since = strtotime($this->arg('since')); @@ -133,7 +131,7 @@ class TwitapistatusesAction extends TwitterapiAction $link = common_local_url('all', array('nickname' => $user->nickname)); $subtitle = sprintf(_('Updates from %1$s and friends on %2$s!'), $user->nickname, $sitename); - $notice = $user->noticesWithFriends(($page-1)*20, $count, $since_id, $before_id, $since); + $notice = $user->noticesWithFriends(($page-1)*20, $count, $since_id, $max_id, $since); switch($apidata['content-type']) { case 'xml': @@ -184,7 +182,7 @@ class TwitapistatusesAction extends TwitterapiAction $since = $this->arg('since'); $since_id = $this->arg('since_id'); $page = $this->arg('page'); - $before_id = $this->arg('before_id'); + $max_id = $this->arg('max_id'); if (!$page) { $page = 1; @@ -198,9 +196,8 @@ class TwitapistatusesAction extends TwitterapiAction $since_id = 0; } - // NOTE: before_id is an extensions to Twitter API -- TB - if (!$before_id) { - $before_id = 0; + if (!$max_id) { + $max_id = 0; } $since = strtotime($this->arg('since')); @@ -220,7 +217,7 @@ class TwitapistatusesAction extends TwitterapiAction # XXX: since - $notice = $user->getNotices((($page-1)*20), $count, $since_id, $before_id, $since); + $notice = $user->getNotices((($page-1)*20), $count, $since_id, $max_id, $since); switch($apidata['content-type']) { case 'xml': @@ -353,7 +350,7 @@ class TwitapistatusesAction extends TwitterapiAction $count = $this->arg('count'); $page = $this->arg('page'); $since_id = $this->arg('since_id'); - $before_id = $this->arg('before_id'); + $max_id = $this->arg('max_id'); $user = $this->get_user($apidata['api_arg'], $apidata); $this->auth_user = $apidata['user']; @@ -380,15 +377,14 @@ class TwitapistatusesAction extends TwitterapiAction $since_id = 0; } - // NOTE: before_id is an extension to Twitter API -- TB - if (!$before_id) { - $before_id = 0; + if (!$max_id) { + $max_id = 0; } $since = strtotime($this->arg('since')); $notice = $user->getReplies((($page-1)*20), - $count, $since_id, $before_id, $since); + $count, $since_id, $max_id, $since); $notices = array(); while ($notice->fetch()) { diff --git a/classes/Fave.php b/classes/Fave.php index 915b4572ff..cdb4798567 100644 --- a/classes/Fave.php +++ b/classes/Fave.php @@ -46,7 +46,7 @@ class Fave extends Memcached_DataObject return $ids; } - function _streamDirect($user_id, $offset, $limit, $since_id, $before_id, $since) + function _streamDirect($user_id, $offset, $limit, $since_id, $max_id, $since) { $fav = new Fave(); @@ -59,8 +59,8 @@ class Fave extends Memcached_DataObject $fav->whereAdd('notice_id > ' . $since_id); } - if ($before_id != 0) { - $fav->whereAdd('notice_id < ' . $before_id); + if ($max_id != 0) { + $fav->whereAdd('notice_id < ' . $max_id); } if (!is_null($since)) { diff --git a/classes/Notice_inbox.php b/classes/Notice_inbox.php index dec14b0d18..65d7927b7d 100644 --- a/classes/Notice_inbox.php +++ b/classes/Notice_inbox.php @@ -43,15 +43,15 @@ class Notice_inbox extends Memcached_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE - function stream($user_id, $offset, $limit, $since_id, $before_id, $since) + function stream($user_id, $offset, $limit, $since_id, $max_id, $since) { return Notice::stream(array('Notice_inbox', '_streamDirect'), array($user_id), 'notice_inbox:by_user:'.$user_id, - $offset, $limit, $since_id, $before_id, $since); + $offset, $limit, $since_id, $max_id, $since); } - function _streamDirect($user_id, $offset, $limit, $since_id, $before_id, $since) + function _streamDirect($user_id, $offset, $limit, $since_id, $max_id, $since) { $inbox = new Notice_inbox(); @@ -61,8 +61,8 @@ class Notice_inbox extends Memcached_DataObject $inbox->whereAdd('notice_id > ' . $since_id); } - if ($before_id != 0) { - $inbox->whereAdd('notice_id < ' . $before_id); + if ($max_id != 0) { + $inbox->whereAdd('notice_id < ' . $max_id); } if (!is_null($since)) { diff --git a/classes/Notice_tag.php b/classes/Notice_tag.php index e5b7722430..758a665947 100644 --- a/classes/Notice_tag.php +++ b/classes/Notice_tag.php @@ -46,7 +46,7 @@ class Notice_tag extends Memcached_DataObject return Notice::getStreamByIds($ids); } - function _streamDirect($tag, $offset, $limit, $since_id, $before_id, $since) + function _streamDirect($tag, $offset, $limit, $since_id, $max_id, $since) { $nt = new Notice_tag(); @@ -59,8 +59,8 @@ class Notice_tag extends Memcached_DataObject $nt->whereAdd('notice_id > ' . $since_id); } - if ($before_id != 0) { - $nt->whereAdd('notice_id < ' . $before_id); + if ($max_id != 0) { + $nt->whereAdd('notice_id < ' . $max_id); } if (!is_null($since)) { diff --git a/classes/Reply.php b/classes/Reply.php index 4439053b44..49b1e05e51 100644 --- a/classes/Reply.php +++ b/classes/Reply.php @@ -22,16 +22,16 @@ class Reply extends Memcached_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE - function stream($user_id, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null) + function stream($user_id, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0, $since=null) { $ids = Notice::stream(array('Reply', '_streamDirect'), array($user_id), 'reply:stream:' . $user_id, - $offset, $limit, $since_id, $before_id, $since); + $offset, $limit, $since_id, $max_id, $since); return $ids; } - function _streamDirect($user_id, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null) + function _streamDirect($user_id, $offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0, $since=null) { $reply = new Reply(); $reply->profile_id = $user_id; @@ -40,8 +40,8 @@ class Reply extends Memcached_DataObject $reply->whereAdd('notice_id > ' . $since_id); } - if ($before_id != 0) { - $reply->whereAdd('notice_id < ' . $before_id); + if ($max_id != 0) { + $reply->whereAdd('notice_id < ' . $max_id); } if (!is_null($since)) { diff --git a/classes/User_group.php b/classes/User_group.php index 7cc31e7026..43591d6559 100755 --- a/classes/User_group.php +++ b/classes/User_group.php @@ -58,7 +58,7 @@ class User_group extends Memcached_DataObject return Notice::getStreamByIds($ids); } - function _streamDirect($offset, $limit, $since_id, $before_id, $since) + function _streamDirect($offset, $limit, $since_id, $max_id, $since) { $inbox = new Group_inbox(); @@ -71,8 +71,8 @@ class User_group extends Memcached_DataObject $inbox->whereAdd('notice_id > ' . $since_id); } - if ($before_id != 0) { - $inbox->whereAdd('notice_id < ' . $before_id); + if ($max_id != 0) { + $inbox->whereAdd('notice_id < ' . $max_id); } if (!is_null($since)) { From 425f9d703c5258920079b268c085b0c7112c3b70 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 29 May 2009 16:54:24 -0700 Subject: [PATCH 07/24] Ticket #1567 - Change max_id to return notices <= ID instead of < ID --- actions/twitapidirect_messages.php | 2 +- classes/Fave.php | 2 +- classes/Notice.php | 32 +++++++++++++++--------------- classes/Notice_inbox.php | 2 +- classes/Profile.php | 10 +++++----- classes/User_group.php | 2 +- 6 files changed, 25 insertions(+), 25 deletions(-) diff --git a/actions/twitapidirect_messages.php b/actions/twitapidirect_messages.php index ab8f078106..d2dbdb619b 100644 --- a/actions/twitapidirect_messages.php +++ b/actions/twitapidirect_messages.php @@ -75,7 +75,7 @@ class Twitapidirect_messagesAction extends TwitterapiAction } if ($max_id) { - $message->whereAdd("id < $max_id"); + $message->whereAdd("id <= $max_id"); } if ($since_id) { diff --git a/classes/Fave.php b/classes/Fave.php index cdb4798567..572334ce4f 100644 --- a/classes/Fave.php +++ b/classes/Fave.php @@ -60,7 +60,7 @@ class Fave extends Memcached_DataObject } if ($max_id != 0) { - $fav->whereAdd('notice_id < ' . $max_id); + $fav->whereAdd('notice_id <= ' . $max_id); } if (!is_null($since)) { diff --git a/classes/Notice.php b/classes/Notice.php index 8dd14b3b73..3f6c5cebbe 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -426,22 +426,22 @@ class Notice extends Memcached_DataObject # XXX: too many args; we need to move to named params or even a separate # class for notice streams - static function getStream($qry, $cachekey, $offset=0, $limit=20, $since_id=0, $before_id=0, $order=null, $since=null) { + static function getStream($qry, $cachekey, $offset=0, $limit=20, $since_id=0, $max_id=0, $order=null, $since=null) { if (common_config('memcached', 'enabled')) { - # Skip the cache if this is a since, since_id or before_id qry - if ($since_id > 0 || $before_id > 0 || $since) { - return Notice::getStreamDirect($qry, $offset, $limit, $since_id, $before_id, $order, $since); + # Skip the cache if this is a since, since_id or max_id qry + if ($since_id > 0 || $max_id > 0 || $since) { + return Notice::getStreamDirect($qry, $offset, $limit, $since_id, $max_id, $order, $since); } else { return Notice::getCachedStream($qry, $cachekey, $offset, $limit, $order); } } - return Notice::getStreamDirect($qry, $offset, $limit, $since_id, $before_id, $order, $since); + return Notice::getStreamDirect($qry, $offset, $limit, $since_id, $max_id, $order, $since); } - static function getStreamDirect($qry, $offset, $limit, $since_id, $before_id, $order, $since) { + static function getStreamDirect($qry, $offset, $limit, $since_id, $max_id, $order, $since) { $needAnd = false; $needWhere = true; @@ -463,7 +463,7 @@ class Notice extends Memcached_DataObject $qry .= ' notice.id > ' . $since_id; } - if ($before_id > 0) { + if ($max_id > 0) { if ($needWhere) { $qry .= ' WHERE '; @@ -472,7 +472,7 @@ class Notice extends Memcached_DataObject $qry .= ' AND '; } - $qry .= ' notice.id < ' . $before_id; + $qry .= ' notice.id <= ' . $max_id; } if ($since) { @@ -630,17 +630,17 @@ class Notice extends Memcached_DataObject } } - function publicStream($offset=0, $limit=20, $since_id=0, $before_id=0, $since=null) + function publicStream($offset=0, $limit=20, $since_id=0, $max_id=0, $since=null) { $ids = Notice::stream(array('Notice', '_publicStreamDirect'), array(), 'public', - $offset, $limit, $since_id, $before_id, $since); + $offset, $limit, $since_id, $max_id, $since); return Notice::getStreamByIds($ids); } - function _publicStreamDirect($offset=0, $limit=20, $since_id=0, $before_id=0, $since=null) + function _publicStreamDirect($offset=0, $limit=20, $since_id=0, $max_id=0, $since=null) { $notice = new Notice(); @@ -664,8 +664,8 @@ class Notice extends Memcached_DataObject $notice->whereAdd('id > ' . $since_id); } - if ($before_id != 0) { - $notice->whereAdd('id < ' . $before_id); + if ($max_id != 0) { + $notice->whereAdd('id <= ' . $max_id); } if (!is_null($since)) { @@ -998,15 +998,15 @@ class Notice extends Memcached_DataObject } } - function stream($fn, $args, $cachekey, $offset=0, $limit=20, $since_id=0, $before_id=0, $since=null) + function stream($fn, $args, $cachekey, $offset=0, $limit=20, $since_id=0, $max_id=0, $since=null) { $cache = common_memcache(); if (empty($cache) || - $since_id != 0 || $before_id != 0 || !is_null($since) || + $since_id != 0 || $max_id != 0 || !is_null($since) || ($offset + $limit) > NOTICE_CACHE_WINDOW) { return call_user_func_array($fn, array_merge($args, array($offset, $limit, $since_id, - $before_id, $since))); + $max_id, $since))); } $idkey = common_cache_key($cachekey); diff --git a/classes/Notice_inbox.php b/classes/Notice_inbox.php index 65d7927b7d..8a27e17478 100644 --- a/classes/Notice_inbox.php +++ b/classes/Notice_inbox.php @@ -62,7 +62,7 @@ class Notice_inbox extends Memcached_DataObject } if ($max_id != 0) { - $inbox->whereAdd('notice_id < ' . $max_id); + $inbox->whereAdd('notice_id <= ' . $max_id); } if (!is_null($since)) { diff --git a/classes/Profile.php b/classes/Profile.php index ae5641d79d..3d13cd46af 100644 --- a/classes/Profile.php +++ b/classes/Profile.php @@ -153,18 +153,18 @@ class Profile extends Memcached_DataObject return null; } - function getNotices($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0) + function getNotices($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0) { // XXX: I'm not sure this is going to be any faster. It probably isn't. $ids = Notice::stream(array($this, '_streamDirect'), array(), 'profile:notice_ids:' . $this->id, - $offset, $limit, $since_id, $before_id); + $offset, $limit, $since_id, $max_id); return Notice::getStreamByIds($ids); } - function _streamDirect($offset, $limit, $since_id, $before_id, $since) + function _streamDirect($offset, $limit, $since_id, $max_id, $since) { $notice = new Notice(); @@ -177,8 +177,8 @@ class Profile extends Memcached_DataObject $notice->whereAdd('id > ' . $since_id); } - if ($before_id != 0) { - $notice->whereAdd('id < ' . $before_id); + if ($max_id != 0) { + $notice->whereAdd('id <= ' . $max_id); } if (!is_null($since)) { diff --git a/classes/User_group.php b/classes/User_group.php index 43591d6559..a135015bac 100755 --- a/classes/User_group.php +++ b/classes/User_group.php @@ -72,7 +72,7 @@ class User_group extends Memcached_DataObject } if ($max_id != 0) { - $inbox->whereAdd('notice_id < ' . $max_id); + $inbox->whereAdd('notice_id <= ' . $max_id); } if (!is_null($since)) { From 78f8b91a13ee07ed3344fd6411a0829a16bef4b1 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 29 May 2009 19:23:53 -0700 Subject: [PATCH 08/24] Ticket #1568 - API should return full user objects --- actions/twitapiusers.php | 125 ++++++++++++--------------------------- lib/twitterapi.php | 81 +++++++++++++++++++++---- 2 files changed, 109 insertions(+), 97 deletions(-) diff --git a/actions/twitapiusers.php b/actions/twitapiusers.php index 1542cfb33e..b90bbfa985 100644 --- a/actions/twitapiusers.php +++ b/actions/twitapiusers.php @@ -25,110 +25,61 @@ class TwitapiusersAction extends TwitterapiAction { function show($args, $apidata) - { + { parent::handle($args); - if (!in_array($apidata['content-type'], array('xml', 'json'))) { + if (!in_array($apidata['content-type'], array('xml', 'json'))) { $this->clientError(_('API method not found!'), $code = 404); return; } - - $user = null; - $email = $this->arg('email'); - $user_id = $this->arg('user_id'); - if ($email) { - $user = User::staticGet('email', $email); - } elseif ($user_id) { - $user = $this->get_user($user_id); - } elseif (isset($apidata['api_arg'])) { - $user = $this->get_user($apidata['api_arg']); - } elseif (isset($apidata['user'])) { - $user = $apidata['user']; - } - - if (!$user) { - // XXX: Twitter returns a random(?) user instead of throwing and err! -- Zach - $this->client_error(_('Not found.'), 404, $apidata['content-type']); - return; - } + $user = null; + $email = $this->arg('email'); + $user_id = $this->arg('user_id'); - $profile = $user->getProfile(); + // XXX: email field deprecated in Twitter's API - if (!$profile) { - common_server_error(_('User has no profile.')); - return; - } + // XXX: Also: need to add screen_name param - $twitter_user = $this->twitter_user_array($profile, true); + if ($email) { + $user = User::staticGet('email', $email); + } elseif ($user_id) { + $user = $this->get_user($user_id); + } elseif (isset($apidata['api_arg'])) { + $user = $this->get_user($apidata['api_arg']); + } elseif (isset($apidata['user'])) { + $user = $apidata['user']; + } - // Add in extended user fields offered up by this method - $twitter_user['created_at'] = $this->date_twitter($profile->created); + if (!$user) { + $this->client_error(_('Not found.'), 404, $apidata['content-type']); + return; + } - $subbed = DB_DataObject::factory('subscription'); - $subbed->subscriber = $profile->id; - $subbed_count = (int) $subbed->count() - 1; + $profile = $user->getProfile(); - $notices = DB_DataObject::factory('notice'); - $notices->profile_id = $profile->id; - $notice_count = (int) $notices->count(); + if (!$profile) { + common_server_error(_('User has no profile.')); + return; + } - $twitter_user['friends_count'] = (is_int($subbed_count)) ? $subbed_count : 0; - $twitter_user['statuses_count'] = (is_int($notice_count)) ? $notice_count : 0; + $twitter_user = $this->twitter_user_array($profile, true); - // Other fields Twitter sends... - $twitter_user['profile_background_color'] = ''; - $twitter_user['profile_background_image_url'] = ''; - $twitter_user['profile_text_color'] = ''; - $twitter_user['profile_link_color'] = ''; - $twitter_user['profile_sidebar_fill_color'] = ''; - $twitter_user['profile_sidebar_border_color'] = ''; - $twitter_user['profile_background_tile'] = false; + if ($apidata['content-type'] == 'xml') { + $this->init_document('xml'); + $this->show_twitter_xml_user($twitter_user); + $this->end_document('xml'); + } elseif ($apidata['content-type'] == 'json') { + $this->init_document('json'); + $this->show_json_objects($twitter_user); + $this->end_document('json'); + } else { - $faves = DB_DataObject::factory('fave'); - $faves->user_id = $user->id; - $faves_count = (int) $faves->count(); - $twitter_user['favourites_count'] = $faves_count; - - $timezone = 'UTC'; - - if ($user->timezone) { - $timezone = $user->timezone; - } - - $t = new DateTime; - $t->setTimezone(new DateTimeZone($timezone)); - $twitter_user['utc_offset'] = $t->format('Z'); - $twitter_user['time_zone'] = $timezone; - - if (isset($apidata['user'])) { - - $twitter_user['following'] = $apidata['user']->isSubscribed($profile); - - // Notifications on? - $sub = Subscription::pkeyGet(array('subscriber' => - $apidata['user']->id, 'subscribed' => $profile->id)); - - if ($sub) { - $twitter_user['notifications'] = ($sub->jabber || $sub->sms); - } - } - - if ($apidata['content-type'] == 'xml') { - $this->init_document('xml'); - $this->show_twitter_xml_user($twitter_user); - $this->end_document('xml'); - } elseif ($apidata['content-type'] == 'json') { - $this->init_document('json'); - $this->show_json_objects($twitter_user); - $this->end_document('json'); - } else { - - // This is in case 'show' was called via /account/verify_credentials - // without a format (xml or json). + // This is in case 'show' was called via /account/verify_credentials + // without a format (xml or json). header('Content-Type: text/html; charset=utf-8'); print 'Authorized'; } - } + } } diff --git a/lib/twitterapi.php b/lib/twitterapi.php index caf8c07163..1d527b935f 100644 --- a/lib/twitterapi.php +++ b/lib/twitterapi.php @@ -54,7 +54,7 @@ class TwitterapiAction extends Action /** * Overrides XMLOutputter::element to write booleans as strings (true|false). * See that method's documentation for more info. - * + * * @param string $tag Element type or tagname * @param array $attrs Array of element attributes, as * key-value pairs @@ -70,24 +70,85 @@ class TwitterapiAction extends Action return parent::element($tag, $attrs, $content); } - + function twitter_user_array($profile, $get_notice=false) { - $twitter_user = array(); - $twitter_user['name'] = $profile->getBestName(); - $twitter_user['followers_count'] = $this->count_subscriptions($profile); - $twitter_user['screen_name'] = $profile->nickname; - $twitter_user['description'] = ($profile->bio) ? $profile->bio : null; - $twitter_user['location'] = ($profile->location) ? $profile->location : null; $twitter_user['id'] = intval($profile->id); + $twitter_user['name'] = $profile->getBestName(); + $twitter_user['screen_name'] = $profile->nickname; + $twitter_user['location'] = ($profile->location) ? $profile->location : null; + $twitter_user['description'] = ($profile->bio) ? $profile->bio : null; $avatar = $profile->getAvatar(AVATAR_STREAM_SIZE); + $twitter_user['profile_image_url'] = ($avatar) ? $avatar->displayUrl() : + Avatar::defaultImage(AVATAR_STREAM_SIZE); - $twitter_user['profile_image_url'] = ($avatar) ? $avatar->displayUrl() : Avatar::defaultImage(AVATAR_STREAM_SIZE); - $twitter_user['protected'] = false; # not supported by Laconica yet $twitter_user['url'] = ($profile->homepage) ? $profile->homepage : null; + $twitter_user['protected'] = false; # not supported by Laconica yet + $twitter_user['followers_count'] = $this->count_subscriptions($profile); + + // To be supported soon... + $twitter_user['profile_background_color'] = ''; + $twitter_user['profile_text_color'] = ''; + $twitter_user['profile_link_color'] = ''; + $twitter_user['profile_sidebar_fill_color'] = ''; + $twitter_user['profile_sidebar_border_color'] = ''; + + $subbed = DB_DataObject::factory('subscription'); + $subbed->subscriber = $profile->id; + $subbed_count = (int) $subbed->count() - 1; + $twitter_user['friends_count'] = (is_int($subbed_count)) ? $subbed_count : 0; + + $twitter_user['created_at'] = $this->date_twitter($profile->created); + + $faves = DB_DataObject::factory('fave'); + $faves->user_id = $user->id; + $faves_count = (int) $faves->count(); + $twitter_user['favourites_count'] = $faves_count; // British spelling! + + // Need to pull up the user for some of this + $user = User::staticGet($profile->id); + + $timezone = 'UTC'; + + if ($user->timezone) { + $timezone = $user->timezone; + } + + $t = new DateTime; + $t->setTimezone(new DateTimeZone($timezone)); + + $twitter_user['utc_offset'] = $t->format('Z'); + $twitter_user['time_zone'] = $timezone; + + // To be supported some day, perhaps + $twitter_user['profile_background_image_url'] = ''; + $twitter_user['profile_background_tile'] = false; + + $notices = DB_DataObject::factory('notice'); + $notices->profile_id = $profile->id; + $notice_count = (int) $notices->count(); + + $twitter_user['statuses_count'] = (is_int($notice_count)) ? $notice_count : 0; + + // Is the requesting user following this user? + $twitter_user['following'] = false; + $twitter_user['notifications'] = false; + + if (isset($apidata['user'])) { + + $twitter_user['following'] = $apidata['user']->isSubscribed($profile); + + // Notifications on? + $sub = Subscription::pkeyGet(array('subscriber' => + $apidata['user']->id, 'subscribed' => $profile->id)); + + if ($sub) { + $twitter_user['notifications'] = ($sub->jabber || $sub->sms); + } + } if ($get_notice) { $notice = $profile->getCurrentNotice(); From 791f5defaf07372de6453ac7903a9a32611b0284 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 29 May 2009 20:23:32 -0700 Subject: [PATCH 09/24] Ticket #1572 - Implement Twitter's account/rate_limit_status API method We don't have a rate limit (yet) but some clients check this method. This dummy implementation always says the auth user has 100 requests left. --- actions/twitapiaccount.php | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/actions/twitapiaccount.php b/actions/twitapiaccount.php index 68a18cb57b..8b956f897a 100644 --- a/actions/twitapiaccount.php +++ b/actions/twitapiaccount.php @@ -98,9 +98,31 @@ class TwitapiaccountAction extends TwitterapiAction $this->serverError(_('API method under construction.'), $code=501); } + // We don't have a rate limit, but some clients check this method. + // It always returns the same thing: 100 hit left. function rate_limit_status($args, $apidata) { parent::handle($args); - $this->serverError(_('API method under construction.'), $code=501); + + $type = $apidata['content-type']; + $this->init_document($type); + + if ($apidata['content-type'] == 'xml') { + $this->elementStart('hash'); + $this->element('remaining-hits', array('type' => 'integer'), 100); + $this->element('hourly-limit', array('type' => 'integer'), 100); + $this->element('reset-time', array('type' => 'datetime'), null); + $this->element('reset_time_in_seconds', array('type' => 'integer'), 0); + $this->elementEnd('hash'); + } elseif ($apidata['content-type'] == 'json') { + + $out = array('reset_time_in_seconds' => 0, + 'remaining_hits' => 100, + 'hourly_limit' => 100, + 'reset_time' => ''); + print json_encode($out); + } + + $this->end_document($type); } } From 78968a31a7459a3c564924754380b64655b46928 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 30 May 2009 00:49:14 -0400 Subject: [PATCH 10/24] check for since=0 in Notice::stream() --- classes/Notice.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes/Notice.php b/classes/Notice.php index 3f6c5cebbe..3a90d18b47 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -1003,7 +1003,7 @@ class Notice extends Memcached_DataObject $cache = common_memcache(); if (empty($cache) || - $since_id != 0 || $max_id != 0 || !is_null($since) || + $since_id != 0 || $max_id != 0 || (!is_null($since) && $since > 0) || ($offset + $limit) > NOTICE_CACHE_WINDOW) { return call_user_func_array($fn, array_merge($args, array($offset, $limit, $since_id, $max_id, $since))); From 79ede2afdb1479fff19f428a0ca57a9cd6ff2326 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 30 May 2009 01:30:10 -0400 Subject: [PATCH 11/24] add get2gnow --- db/notice_source.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/db/notice_source.sql b/db/notice_source.sql index cf4bd3db44..4c3dc2113d 100644 --- a/db/notice_source.sql +++ b/db/notice_source.sql @@ -13,6 +13,7 @@ VALUES ('eventbox','EventBox','http://thecosmicmachine.com/eventbox/ ', now()), ('Facebook','Facebook','http://apps.facebook.com/identica/', now()), ('feed2omb','feed2omb','http://projects.ciarang.com/p/feed2omb/', now()), + ('get2gnow', 'get2gnow', 'http://uberchicgeekchick.com/?projects=get2gnow', now()), ('gravity', 'Gravity', 'http://mobileways.de/gravity', now()), ('Gwibber','Gwibber','http://launchpad.net/gwibber', now()), ('HelloTxt','HelloTxt','http://hellotxt.com/', now()), From 7656277313e351bcab86b246bc5b13d8dcd65931 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 30 May 2009 03:02:26 -0400 Subject: [PATCH 12/24] remove debug code from replies --- classes/User.php | 1 - 1 file changed, 1 deletion(-) diff --git a/classes/User.php b/classes/User.php index b5ac7b2206..59451258ec 100644 --- a/classes/User.php +++ b/classes/User.php @@ -403,7 +403,6 @@ class User extends Memcached_DataObject function getReplies($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null) { $ids = Reply::stream($this->id, $offset, $limit, $since_id, $before_id, $since); - common_debug("Ids = " . implode(',', $ids)); return Notice::getStreamByIds($ids); } From 45c58c74d4d2c2c0a886ff7816f27aa9c6033652 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 30 May 2009 03:31:26 -0400 Subject: [PATCH 13/24] take debug code out of omb.php --- lib/omb.php | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/lib/omb.php b/lib/omb.php index e8e1acc413..40cb847dfa 100644 --- a/lib/omb.php +++ b/lib/omb.php @@ -159,13 +159,9 @@ function omb_post_notice($notice, $remote_profile, $subscription) function omb_post_notice_keys($notice, $postnoticeurl, $tk, $secret) { - - common_debug('Posting notice ' . $notice->id . ' to ' . $postnoticeurl, __FILE__); - $user = User::staticGet('id', $notice->profile_id); if (!$user) { - common_debug('Failed to get user for notice ' . $notice->id . ', profile = ' . $notice->profile_id, __FILE__); return false; } @@ -208,8 +204,6 @@ function omb_post_notice_keys($notice, $postnoticeurl, $tk, $secret) $req->to_postdata(), array('User-Agent: Laconica/' . LACONICA_VERSION)); - common_debug('Got HTTP result "'.print_r($result,true).'"', __FILE__); - if ($result->status == 403) { # not authorized, don't send again common_debug('403 result, deleting subscription', __FILE__); # FIXME: figure out how to delete this @@ -286,14 +280,10 @@ function omb_update_profile($profile, $remote_profile, $subscription) $fetcher = Auth_Yadis_Yadis::getHTTPFetcher(); - common_debug('request URL = '.$req->get_normalized_http_url(), __FILE__); - common_debug('postdata = '.$req->to_postdata(), __FILE__); $result = $fetcher->post($req->get_normalized_http_url(), $req->to_postdata(), array('User-Agent: Laconica/' . LACONICA_VERSION)); - common_debug('Got HTTP result "'.print_r($result,true).'"', __FILE__); - if (empty($result) || !$result) { common_debug("Unable to contact " . $req->get_normalized_http_url()); } else if ($result->status == 403) { # not authorized, don't send again From 76ee1fd5daa6ab1999224d8e93df1b7116f24c36 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 30 May 2009 04:40:47 -0400 Subject: [PATCH 14/24] Removing inbox and memcached daemon handling --- classes/Notice.php | 54 ++-------------------- lib/util.php | 13 +----- scripts/getvaliddaemons.php | 5 -- scripts/inboxqueuehandler.php | 77 ------------------------------- scripts/memcachedqueuehandler.php | 70 ---------------------------- scripts/stopdaemons.sh | 3 +- 6 files changed, 6 insertions(+), 216 deletions(-) delete mode 100755 scripts/inboxqueuehandler.php delete mode 100755 scripts/memcachedqueuehandler.php diff --git a/classes/Notice.php b/classes/Notice.php index 3a90d18b47..b4c86ebeb5 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -196,12 +196,8 @@ class Notice extends Memcached_DataObject $notice->saveReplies(); $notice->saveTags(); - if (common_config('queue', 'enabled')) { - $notice->addToAuthorInbox(); - } else { - $notice->addToInboxes(); - $notice->saveGroups(); - } + $notice->addToInboxes(); + $notice->saveGroups(); $notice->query('COMMIT'); @@ -211,13 +207,7 @@ class Notice extends Memcached_DataObject # Clear the cache for subscribed users, so they'll update at next request # XXX: someone clever could prepend instead of clearing the cache - if (common_config('memcached', 'enabled')) { - if (common_config('queue', 'enabled')) { - $notice->blowAuthorCaches(); - } else { - $notice->blowCaches(); - } - } + $notice->blowCaches(); return $notice; } @@ -280,17 +270,6 @@ class Notice extends Memcached_DataObject $this->blowGroupCache($blowLast); } - function blowAuthorCaches($blowLast=false) - { - // Clear the user's cache - $cache = common_memcache(); - if (!empty($cache)) { - $cache->delete(common_cache_key('notice_inbox:by_user:'.$this->profile_id)); - } - $this->blowNoticeCache($blowLast); - $this->blowPublicCache($blowLast); - } - function blowGroupCache($blowLast=false) { $cache = common_memcache(); @@ -709,33 +688,6 @@ class Notice extends Memcached_DataObject return; } - function addToAuthorInbox() - { - $enabled = common_config('inboxes', 'enabled'); - - if ($enabled === true || $enabled === 'transitional') { - $user = User::staticGet('id', $this->profile_id); - if (empty($user)) { - return; - } - $inbox = new Notice_inbox(); - $UT = common_config('db','type')=='pgsql'?'"user"':'user'; - $qry = 'INSERT INTO notice_inbox (user_id, notice_id, created) ' . - "SELECT $UT.id, " . $this->id . ", '" . $this->created . "' " . - "FROM $UT " . - "WHERE $UT.id = " . $this->profile_id . ' ' . - 'AND NOT EXISTS (SELECT user_id, notice_id ' . - 'FROM notice_inbox ' . - "WHERE user_id = " . $this->profile_id . ' '. - 'AND notice_id = ' . $this->id . ' )'; - if ($enabled === 'transitional') { - $qry .= " AND $UT.inboxed = 1"; - } - $inbox->query($qry); - } - return; - } - function saveGroups() { $enabled = common_config('inboxes', 'enabled'); diff --git a/lib/util.php b/lib/util.php index 214c332799..22308f432c 100644 --- a/lib/util.php +++ b/lib/util.php @@ -884,16 +884,12 @@ function common_enqueue_notice($notice) // If inboxes are enabled, wait till inboxes are filled // before doing inbox-dependent broadcasts - if (common_config('inboxes', 'enabled') === true || - common_config('inboxes', 'enabled') === 'transitional') { - $transports[] = 'inbox'; - } else { - $transports = array_merge($transports, common_post_inbox_transports()); - } + $transports = array_merge($transports, common_post_inbox_transports()); foreach ($transports as $transport) { common_enqueue_notice_transport($notice, $transport); } + return $result; } @@ -905,11 +901,6 @@ function common_post_inbox_transports() $transports = array_merge($transports, array('jabber', 'public')); } - if (common_config('memcached', 'enabled')) { - // Note: limited to 8 chars - $transports[] = 'memcache'; - } - return $transports; } diff --git a/scripts/getvaliddaemons.php b/scripts/getvaliddaemons.php index 482e63af70..0996ba9f41 100755 --- a/scripts/getvaliddaemons.php +++ b/scripts/getvaliddaemons.php @@ -25,7 +25,6 @@ * daemon names. */ - # Abort if called from a web server if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { print "This script must be run from the command line\n"; @@ -41,12 +40,8 @@ if(common_config('xmpp','enabled')) { echo "xmppdaemon.php jabberqueuehandler.php publicqueuehandler.php "; echo "xmppconfirmhandler.php "; } -if(common_config('memcached','enabled')) { - echo "memcachedqueuehandler.php "; -} echo "ombqueuehandler.php "; echo "twitterqueuehandler.php "; echo "facebookqueuehandler.php "; echo "pingqueuehandler.php "; -echo "inboxqueuehandler.php "; echo "smsqueuehandler.php "; diff --git a/scripts/inboxqueuehandler.php b/scripts/inboxqueuehandler.php deleted file mode 100755 index c7aab4fe16..0000000000 --- a/scripts/inboxqueuehandler.php +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env php -. - */ - -// Abort if called from a web server - -if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { - print "This script must be run from the command line\n"; - exit(); -} - -define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -define('LACONICA', true); - -require_once(INSTALLDIR . '/lib/common.php'); -require_once(INSTALLDIR . '/lib/queuehandler.php'); - -set_error_handler('common_error_handler'); - -class InboxQueueHandler extends QueueHandler -{ - function transport() - { - return 'inbox'; - } - - function start() { - $this->log(LOG_INFO, "Initialize inbox queue handler"); - return true; - } - - function handle_notice($notice) - { - $this->log(LOG_INFO, "Distributing notice to inboxes for $notice->id"); - $notice->addToInboxes(); - $notice->saveGroups(); - $notice->blowSubsCache(); - $transports = common_post_inbox_transports(); - - foreach ($transports as $transport) { - common_enqueue_notice_transport($notice, $transport); - } - - return true; - } - - function finish() { - $this->log(LOG_INFO, "Terminating inbox queue handler"); - } -} - -ini_set("max_execution_time", "0"); -ini_set("max_input_time", "0"); -set_time_limit(0); -mb_internal_encoding('UTF-8'); - -$id = ($argc > 1) ? $argv[1] : null; - -$handler = new InboxQueueHandler($id); - -$handler->runOnce(); diff --git a/scripts/memcachedqueuehandler.php b/scripts/memcachedqueuehandler.php deleted file mode 100755 index 185b781f75..0000000000 --- a/scripts/memcachedqueuehandler.php +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env php -. - */ - -// Abort if called from a web server - -if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) { - print "This script must be run from the command line\n"; - exit(); -} - -define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); -define('LACONICA', true); - -require_once(INSTALLDIR . '/lib/common.php'); -require_once(INSTALLDIR . '/lib/queuehandler.php'); - -set_error_handler('common_error_handler'); - -class MemcachedQueueHandler extends QueueHandler -{ - function transport() - { - return 'memcache'; - } - - function start() { - $this->log(LOG_INFO, "INITIALIZE"); - return true; - } - - function handle_notice($notice) - { - // XXX: fork here - $this->log(LOG_INFO, "Blowing memcached for $notice->id"); - $notice->blowCaches(); - return true; - } - - function finish() { - } - -} - -ini_set("max_execution_time", "0"); -ini_set("max_input_time", "0"); -set_time_limit(0); -mb_internal_encoding('UTF-8'); - -$id = ($argc > 1) ? $argv[1] : null; - -$handler = new MemcachedQueueHandler($id); - -$handler->runOnce(); diff --git a/scripts/stopdaemons.sh b/scripts/stopdaemons.sh index f6d71eddfb..2134b4ab00 100755 --- a/scripts/stopdaemons.sh +++ b/scripts/stopdaemons.sh @@ -24,8 +24,7 @@ SDIR=`dirname $0` DIR=`php $SDIR/getpiddir.php` for f in jabberhandler ombhandler publichandler smshandler pinghandler \ - xmppconfirmhandler xmppdaemon twitterhandler facebookhandler \ - memcachehandler inboxhandler; do + xmppconfirmhandler xmppdaemon twitterhandler facebookhandler; do FILES="$DIR/$f.*.pid" for ff in "$FILES" ; do From 7b1a72da307694bee40a2278482003855a2a2ab1 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 30 May 2009 11:52:35 -0400 Subject: [PATCH 15/24] take a max and min argument for fixup_utf8 --- scripts/fixup_utf8.php | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/scripts/fixup_utf8.php b/scripts/fixup_utf8.php index e5021ff343..67f9c46236 100644 --- a/scripts/fixup_utf8.php +++ b/scripts/fixup_utf8.php @@ -35,7 +35,7 @@ define('LACONICA', true); require_once(INSTALLDIR . '/lib/common.php'); require_once('DB.php'); -function fixup_utf8($id) { +function fixup_utf8($max_id, $min_id) { $dbl = doConnect('latin1'); @@ -61,8 +61,12 @@ function fixup_utf8($id) { $sql = 'SELECT id, content, rendered FROM notice ' . 'WHERE LENGTH(content) != CHAR_LENGTH(content)'; - if (!empty($id)) { - $sql .= ' AND id < ' . $id; + if (!empty($max_id)) { + $sql .= ' AND id <= ' . $max_id; + } + + if (!empty($min_id)) { + $sql .= ' AND id >= ' . $min_id; } $sql .= ' ORDER BY id DESC'; @@ -136,6 +140,7 @@ function doConnect($charset) return $db; } -$id = ($argc > 1) ? $argv[1] : null; +$max_id = ($argc > 1) ? $argv[1] : null; +$min_id = ($argc > 2) ? $argv[2] : null; -fixup_utf8($id); +fixup_utf8($max_id, $min_id); From a262f83210f6a405bfe79148b52387d1dbdd9a5d Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 30 May 2009 12:20:42 -0400 Subject: [PATCH 16/24] use mysqli_set_charset instead of set names --- scripts/fixup_utf8.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/scripts/fixup_utf8.php b/scripts/fixup_utf8.php index 67f9c46236..925da24844 100644 --- a/scripts/fixup_utf8.php +++ b/scripts/fixup_utf8.php @@ -121,10 +121,14 @@ function doConnect($charset) return NULL; } - $result = $db->query("SET NAMES $charset"); +// $result = $db->query("SET NAMES $charset"); - if (PEAR::isError($result)) { - echo "ERROR: " . $result->getMessage() . "\n"; + $conn = $db->connection; + + $succ = mysqli_set_charset($conn, $charset); + + if (!$succ) { + echo "ERROR: couldn't set charset\n"; $db->disconnect(); return NULL; } From 9e16b7d89b101d8dfebdb8bf22ea56e9b8731bdd Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 30 May 2009 13:59:57 -0400 Subject: [PATCH 17/24] Use mysql_set_charset for connection instead of SET NAMES PHP doesn't get the info about the charset of the connection if you use SET NAMES. So, we use the appropriate PHP function instead. --- classes/Memcached_DataObject.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/classes/Memcached_DataObject.php b/classes/Memcached_DataObject.php index 52ad4100fc..33ac70dd04 100644 --- a/classes/Memcached_DataObject.php +++ b/classes/Memcached_DataObject.php @@ -239,8 +239,14 @@ class Memcached_DataObject extends DB_DataObject $result = parent::_connect(); if (!$exists) { $DB = &$_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5]; - if (common_config('db', 'utf8')) { - $DB->query('SET NAMES "utf8"'); + if (common_config('db', 'type') == 'mysql' && + common_config('db', 'utf8')) { + $conn = $DB->connection; + if ($DB instanceof DB_mysqli) { + mysqli_set_charset($conn, 'utf8'); + } else if ($DB instanceof DB_mysql) { + mysql_set_charset('utf8', $conn); + } } } return $result; From da0d2a9745ea072cd261990e152d08198331a415 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 30 May 2009 20:58:29 -0400 Subject: [PATCH 18/24] make fixup_utf8.php handle profiles and groups too --- scripts/fixup_utf8.php | 335 ++++++++++++++++++++++++++++++----------- 1 file changed, 246 insertions(+), 89 deletions(-) diff --git a/scripts/fixup_utf8.php b/scripts/fixup_utf8.php index 925da24844..2046d2b770 100644 --- a/scripts/fixup_utf8.php +++ b/scripts/fixup_utf8.php @@ -35,116 +35,273 @@ define('LACONICA', true); require_once(INSTALLDIR . '/lib/common.php'); require_once('DB.php'); -function fixup_utf8($max_id, $min_id) { +class UTF8FixerUpper +{ + var $dbl = null; + var $dbu = null; + var $args = array(); - $dbl = doConnect('latin1'); + function __construct($args) + { + $this->args = $args; - if (empty($dbl)) { - return; + if (array_key_exists('max_date', $args)) { + $this->max_date = strftime('%Y-%m-%d %H:%M:%S', strtotime($args['max_date'])); + } else { + $this->max_date = strftime('%Y-%m-%d %H:%M:%S', time()); + } + + $this->dbl = $this->doConnect('latin1'); + + if (empty($this->dbl)) { + return; + } + + $this->dbu = $this->doConnect('utf8'); + + if (empty($this->dbu)) { + return; + } } - $dbu = doConnect('utf8'); + function doConnect($charset) + { + $db = DB::connect(common_config('db', 'database'), + array('persistent' => false)); - if (empty($dbu)) { - return; - } + if (PEAR::isError($db)) { + echo "ERROR: " . $db->getMessage() . "\n"; + return NULL; + } - // Do a separate DB connection + $conn = $db->connection; - $sth = $dbu->prepare("UPDATE notice SET content = UNHEX(?), rendered = UNHEX(?) WHERE id = ?"); + $succ = mysqli_set_charset($conn, $charset); - if (PEAR::isError($sth)) { - echo "ERROR: " . $sth->getMessage() . "\n"; - return; - } + if (!$succ) { + echo "ERROR: couldn't set charset\n"; + $db->disconnect(); + return NULL; + } - $sql = 'SELECT id, content, rendered FROM notice ' . - 'WHERE LENGTH(content) != CHAR_LENGTH(content)'; - - if (!empty($max_id)) { - $sql .= ' AND id <= ' . $max_id; - } - - if (!empty($min_id)) { - $sql .= ' AND id >= ' . $min_id; - } - - $sql .= ' ORDER BY id DESC'; - - $rn = $dbl->query($sql); - - if (PEAR::isError($rn)) { - echo "ERROR: " . $rn->getMessage() . "\n"; - return; - } - - echo "Number of rows: " . $rn->numRows() . "\n"; - - $notice = array(); - - while (DB_OK == $rn->fetchInto($notice)) { - - $id = ($notice[0])+0; - $content = bin2hex($notice[1]); - $rendered = bin2hex($notice[2]); - - echo "$id..."; - - $result =& $dbu->execute($sth, array($content, $rendered, $id)); + $result = $db->autoCommit(true); if (PEAR::isError($result)) { echo "ERROR: " . $result->getMessage() . "\n"; - continue; + $db->disconnect(); + return NULL; } - $cnt = $dbu->affectedRows(); + return $db; + } - if ($cnt != 1) { - echo "ERROR: 0 rows affected\n"; - continue; + function fixup() + { + $this->fixupNotices($this->args['max_notice'], + $this->args['min_notice']); + $this->fixupProfiles(); + $this->fixupGroups(); + } + + function fixupNotices($max_id, $min_id) { + + // Do a separate DB connection + + $sth = $this->dbu->prepare("UPDATE notice SET content = UNHEX(?), rendered = UNHEX(?) WHERE id = ?"); + + if (PEAR::isError($sth)) { + echo "ERROR: " . $sth->getMessage() . "\n"; + return; } - $notice = Notice::staticGet('id', $id); - $notice->decache(); + $sql = 'SELECT id, content, rendered FROM notice ' . + 'WHERE LENGTH(content) != CHAR_LENGTH(content) '. + 'AND modified < "'.$this->max_date.'" '; - echo "OK\n"; + if (!empty($max_id)) { + $sql .= ' AND id <= ' . $max_id; + } + + if (!empty($min_id)) { + $sql .= ' AND id >= ' . $min_id; + } + + $sql .= ' ORDER BY id DESC'; + + $rn = $this->dbl->query($sql); + + if (PEAR::isError($rn)) { + echo "ERROR: " . $rn->getMessage() . "\n"; + return; + } + + echo "Number of rows: " . $rn->numRows() . "\n"; + + $notice = array(); + + while (DB_OK == $rn->fetchInto($notice)) { + + $id = ($notice[0])+0; + $content = bin2hex($notice[1]); + $rendered = bin2hex($notice[2]); + + echo "$id..."; + + $result =& $this->dbu->execute($sth, array($content, $rendered, $id)); + + if (PEAR::isError($result)) { + echo "ERROR: " . $result->getMessage() . "\n"; + continue; + } + + $cnt = $this->dbu->affectedRows(); + + if ($cnt != 1) { + echo "ERROR: 0 rows affected\n"; + continue; + } + + $notice = Notice::staticGet('id', $id); + $notice->decache(); + + echo "OK\n"; + } + } + + function fixupProfiles() + { + // Do a separate DB connection + + $sth = $this->dbu->prepare("UPDATE profile SET ". + "fullname = UNHEX(?),". + "location = UNHEX(?), ". + "bio = UNHEX(?) ". + "WHERE id = ?"); + + if (PEAR::isError($sth)) { + echo "ERROR: " . $sth->getMessage() . "\n"; + return; + } + + $sql = 'SELECT id, fullname, location, bio FROM profile ' . + 'WHERE (LENGTH(fullname) != CHAR_LENGTH(fullname) '. + 'OR LENGTH(location) != CHAR_LENGTH(location) '. + 'OR LENGTH(bio) != CHAR_LENGTH(bio)) '. + 'AND modified < "'.$this->max_date.'" '. + ' ORDER BY modified DESC'; + + $rn = $this->dbl->query($sql); + + if (PEAR::isError($rn)) { + echo "ERROR: " . $rn->getMessage() . "\n"; + return; + } + + echo "Number of rows: " . $rn->numRows() . "\n"; + + $profile = array(); + + while (DB_OK == $rn->fetchInto($profile)) { + + $id = ($profile[0])+0; + $fullname = bin2hex($profile[1]); + $location = bin2hex($profile[2]); + $bio = bin2hex($profile[3]); + + echo "$id..."; + + $result =& $this->dbu->execute($sth, array($fullname, $location, $bio, $id)); + + if (PEAR::isError($result)) { + echo "ERROR: " . $result->getMessage() . "\n"; + continue; + } + + $cnt = $this->dbu->affectedRows(); + + if ($cnt != 1) { + echo "ERROR: 0 rows affected\n"; + continue; + } + + $profile = Profile::staticGet('id', $id); + $profile->decache(); + + echo "OK\n"; + } + } + + function fixupGroups() + { + // Do a separate DB connection + + $sth = $this->dbu->prepare("UPDATE user_group SET ". + "fullname = UNHEX(?),". + "location = UNHEX(?), ". + "description = UNHEX(?) ". + "WHERE id = ?"); + + if (PEAR::isError($sth)) { + echo "ERROR: " . $sth->getMessage() . "\n"; + return; + } + + $sql = 'SELECT id, fullname, location, description FROM user_group ' . + 'WHERE LENGTH(fullname) != CHAR_LENGTH(fullname) '. + 'OR LENGTH(location) != CHAR_LENGTH(location) '. + 'OR LENGTH(description) != CHAR_LENGTH(description) '; + 'AND modified < "'.$this->max_date.'" '. + 'ORDER BY modified DESC'; + + $rn = $this->dbl->query($sql); + + if (PEAR::isError($rn)) { + echo "ERROR: " . $rn->getMessage() . "\n"; + return; + } + + echo "Number of rows: " . $rn->numRows() . "\n"; + + $user_group = array(); + + while (DB_OK == $rn->fetchInto($user_group)) { + + $id = ($user_group[0])+0; + $fullname = bin2hex($user_group[1]); + $location = bin2hex($user_group[2]); + $description = bin2hex($user_group[3]); + + echo "$id..."; + + $result =& $this->dbu->execute($sth, array($fullname, $location, $description, $id)); + + if (PEAR::isError($result)) { + echo "ERROR: " . $result->getMessage() . "\n"; + continue; + } + + $cnt = $this->dbu->affectedRows(); + + if ($cnt != 1) { + echo "ERROR: 0 rows affected\n"; + continue; + } + + $user_group = User_group::staticGet('id', $id); + $user_group->decache(); + + echo "OK\n"; + } } } -function doConnect($charset) -{ - $db = DB::connect(common_config('db', 'database'), - array('persistent' => false)); +$max_date = ($argc > 1) ? $argv[1] : null; +$max_id = ($argc > 2) ? $argv[2] : null; +$min_id = ($argc > 3) ? $argv[3] : null; - if (PEAR::isError($db)) { - echo "ERROR: " . $db->getMessage() . "\n"; - return NULL; - } +$fixer = new UTF8FixerUpper(array('max_date' => $max_date, + 'max_notice' => $max_id, + 'min_notice' => $min_id)); -// $result = $db->query("SET NAMES $charset"); +$fixer->fixup(); - $conn = $db->connection; - - $succ = mysqli_set_charset($conn, $charset); - - if (!$succ) { - echo "ERROR: couldn't set charset\n"; - $db->disconnect(); - return NULL; - } - - $result = $db->autoCommit(true); - - if (PEAR::isError($result)) { - echo "ERROR: " . $result->getMessage() . "\n"; - $db->disconnect(); - return NULL; - } - - return $db; -} - -$max_id = ($argc > 1) ? $argv[1] : null; -$min_id = ($argc > 2) ? $argv[2] : null; - -fixup_utf8($max_id, $min_id); From f134ba68ab6a7e9f94579d2a4e1f02eca2a7ebc0 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 30 May 2009 21:04:35 -0400 Subject: [PATCH 19/24] free memory for each iteration DB_DataObject in fixup_utf8 --- scripts/fixup_utf8.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/fixup_utf8.php b/scripts/fixup_utf8.php index 2046d2b770..f9debd3eca 100644 --- a/scripts/fixup_utf8.php +++ b/scripts/fixup_utf8.php @@ -163,6 +163,7 @@ class UTF8FixerUpper $notice = Notice::staticGet('id', $id); $notice->decache(); + $notice->free(); echo "OK\n"; } @@ -226,6 +227,7 @@ class UTF8FixerUpper $profile = Profile::staticGet('id', $id); $profile->decache(); + $profile->free(); echo "OK\n"; } @@ -289,6 +291,7 @@ class UTF8FixerUpper $user_group = User_group::staticGet('id', $id); $user_group->decache(); + $user_group->free(); echo "OK\n"; } From 4ec1c333073fd693147ff34895cf7e3664f83cf6 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 30 May 2009 21:45:11 -0400 Subject: [PATCH 20/24] correct last-modified date for shownotice.php --- actions/shownotice.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/shownotice.php b/actions/shownotice.php index 2c469c9dee..1be1e2414c 100644 --- a/actions/shownotice.php +++ b/actions/shownotice.php @@ -122,7 +122,7 @@ class ShownoticeAction extends Action function lastModified() { - return max(strtotime($this->notice->created), + return max(strtotime($this->notice->modified), strtotime($this->profile->modified), ($this->avatar) ? strtotime($this->avatar->modified) : 0); } From 6658e2a2ee9517bebd59cf69d7483e6eda691b4e Mon Sep 17 00:00:00 2001 From: Dan Moore Date: Thu, 4 Jun 2009 17:57:03 -0400 Subject: [PATCH 21/24] Handle the ways Twitter accepts passing the user in the query string. --- actions/api.php | 4 ++-- lib/twitterapi.php | 22 +++++++++++++++++++++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/actions/api.php b/actions/api.php index b25ba99f30..b8da852b53 100644 --- a/actions/api.php +++ b/actions/api.php @@ -144,8 +144,8 @@ class ApiAction extends Action } if (in_array($fullname, $bareauth)) { - # bareauth: only needs auth if without an argument - if ($this->api_arg) { + # bareauth: only needs auth if without an argument or query param specifying user + if ($this->api_arg || $this->arg('id') || is_numeric($this->arg('user_id')) || $this->arg('screen_name')) { return false; } else { return true; diff --git a/lib/twitterapi.php b/lib/twitterapi.php index 1d527b935f..ca8b03cdcd 100644 --- a/lib/twitterapi.php +++ b/lib/twitterapi.php @@ -673,7 +673,27 @@ class TwitterapiAction extends Action function get_user($id, $apidata=null) { if (!$id) { - return $apidata['user']; + + // Twitter supports these other ways of passing the user ID + if (is_numeric($this->arg('id'))) { + return User::staticGet($this->arg('id')); + } else if ($this->arg('id')) { + $nickname = common_canonical_nickname($this->arg('id')); + return User::staticGet('nickname', $nickname); + } else if ($this->arg('user_id')) { + // This is to ensure that a non-numeric user_id still + // overrides screen_name even if it doesn't get used + if (is_numeric($this->arg('user_id'))) { + return User::staticGet('id', $this->arg('user_id')); + } + } else if ($this->arg('screen_name')) { + $nickname = common_canonical_nickname($this->arg('screen_name')); + return User::staticGet('nickname', $nickname); + } else { + // Fall back to trying the currently authenticated user + return $apidata['user']; + } + } else if (is_numeric($id)) { return User::staticGet($id); } else { From 2c81d8db76135af2e4343316f67a2f535971d013 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 5 Jun 2009 10:07:26 -0700 Subject: [PATCH 22/24] don't send smses to sender --- lib/mail.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/mail.php b/lib/mail.php index 27a1d99dcb..4e1f1dbb1d 100644 --- a/lib/mail.php +++ b/lib/mail.php @@ -335,6 +335,7 @@ function mail_broadcast_notice_sms($notice) "FROM $UT JOIN subscription " . "ON $UT.id = subscription.subscriber " . 'WHERE subscription.subscribed = ' . $notice->profile_id . ' ' . + 'AND subscription.subscribed != subscription.subscriber ' . "AND $UT.smsemail IS NOT null " . "AND $UT.smsnotify = 1 " . 'AND subscription.sms = 1 '); From d15fdac3d348eda7314a206c2403494e9a096c98 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 6 Jun 2009 09:54:40 -0700 Subject: [PATCH 23/24] add fixup messages for utf8 --- scripts/fixup_utf8.php | 57 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/scripts/fixup_utf8.php b/scripts/fixup_utf8.php index f9debd3eca..83e4850217 100644 --- a/scripts/fixup_utf8.php +++ b/scripts/fixup_utf8.php @@ -296,6 +296,63 @@ class UTF8FixerUpper echo "OK\n"; } } + + function fixupMessages() { + + // Do a separate DB connection + + $sth = $this->dbu->prepare("UPDATE message SET content = UNHEX(?), rendered = UNHEX(?) WHERE id = ?"); + + if (PEAR::isError($sth)) { + echo "ERROR: " . $sth->getMessage() . "\n"; + return; + } + + $sql = 'SELECT id, content, rendered FROM message ' . + 'WHERE LENGTH(content) != CHAR_LENGTH(content) '. + 'AND modified < "'.$this->max_date.'" '. + 'ORDER BY id DESC'; + + $rn = $this->dbl->query($sql); + + if (PEAR::isError($rn)) { + echo "ERROR: " . $rn->getMessage() . "\n"; + return; + } + + echo "Number of rows: " . $rn->numRows() . "\n"; + + $message = array(); + + while (DB_OK == $rn->fetchInto($message)) { + + $id = ($message[0])+0; + $content = bin2hex($message[1]); + $rendered = bin2hex($message[2]); + + echo "$id..."; + + $result =& $this->dbu->execute($sth, array($content, $rendered, $id)); + + if (PEAR::isError($result)) { + echo "ERROR: " . $result->getMessage() . "\n"; + continue; + } + + $cnt = $this->dbu->affectedRows(); + + if ($cnt != 1) { + echo "ERROR: 0 rows affected\n"; + continue; + } + + $message = Message::staticGet('id', $id); + $message->decache(); + $message->free(); + + echo "OK\n"; + } + } } $max_date = ($argc > 1) ? $argv[1] : null; From 265e2bd58de2a01e0d7840310eb44b21b70e3914 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 8 Jun 2009 10:57:35 -0700 Subject: [PATCH 24/24] remember to convert messages --- scripts/fixup_utf8.php | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/fixup_utf8.php b/scripts/fixup_utf8.php index 83e4850217..1693760914 100644 --- a/scripts/fixup_utf8.php +++ b/scripts/fixup_utf8.php @@ -101,6 +101,7 @@ class UTF8FixerUpper $this->args['min_notice']); $this->fixupProfiles(); $this->fixupGroups(); + $this->fixupMessages(); } function fixupNotices($max_id, $min_id) {