. * * @category Search * @package StatusNet * @author Zach Copley * @copyright 2008-2010 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/apiprivateauth.php'; require_once INSTALLDIR.'/lib/jsonsearchresultslist.php'; /** * Action handler for Twitter-compatible API search * * @category Search * @package StatusNet * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ * @see ApiAction */ class ApiSearchJSONAction extends ApiPrivateAuthAction { var $query; var $lang; var $rpp; var $page; var $since_id; var $limit; var $geocode; /** * Initialization. * * @param array $args Web and URL arguments * * @return boolean true if nothing goes wrong */ function prepare($args) { parent::prepare($args); $this->query = $this->trimmed('q'); $this->lang = $this->trimmed('lang'); $this->rpp = $this->trimmed('rpp'); if (!$this->rpp) { $this->rpp = 15; } if ($this->rpp > 100) { $this->rpp = 100; } $this->page = $this->trimmed('page'); if (!$this->page) { $this->page = 1; } // TODO: Suppport max_id -- we need to tweak the backend // Search classes to support it. $this->since_id = $this->trimmed('since_id'); $this->geocode = $this->trimmed('geocode'); if (!empty($this->auth_user)) { $this->auth_profile = $this->auth_user->getProfile(); } else { $this->auth_profile = null; } return true; } /** * Handle a request * * @param array $args Arguments from $_REQUEST * * @return void */ function handle($args) { parent::handle($args); $this->showResults(); } /** * Show search results * * @return void */ function showResults() { $q = strtolower($this->query); // TODO: Support search operators like from: and to:, boolean, etc. if (preg_match('/^#([\pL\pN_\-\.]{1,64})$/ue', $q)) { $stream = new TagNoticeStream(substr($q, 1), $this->auth_profile); } else if ($this->isAnURL($q)) { $canon = File_redirection::_canonUrl($q); $file = File::staticGet('url', $canon); if (!empty($file)) { $stream = new FileNoticeStream($file, $this->auth_profile); } } else { $stream = new SearchNoticeStream($q, $this->auth_profile); } if (empty($stream)) { // XXX: This is hackish, but need some simple way to say "There's no results" $notice = new ArrayWrapper(array()); } else { $notice = $stream->getNotices(($this->page - 1) * $this->rpp, $this->rpp + 1); } // TODO: max_id, lang, geocode $results = new JSONSearchResultsList($notice, $q, $this->rpp, $this->page, $this->since_id); $this->initDocument('json'); $results->show(); $this->endDocument('json'); } function isAnURL($q) { $regex = '#^'. '(?:^|[\s\<\>\(\)\[\]\{\}\\\'\\\";]+)(?![\@\!\#])'. '('. '(?:'. '(?:'. //Known protocols '(?:'. '(?:(?:https?|ftps?|mms|rtsp|gopher|news|nntp|telnet|wais|file|prospero|webcal|irc)://)'. '|'. '(?:(?:mailto|aim|tel|xmpp):)'. ')'. '(?:[\pN\pL\-\_\+\%\~]+(?::[\pN\pL\-\_\+\%\~]+)?\@)?'. //user:pass@ '(?:'. '(?:'. '\[[\pN\pL\-\_\:\.]+(?