From 4331b8b4f12f7c55afbe80fe828d77da6eaf9b84 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 11 Apr 2011 18:59:58 -0400 Subject: [PATCH] make search results privacy-aware --- actions/noticesearch.php | 53 +++++++++++------- classes/Memcached_DataObject.php | 27 +++++----- lib/searchnoticestream.php | 92 ++++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+), 34 deletions(-) create mode 100644 lib/searchnoticestream.php diff --git a/actions/noticesearch.php b/actions/noticesearch.php index 357e8ba192..257a925835 100644 --- a/actions/noticesearch.php +++ b/actions/noticesearch.php @@ -63,6 +63,21 @@ class NoticesearchAction extends SearchAction 303); } + if (!empty($this->q)) { + + $profile = Profile::current(); + $stream = new SearchNoticeStream($this->q, $profile); + $page = $this->trimmed('page'); + + if (empty($page)) { + $page = 1; + } else { + $page = (int)$page; + } + + $this->notice = $stream->getNotices((($page-1)*NOTICES_PER_PAGE), NOTICES_PER_PAGE + 1); + } + common_set_returnto($this->selfUrl()); return true; @@ -117,18 +132,25 @@ class NoticesearchAction extends SearchAction */ function showResults($q, $page) { - $notice = new Notice(); - - $search_engine = $notice->getSearchEngine('notice'); - $search_engine->set_sort_mode('chron'); - // Ask for an extra to see if there's more. - $search_engine->limit((($page-1)*NOTICES_PER_PAGE), NOTICES_PER_PAGE + 1); - if (false === $search_engine->query($q)) { - $cnt = 0; - } else { - $cnt = $notice->find(); + if ($this->notice->N === 0) { + $this->showEmptyResults($q, $page); } - if ($cnt === 0) { + + if (Event::handle('StartNoticeSearchShowResults', array($this, $q, $this->notice))) { + $terms = preg_split('/[\s,]+/', $q); + $nl = new SearchNoticeList($this->notice, $this, $terms); + $cnt = $nl->show(); + $this->pagination($page > 1, + $cnt > NOTICES_PER_PAGE, + $page, + 'noticesearch', + array('q' => $q)); + Event::handle('EndNoticeSearchShowResults', array($this, $q, $this->notice)); + } + } + + function showEmptyResults($q, $page) + { // TRANS: Text for notice search results is the query had no results. $this->element('p', 'error', _('No results.')); @@ -148,15 +170,6 @@ class NoticesearchAction extends SearchAction $this->raw(common_markup_to_html($message)); $this->elementEnd('div'); return; - } - if (Event::handle('StartNoticeSearchShowResults', array($this, $q, $notice))) { - $terms = preg_split('/[\s,]+/', $q); - $nl = new SearchNoticeList($notice, $this, $terms); - $cnt = $nl->show(); - $this->pagination($page > 1, $cnt > NOTICES_PER_PAGE, - $page, 'noticesearch', array('q' => $q)); - Event::handle('EndNoticeSearchShowResults', array($this, $q, $notice)); - } } function showScripts() diff --git a/classes/Memcached_DataObject.php b/classes/Memcached_DataObject.php index 59809dc8f7..c361ba8783 100644 --- a/classes/Memcached_DataObject.php +++ b/classes/Memcached_DataObject.php @@ -273,24 +273,23 @@ class Memcached_DataObject extends Safe_DataObject function getSearchEngine($table) { require_once INSTALLDIR.'/lib/search_engines.php'; - static $search_engine; - if (!isset($search_engine)) { - if (Event::handle('GetSearchEngine', array($this, $table, &$search_engine))) { - if ('mysql' === common_config('db', 'type')) { - $type = common_config('search', 'type'); - if ($type == 'like') { - $search_engine = new MySQLLikeSearch($this, $table); - } else if ($type == 'fulltext') { - $search_engine = new MySQLSearch($this, $table); - } else { - // Low level exception. No need for i18n as discussed with Brion. - throw new ServerException('Unknown search type: ' . $type); - } + + if (Event::handle('GetSearchEngine', array($this, $table, &$search_engine))) { + if ('mysql' === common_config('db', 'type')) { + $type = common_config('search', 'type'); + if ($type == 'like') { + $search_engine = new MySQLLikeSearch($this, $table); + } else if ($type == 'fulltext') { + $search_engine = new MySQLSearch($this, $table); } else { - $search_engine = new PGSearch($this, $table); + // Low level exception. No need for i18n as discussed with Brion. + throw new ServerException('Unknown search type: ' . $type); } + } else { + $search_engine = new PGSearch($this, $table); } } + return $search_engine; } diff --git a/lib/searchnoticestream.php b/lib/searchnoticestream.php new file mode 100644 index 0000000000..6593a4c860 --- /dev/null +++ b/lib/searchnoticestream.php @@ -0,0 +1,92 @@ +. + * + * @category Stream + * @package StatusNet + * @author Evan Prodromou + * @copyright 2011 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + // This check helps protect against security problems; + // your code file can't be executed directly from the web. + exit(1); +} + +/** + * Stream of notice search results + * + * @category General + * @package StatusNet + * @author Evan Prodromou + * @copyright 2011 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ + +class SearchNoticeStream extends ScopingNoticeStream +{ + function __construct($q, $profile = -1) + { + if (is_int($profile) && $profile == -1) { + $profile = Profile::current(); + } + + parent::__construct(new RawSearchNoticeStream($q), $profile); + } +} + +class RawSearchNoticeStream extends NoticeStream +{ + protected $q; + + function __construct($q) + { + $this->q = $q; + } + + function getNoticeIds($offset, $limit, $since_id, $max_id) + { + $notice = new Notice(); + + $search_engine = $notice->getSearchEngine('notice'); + $search_engine->set_sort_mode('chron'); + + $search_engine->limit($offset, $limit); + + $ids = array(); + + // wtf? + + $search_engine->query($this->q); + + if ($notice->find()) { + while ($notice->fetch()) { + $ids[] = $notice->id; + } + } + + return $ids; + } +} \ No newline at end of file