From fda2fb28f6ea101571d87ec2c46aeb6048fc421f Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 31 Dec 2009 22:32:10 +0000 Subject: - Use a stripped down new notice form for FB app because FB canvas apps can't support image upload via multipart/form-data (and location sharing is iffy). - Deal with new error code 100 from Facebook, which seem to be for inactive accounts. --- plugins/Facebook/facebookaction.php | 35 +----- plugins/Facebook/facebooknoticeform.php | 206 ++++++++++++++++++++++++++++++++ plugins/Facebook/facebookutil.php | 16 +-- 3 files changed, 216 insertions(+), 41 deletions(-) create mode 100644 plugins/Facebook/facebooknoticeform.php diff --git a/plugins/Facebook/facebookaction.php b/plugins/Facebook/facebookaction.php index 24bf215fd..86d6647b5 100644 --- a/plugins/Facebook/facebookaction.php +++ b/plugins/Facebook/facebookaction.php @@ -32,7 +32,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { } require_once INSTALLDIR . '/plugins/Facebook/facebookutil.php'; -require_once INSTALLDIR . '/lib/noticeform.php'; +require_once INSTALLDIR . '/plugins/Facebook/facebooknoticeform.php'; class FacebookAction extends Action { @@ -462,39 +462,6 @@ class FacebookAction extends Action } -class FacebookNoticeForm extends NoticeForm -{ - - var $post_action = null; - - /** - * Constructor - * - * @param HTMLOutputter $out output channel - * @param string $action action to return to, if any - * @param string $content content to pre-fill - */ - - function __construct($out=null, $action=null, $content=null, - $post_action=null, $user=null) - { - parent::__construct($out, $action, $content, $user); - $this->post_action = $post_action; - } - - /** - * Action of the form - * - * @return string URL of the action - */ - - function action() - { - return $this->post_action; - } - -} - class FacebookNoticeList extends NoticeList { diff --git a/plugins/Facebook/facebooknoticeform.php b/plugins/Facebook/facebooknoticeform.php new file mode 100644 index 000000000..5989147f4 --- /dev/null +++ b/plugins/Facebook/facebooknoticeform.php @@ -0,0 +1,206 @@ +. + * + * @category Form + * @package StatusNet + * @author Evan Prodromou + * @author Sarven Capadisli + * @author Zach Copley + * @copyright 2009 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET') && !defined('LACONICA')) { + exit(1); +} + +require_once INSTALLDIR . '/lib/form.php'; + +/** + * Form for posting a notice from within the Facebook app + * + * @category Form + * @package StatusNet + * @author Evan Prodromou + * @author Sarven Capadisli + * @author Zach Copey + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + * + * @see HTMLOutputter + */ + +class FacebookNoticeForm extends Form +{ + /** + * Current action, used for returning to this page. + */ + + var $action = null; + + /** + * Pre-filled content of the form + */ + + var $content = null; + + /** + * The current user + */ + + var $user = null; + + /** + * The notice being replied to + */ + + var $inreplyto = null; + + /** + * Constructor + * + * @param HTMLOutputter $out output channel + * @param string $action action to return to, if any + * @param string $content content to pre-fill + */ + + function __construct($out=null, $action=null, $content=null, $post_action=null, $user=null, $inreplyto=null) + { + parent::__construct($out); + + $this->action = $action; + $this->post_action = $post_action; + $this->content = $content; + $this->inreplyto = $inreplyto; + + if ($user) { + $this->user = $user; + } else { + $this->user = common_current_user(); + } + + // Note: Facebook doesn't allow multipart/form-data posting to + // canvas pages, so don't try to set it--no file uploads, at + // least not this way. It can be done using multiple servers + // and iFrames, but it's a pretty hacky process. + } + + /** + * ID of the form + * + * @return string ID of the form + */ + + function id() + { + return 'form_notice'; + } + + /** + * Class of the form + * + * @return string class of the form + */ + + function formClass() + { + return 'form_notice'; + } + + /** + * Action of the form + * + * @return string URL of the action + */ + + function action() + { + return $this->post_action; + } + + /** + * Legend of the Form + * + * @return void + */ + function formLegend() + { + $this->out->element('legend', null, _('Send a notice')); + } + + /** + * Data elements + * + * @return void + */ + + function formData() + { + if (Event::handle('StartShowNoticeFormData', array($this))) { + $this->out->element('label', array('for' => 'notice_data-text'), + sprintf(_('What\'s up, %s?'), $this->user->nickname)); + // XXX: vary by defined max size + $this->out->element('textarea', array('id' => 'notice_data-text', + 'cols' => 35, + 'rows' => 4, + 'name' => 'status_textarea'), + ($this->content) ? $this->content : ''); + + $contentLimit = Notice::maxContent(); + + if ($contentLimit > 0) { + $this->out->elementStart('dl', 'form_note'); + $this->out->element('dt', null, _('Available characters')); + $this->out->element('dd', array('id' => 'notice_text-count'), + $contentLimit); + $this->out->elementEnd('dl'); + } + + if ($this->action) { + $this->out->hidden('notice_return-to', $this->action, 'returnto'); + } + $this->out->hidden('notice_in-reply-to', $this->inreplyto, 'inreplyto'); + + Event::handle('StartShowNoticeFormData', array($this)); + } + } + + /** + * Action elements + * + * @return void + */ + + function formActions() + { + $this->out->element('input', array('id' => 'notice_action-submit', + 'class' => 'submit', + 'name' => 'status_submit', + 'type' => 'submit', + 'value' => _('Send'))); + } +} diff --git a/plugins/Facebook/facebookutil.php b/plugins/Facebook/facebookutil.php index 2ec6db6b8..ac532e18b 100644 --- a/plugins/Facebook/facebookutil.php +++ b/plugins/Facebook/facebookutil.php @@ -138,21 +138,23 @@ function facebookBroadcastNotice($notice) $code = $e->getCode(); - common_log(LOG_WARNING, 'Facebook returned error code ' . - $code . ': ' . $e->getMessage()); - common_log(LOG_WARNING, - 'Unable to update Facebook status for ' . - "$user->nickname (user id: $user->id)!"); + $msg = "Facebook returned error code $code: " . + $e->getMessage() . ' - ' . + "Unable to update Facebook status (notice $notice->id) " . + "for $user->nickname (user id: $user->id)!"; - if ($code == 200 || $code == 250) { + common_log(LOG_WARNING, $msg); + if ($code == 100 || $code == 200 || $code == 250) { + + // 100 The account is 'inactive' (probably - this is not well documented) // 200 The application does not have permission to operate on the passed in uid parameter. // 250 Updating status requires the extended permission status_update or publish_stream. // see: http://wiki.developers.facebook.com/index.php/Users.setStatus#Example_Return_XML remove_facebook_app($flink); - } else { + } else { // Try sending again later. -- cgit v1.2.3-54-g00ecf From 7491274c0eb1317203ed39a6ff2a96acb6c8ed78 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 31 Dec 2009 22:53:46 +0000 Subject: Removed crazy redundant broadcasting of notices by the FB app --- plugins/Facebook/facebookaction.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/plugins/Facebook/facebookaction.php b/plugins/Facebook/facebookaction.php index 86d6647b5..3e8c5cf41 100644 --- a/plugins/Facebook/facebookaction.php +++ b/plugins/Facebook/facebookaction.php @@ -455,9 +455,6 @@ class FacebookAction extends Action common_broadcast_notice($notice); - // Also update the user's Facebook status - facebookBroadcastNotice($notice); - } } -- cgit v1.2.3-54-g00ecf From eb22d2d2401293ec87e9fa2c2e7fb053d9780dfd Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 5 Jan 2010 15:04:08 -0800 Subject: Ticket 2135: trim overlong repeats with ellipsis rather than failing. In web interface and retweet/repeat API we show the original untrimmed text, but some back-compat API messages will still show the trimmed 'RT' version. This matches Twitter's behavior on overlong retweets, though we're outputting the RT version in more API results than they do. --- classes/Notice.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/classes/Notice.php b/classes/Notice.php index 93e94230d..6d75cbcad 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -1366,12 +1366,21 @@ class Notice extends Memcached_DataObject { $author = Profile::staticGet('id', $this->profile_id); - // FIXME: truncate on long repeats...? - $content = sprintf(_('RT @%1$s %2$s'), $author->nickname, $this->content); + $maxlen = common_config('site', 'textlimit'); + if (mb_strlen($content) > $maxlen) { + // Web interface and current Twitter API clients will + // pull the original notice's text, but some older + // clients and RSS/Atom feeds will see this trimmed text. + // + // Unfortunately this is likely to lose tags or URLs + // at the end of long notices. + $content = mb_substr($content, 0, $maxlen - 4) . ' ...'; + } + return self::saveNew($repeater_id, $content, $source, array('repeat_of' => $this->id)); } -- cgit v1.2.3-54-g00ecf From bbbec435b02340b38aac8facf90f43868e2af144 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 5 Jan 2010 16:15:12 -0800 Subject: Fix for overlong RT trimming: don't trim if textlimit is 0 (unlimited) --- classes/Notice.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes/Notice.php b/classes/Notice.php index 6d75cbcad..c2ff7fd09 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -1371,7 +1371,7 @@ class Notice extends Memcached_DataObject $this->content); $maxlen = common_config('site', 'textlimit'); - if (mb_strlen($content) > $maxlen) { + if ($maxlen > 0 && mb_strlen($content) > $maxlen) { // Web interface and current Twitter API clients will // pull the original notice's text, but some older // clients and RSS/Atom feeds will see this trimmed text. -- cgit v1.2.3-54-g00ecf From d6db8e58170e6e78a0fd67d50f7fea5d95b5d9c8 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 6 Jan 2010 13:40:28 -0800 Subject: Don't output notices from deleted users. --- actions/twitapisearchatom.php | 9 ++++++++- lib/jsonsearchresultslist.php | 10 ++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/actions/twitapisearchatom.php b/actions/twitapisearchatom.php index 1cb8d7efe..baed2a0c7 100644 --- a/actions/twitapisearchatom.php +++ b/actions/twitapisearchatom.php @@ -208,7 +208,14 @@ class TwitapisearchatomAction extends ApiAction $this->showFeed(); foreach ($notices as $n) { - $this->showEntry($n); + + $profile = $n->getProfile(); + + // Don't show notices from deleted users + + if (!empty($profile)) { + $this->showEntry($n); + } } $this->endAtom(); diff --git a/lib/jsonsearchresultslist.php b/lib/jsonsearchresultslist.php index 569bfa873..0d72ddf7a 100644 --- a/lib/jsonsearchresultslist.php +++ b/lib/jsonsearchresultslist.php @@ -105,8 +105,14 @@ class JSONSearchResultsList break; } - $item = new ResultItem($this->notice); - array_push($this->results, $item); + $profile = $this->notice->getProfile(); + + // Don't show notices from deleted users + + if (!empty($profile)) { + $item = new ResultItem($this->notice); + array_push($this->results, $item); + } } $time_end = microtime(true); -- cgit v1.2.3-54-g00ecf From 30409f7bad45862ce498d7084ab2a8a4287e7d3f Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 10 Jan 2010 12:07:49 -0800 Subject: debugging code to find passed-in objects in munge_password --- lib/util.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/util.php b/lib/util.php index fdcc87677..00d1ab557 100644 --- a/lib/util.php +++ b/lib/util.php @@ -62,7 +62,7 @@ function common_init_language() // gettext will still select the right language. $language = common_language(); $locale_set = common_init_locale($language); - + setlocale(LC_CTYPE, 'C'); // So we do not have to make people install the gettext locales $path = common_config('site','locale_path'); @@ -119,6 +119,11 @@ function common_language() function common_munge_password($password, $id) { + if (is_object($id) || is_object($password)) { + $e = new Exception(); + common_log(LOG_ERR, __METHOD__ . ' object in param to common_munge_password ' . + str_replace("\n", " ", $e->getTraceAsString())); + } return md5($password . $id); } -- cgit v1.2.3-54-g00ecf From 9d3893255a77ee6c6cf1ab861d0da55ecbadbecc Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 10 Jan 2010 12:31:43 -0800 Subject: don't put Users with object IDs in the cache, and don't fetch them --- classes/Memcached_DataObject.php | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/classes/Memcached_DataObject.php b/classes/Memcached_DataObject.php index ca360d411..21f6781c2 100644 --- a/classes/Memcached_DataObject.php +++ b/classes/Memcached_DataObject.php @@ -68,7 +68,7 @@ class Memcached_DataObject extends DB_DataObject // Clear this out so we don't accidentally break global // state in *this* process. $this->_DB_resultid = null; - + // We don't have any local DBO refs, so clear these out. $this->_link_loaded = false; } @@ -171,7 +171,16 @@ class Memcached_DataObject extends DB_DataObject if (!$c) { return false; } else { - return $c->get(Memcached_DataObject::cacheKey($cls, $k, $v)); + $obj = $c->get(Memcached_DataObject::cacheKey($cls, $k, $v)); + if (0 == strcasecmp($cls, 'User')) { + // Special case for User + if (is_object($obj->id)) { + common_log(LOG_ERR, "User " . $obj->nickname . " was cached with User as ID; deleting"); + $c->delete(Memcached_DataObject::cacheKey($cls, $k, $v)); + return false; + } + } + return $obj; } } @@ -190,6 +199,12 @@ class Memcached_DataObject extends DB_DataObject $c = $this->memcache(); if (!$c) { return false; + } else if ($this->tableName() == 'user' && is_object($this->id)) { + // Special case for User bug + $e = new Exception(); + common_log(LOG_ERR, __METHOD__ . ' caching user with User object as ID ' . + str_replace("\n", " ", $e->getTraceAsString())); + return false; } else { $pkey = array(); $pval = array(); -- cgit v1.2.3-54-g00ecf From f463329b9a5575856757ae8879e4cc11400d50a2 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 10 Jan 2010 13:18:53 -0800 Subject: check before inserting File_oembed and File_thumbnail --- classes/File.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/classes/File.php b/classes/File.php index e04a9d525..03d9ca6f0 100644 --- a/classes/File.php +++ b/classes/File.php @@ -80,7 +80,14 @@ class File extends Memcached_DataObject if (isset($redir_data['type']) && (('text/html' === substr($redir_data['type'], 0, 9) || 'application/xhtml+xml' === substr($redir_data['type'], 0, 21))) && ($oembed_data = File_oembed::_getOembed($given_url))) { + + $fo = File_oembed::staticGet('file_id', $file_id); + + if (empty($fo)) { File_oembed::saveNew($oembed_data, $file_id); + } else { + common_log(LOG_WARNING, "Strangely, a File_oembed object exists for new file $file_id", __FILE__); + } } return $x; } -- cgit v1.2.3-54-g00ecf From 2e42d3336af659ef76b2a9ade9cec099ba9ff521 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 10 Jan 2010 13:25:16 -0800 Subject: check before saving a thumbnail --- classes/File_oembed.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/classes/File_oembed.php b/classes/File_oembed.php index e41ccfd09..11f160718 100644 --- a/classes/File_oembed.php +++ b/classes/File_oembed.php @@ -115,7 +115,13 @@ class File_oembed extends Memcached_DataObject } $file_oembed->insert(); if (!empty($data->thumbnail_url)) { - File_thumbnail::saveNew($data, $file_id); + $ft = File_thumbnail::staticGet('file_id', $file_id); + if (!empty($ft)) { + common_log(LOG_WARNING, "Strangely, a File_thumbnail object exists for new file $file_id", + __FILE__); + } else { + File_thumbnail::saveNew($data, $file_id); + } } } } -- cgit v1.2.3-54-g00ecf From 6fdd52467dea6164d71afc9b80e1f8bcf5fb1b9a Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 10 Jan 2010 13:54:26 -0800 Subject: catch exceptions from snapshot --- lib/snapshot.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/snapshot.php b/lib/snapshot.php index 2a10c6b93..a16087ac0 100644 --- a/lib/snapshot.php +++ b/lib/snapshot.php @@ -173,8 +173,12 @@ class Snapshot // XXX: Use OICU2 and OAuth to make authorized requests $reporturl = common_config('snapshot', 'reporturl'); - $request = HTTPClient::start(); - $request->post($reporturl, null, $this->stats); + try { + $request = HTTPClient::start(); + $request->post($reporturl, null, $this->stats); + } catch (Exception $e) { + common_log(LOG_WARNING, "Error in snapshot: " . $e->getMessage()); + } } /** -- cgit v1.2.3-54-g00ecf From 7aa43f3c93a5434b59a66824b2816d5ba8cf1978 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 10 Jan 2010 14:10:31 -0800 Subject: defaultDesign was undefined; fixed that --- lib/api.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/api.php b/lib/api.php index 4ed49e452..06d7c079d 100644 --- a/lib/api.php +++ b/lib/api.php @@ -140,12 +140,14 @@ class ApiAction extends Action // Note: some profiles don't have an associated user + $defaultDesign = Design::siteDesign(); + if (!empty($user)) { $design = $user->getDesign(); } if (empty($design)) { - $design = Design::siteDesign(); + $design = $defaultDesign; } $color = Design::toWebColor(empty($design->backgroundcolor) ? $defaultDesign->backgroundcolor : $design->backgroundcolor); -- cgit v1.2.3-54-g00ecf