diff options
author | Brion Vibber <brion@pobox.com> | 2010-10-13 15:37:54 -0700 |
---|---|---|
committer | Brion Vibber <brion@pobox.com> | 2010-10-13 15:37:54 -0700 |
commit | 22047f6412811cb340aee6ba49d15257581b5aa9 (patch) | |
tree | e673cc89d1518992ac515be2af86e8f787438520 /lib | |
parent | 3cd03ee6ecb029ce0c27ddd6b3af92d888e1f58f (diff) | |
parent | 6c77d86b7f39c35eac0fcc3f13c0beba3e694318 (diff) |
Merge branch '0.9.x' into twitstream
Diffstat (limited to 'lib')
-rw-r--r-- | lib/apiaction.php | 16 | ||||
-rw-r--r-- | lib/apioauth.php | 43 | ||||
-rw-r--r-- | lib/apioauthstore.php | 70 | ||||
-rw-r--r-- | lib/clienterroraction.php | 26 | ||||
-rw-r--r-- | lib/connectsettingsaction.php | 4 | ||||
-rw-r--r-- | lib/deletegroupform.php | 123 | ||||
-rw-r--r-- | lib/error.php | 73 | ||||
-rw-r--r-- | lib/info.php | 118 | ||||
-rw-r--r-- | lib/installer.php | 6 | ||||
-rw-r--r-- | lib/oauthstore.php | 30 | ||||
-rw-r--r-- | lib/right.php | 1 | ||||
-rw-r--r-- | lib/router.php | 2 | ||||
-rw-r--r-- | lib/servererroraction.php | 23 | ||||
-rw-r--r-- | lib/serverexception.php | 2 | ||||
-rw-r--r-- | lib/statusnet.php | 7 | ||||
-rw-r--r-- | lib/util.php | 7 |
16 files changed, 428 insertions, 123 deletions
diff --git a/lib/apiaction.php b/lib/apiaction.php index 0ebf88282..afba8ab63 100644 --- a/lib/apiaction.php +++ b/lib/apiaction.php @@ -1244,23 +1244,29 @@ class ApiAction extends Action // Do not emit error header for JSONP if (!isset($this->callback)) { - header('HTTP/1.1 '.$code.' '.$status_string); + header('HTTP/1.1 ' . $code . ' ' . $status_string); } - if ($format == 'xml') { + switch($format) { + case 'xml': $this->initDocument('xml'); $this->elementStart('hash'); $this->element('error', null, $msg); $this->element('request', null, $_SERVER['REQUEST_URI']); $this->elementEnd('hash'); $this->endDocument('xml'); - } elseif ($format == 'json'){ + break; + case 'json': $this->initDocument('json'); $error_array = array('error' => $msg, 'request' => $_SERVER['REQUEST_URI']); print(json_encode($error_array)); $this->endDocument('json'); - } else { - + break; + case 'text': + header('Content-Type: text/plain; charset=utf-8'); + print $msg; + break; + default: // If user didn't request a useful format, throw a regular client error throw new ClientException($msg, $code); } diff --git a/lib/apioauth.php b/lib/apioauth.php index 1c87e4232..54cecf92a 100644 --- a/lib/apioauth.php +++ b/lib/apioauth.php @@ -30,13 +30,12 @@ if (!defined('STATUSNET')) { exit(1); } - +require_once INSTALLDIR . '/lib/apiaction.php'; require_once INSTALLDIR . '/lib/apioauthstore.php'; /** - * Base action for API OAuth enpoints. Clean up the - * the request, and possibly some other common things - * here. + * Base action for API OAuth enpoints. Clean up the + * request. Some other common functions. * * @category API * @package StatusNet @@ -44,7 +43,7 @@ require_once INSTALLDIR . '/lib/apioauthstore.php'; * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ */ -class ApiOauthAction extends Action +class ApiOauthAction extends ApiAction { /** * Is this a read-only action? @@ -77,6 +76,12 @@ class ApiOauthAction extends Action self::cleanRequest(); } + /* + * Clean up the request so the OAuth library doesn't find + * any extra parameters or anything else it's not expecting. + * I'm looking at you, p parameter. + */ + static function cleanRequest() { // kill evil effects of magical slashing @@ -86,31 +91,19 @@ class ApiOauthAction extends Action } // strip out the p param added in index.php - - // XXX: should we strip anything else? Or alternatively - // only allow a known list of params? unset($_GET['p']); unset($_POST['p']); - } + unset($_REQUEST['p']); - function getCallback($url, $params) - { - foreach ($params as $k => $v) { - $url = $this->appendQueryVar($url, - OAuthUtil::urlencode_rfc3986($k), - OAuthUtil::urlencode_rfc3986($v)); + $queryArray = explode('&', $_SERVER['QUERY_STRING']); + + for ($i = 0; $i < sizeof($queryArray); $i++) { + if (substr($queryArray[$i], 0, 2) == 'p=') { + unset($queryArray[$i]); + } } - return $url; + $_SERVER['QUERY_STRING'] = implode('&', $queryArray); } - function appendQueryVar($url, $k, $v) { - $url = preg_replace('/(.*)(\?|&)' . $k . '=[^&]+?(&)(.*)/i', '$1$2$4', $url . '&'); - $url = substr($url, 0, -1); - if (strpos($url, '?') === false) { - return ($url . '?' . $k . '=' . $v); - } else { - return ($url . '&' . $k . '=' . $v); - } - } } diff --git a/lib/apioauthstore.php b/lib/apioauthstore.php index eca93866f..f3bf0b857 100644 --- a/lib/apioauthstore.php +++ b/lib/apioauthstore.php @@ -71,33 +71,37 @@ class ApiStatusNetOAuthDataStore extends StatusNetOAuthDataStore } } - function new_access_token($token, $consumer) + function new_access_token($token, $consumer, $verifier) { - common_debug('new_access_token("'.$token->key.'","'.$consumer->key.'")', __FILE__); + common_debug( + 'new_access_token("' . $token->key . '","' . $consumer->key. '","' . $verifier . '")', + __FILE__ + ); $rt = new Token(); + $rt->consumer_key = $consumer->key; - $rt->tok = $token->key; - $rt->type = 0; // request + $rt->tok = $token->key; + $rt->type = 0; // request $app = Oauth_application::getByConsumerKey($consumer->key); + assert(!empty($app)); - if (empty($app)) { - common_debug("empty app!"); - } + if ($rt->find(true) && $rt->state == 1 && $rt->verifier == $verifier) { // authorized - if ($rt->find(true) && $rt->state == 1) { // authorized common_debug('request token found.', __FILE__); // find the associated user of the app $appUser = new Oauth_application_user(); + $appUser->application_id = $app->id; - $appUser->token = $rt->tok; + $appUser->token = $rt->tok; + $result = $appUser->find(true); if (!empty($result)) { - common_debug("Oath app user found."); + common_debug("Ouath app user found."); } else { common_debug("Oauth app user not found. app id $app->id token $rt->tok"); return null; @@ -106,10 +110,12 @@ class ApiStatusNetOAuthDataStore extends StatusNetOAuthDataStore // go ahead and make the access token $at = new Token(); - $at->consumer_key = $consumer->key; - $at->tok = common_good_rand(16); - $at->secret = common_good_rand(16); - $at->type = 1; // access + $at->consumer_key = $consumer->key; + $at->tok = common_good_rand(16); + $at->secret = common_good_rand(16); + $at->type = 1; // access + $at->verifier = $verifier; + $at->verified_callback = $rt->verified_callback; // 1.0a $at->created = DB_DataObject_Cast::dateTime(); if (!$at->insert()) { @@ -183,4 +189,40 @@ class ApiStatusNetOAuthDataStore extends StatusNetOAuthDataStore throw new Exception(_('Failed to delete revoked token.')); } } + + /* + * Create a new request token. Overrided to support OAuth 1.0a callback + * + * @param OAuthConsumer $consumer the OAuth Consumer for this token + * @param string $callback the verified OAuth callback URL + * + * @return OAuthToken $token a new unauthorized OAuth request token + */ + + function new_request_token($consumer, $callback) + { + $t = new Token(); + $t->consumer_key = $consumer->key; + $t->tok = common_good_rand(16); + $t->secret = common_good_rand(16); + $t->type = 0; // request + $t->state = 0; // unauthorized + $t->verified_callback = $callback; + + if ($callback === 'oob') { + // six digit pin + $t->verifier = mt_rand(0, 9999999); + } else { + $t->verifier = common_good_rand(8); + } + + $t->created = DB_DataObject_Cast::dateTime(); + if (!$t->insert()) { + return null; + } else { + return new OAuthToken($t->tok, $t->secret); + } + } + + } diff --git a/lib/clienterroraction.php b/lib/clienterroraction.php index 08bced5bd..9233c9bde 100644 --- a/lib/clienterroraction.php +++ b/lib/clienterroraction.php @@ -12,7 +12,7 @@ * @link http://status.net/ * * StatusNet - the distributed open-source microblogging tool - * Copyright (C) 2008, 2009, StatusNet, Inc. + * Copyright (C) 2008-2010 StatusNet, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -32,7 +32,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } -require_once INSTALLDIR.'/lib/error.php'; +require_once INSTALLDIR . '/lib/error.php'; /** * Class for displaying HTTP client errors @@ -90,4 +90,26 @@ class ClientErrorAction extends ErrorAction $this->showPage(); } + + /** + * To specify additional HTTP headers for the action + * + * @return void + */ + function extraHeaders() + { + $status_string = @self::$status[$this->code]; + header('HTTP/1.1 '.$this->code.' '.$status_string); + } + + /** + * Page title. + * + * @return page title + */ + + function title() + { + return @self::$status[$this->code]; + } } diff --git a/lib/connectsettingsaction.php b/lib/connectsettingsaction.php index bb2e86176..325276c5f 100644 --- a/lib/connectsettingsaction.php +++ b/lib/connectsettingsaction.php @@ -116,9 +116,9 @@ class ConnectSettingsNav extends Widget } $menu['oauthconnectionssettings'] = array( - // TRANS: Menu item for OAth connection settings. + // TRANS: Menu item for OuAth connection settings. _m('MENU','Connections'), - // TRANS: Tooltip for connected applications (Connections through OAth) menu item. + // TRANS: Tooltip for connected applications (Connections through OAuth) menu item. _('Authorized connected applications') ); diff --git a/lib/deletegroupform.php b/lib/deletegroupform.php new file mode 100644 index 000000000..9d8012d33 --- /dev/null +++ b/lib/deletegroupform.php @@ -0,0 +1,123 @@ +<?php +/** + * StatusNet, the distributed open-source microblogging tool + * + * Form for joining a group + * + * PHP version 5 + * + * LICENCE: This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * @category Form + * @package StatusNet + * @author Evan Prodromou <evan@status.net> + * @author Sarven Capadisli <csarven@status.net> + * @author Brion Vibber <brion@status.net> + * @copyright 2009, 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')) { + exit(1); +} + +/** + * Form for deleting a group + * + * @category Form + * @package StatusNet + * @author Evan Prodromou <evan@status.net> + * @author Sarven Capadisli <csarven@status.net> + * @author Brion Vibber <brion@status.net> + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + * + * @see UnsubscribeForm + * @fixme merge a bunch of this stuff with similar form types to reduce boilerplate + */ + +class DeleteGroupForm extends Form +{ + /** + * group for user to delete + */ + + var $group = null; + + /** + * Constructor + * + * @param HTMLOutputter $out output channel + * @param group $group group to join + */ + + function __construct($out=null, $group=null) + { + parent::__construct($out); + + $this->group = $group; + } + + /** + * ID of the form + * + * @return string ID of the form + */ + + function id() + { + return 'group-delete-' . $this->group->id; + } + + /** + * class of the form + * + * @return string of the form class + */ + + function formClass() + { + return 'form_group_delete'; + } + + /** + * Action of the form + * + * @return string URL of the action + */ + + function action() + { + return common_local_url('deletegroup', + array('id' => $this->group->id)); + } + + function formData() + { + $this->out->hidden($this->id() . '-returnto-action', 'groupbyid', 'returnto-action'); + $this->out->hidden($this->id() . '-returnto-id', $this->group->id, 'returnto-id'); + } + + /** + * Action elements + * + * @return void + */ + + function formActions() + { + $this->out->submit('submit', _('Delete')); + } +} diff --git a/lib/error.php b/lib/error.php index a6a29119f..762425dc4 100644 --- a/lib/error.php +++ b/lib/error.php @@ -33,6 +33,8 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } +require_once INSTALLDIR . '/lib/info.php'; + /** * Base class for displaying HTTP errors * @@ -42,7 +44,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 * @link http://status.net/ */ -class ErrorAction extends Action +class ErrorAction extends InfoAction { static $status = array(); @@ -52,7 +54,7 @@ class ErrorAction extends Action function __construct($message, $code, $output='php://output', $indent=null) { - parent::__construct($output, $indent); + parent::__construct(null, $message, $output, $indent); $this->code = $code; $this->message = $message; @@ -64,43 +66,6 @@ class ErrorAction extends Action $this->prepare($_REQUEST); } - /** - * To specify additional HTTP headers for the action - * - * @return void - */ - function extraHeaders() - { - $status_string = @self::$status[$this->code]; - header('HTTP/1.1 '.$this->code.' '.$status_string); - } - - /** - * Display content. - * - * @return nothing - */ - function showContent() - { - $this->element('div', array('class' => 'error'), $this->message); - } - - /** - * Page title. - * - * @return page title - */ - - function title() - { - return @self::$status[$this->code]; - } - - function isReadOnly($args) - { - return true; - } - function showPage() { if ($this->minimal) { @@ -116,32 +81,16 @@ class ErrorAction extends Action exit(); } - // Overload a bunch of stuff so the page isn't too bloated - - function showBody() + /** + * Display content. + * + * @return nothing + */ + function showContent() { - $this->elementStart('body', array('id' => 'error')); - $this->elementStart('div', array('id' => 'wrap')); - $this->showHeader(); - $this->showCore(); - $this->showFooter(); - $this->elementEnd('div'); - $this->elementEnd('body'); + $this->element('div', array('class' => 'error'), $this->message); } - function showCore() - { - $this->elementStart('div', array('id' => 'core')); - $this->showContentBlock(); - $this->elementEnd('div'); - } - function showHeader() - { - $this->elementStart('div', array('id' => 'header')); - $this->showLogo(); - $this->showPrimaryNav(); - $this->elementEnd('div'); - } } diff --git a/lib/info.php b/lib/info.php new file mode 100644 index 000000000..395c6522e --- /dev/null +++ b/lib/info.php @@ -0,0 +1,118 @@ +<?php + +/** + * Information action + * + * PHP version 5 + * + * @category Action + * @package StatusNet + * @author Zach Copley <zach@status.net> + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://status.net/ + * + * StatusNet - the distributed open-source microblogging tool + * Copyright (C) 2010, StatusNet, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +if (!defined('STATUSNET') && !defined('LACONICA')) { + exit(1); +} + +/** + * Base class for displaying dialog box like messages to the user + * + * @category Action + * @package StatusNet + * @author Zach Copley <zach@status.net> + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://status.net/ + * + * @see ErrorAction + */ + +class InfoAction extends Action +{ + var $message = null; + + function __construct($title, $message, $output='php://output', $indent=null) + { + parent::__construct($output, $indent); + + $this->message = $message; + $this->title = $title; + + // XXX: hack alert: usually we aren't going to + // call this page directly, but because it's + // an action it needs an args array anyway + $this->prepare($_REQUEST); + } + + /** + * Page title. + * + * @return page title + */ + + function title() + { + return empty($this->title) ? '' : $this->title; + } + + function isReadOnly($args) + { + return true; + } + + // Overload a bunch of stuff so the page isn't too bloated + + function showBody() + { + $this->elementStart('body', array('id' => 'error')); + $this->elementStart('div', array('id' => 'wrap')); + $this->showHeader(); + $this->showCore(); + $this->showFooter(); + $this->elementEnd('div'); + $this->elementEnd('body'); + } + + function showCore() + { + $this->elementStart('div', array('id' => 'core')); + $this->showContentBlock(); + $this->elementEnd('div'); + } + + function showHeader() + { + $this->elementStart('div', array('id' => 'header')); + $this->showLogo(); + $this->showPrimaryNav(); + $this->elementEnd('div'); + } + + /** + * Display content. + * + * @return nothing + */ + function showContent() + { + $this->element('div', array('class' => 'info'), $this->message); + } + +} diff --git a/lib/installer.php b/lib/installer.php index 2eff2d85a..c046eadea 100644 --- a/lib/installer.php +++ b/lib/installer.php @@ -85,7 +85,11 @@ abstract class Installer $config = INSTALLDIR.'/config.php'; if (file_exists($config)) { if (!is_writable($config) || filesize($config) > 0) { - $this->warning('Config file "config.php" already exists.'); + if (filesize($config) == 0) { + $this->warning('Config file "config.php" already exists and is empty, but is not writable.'); + } else { + $this->warning('Config file "config.php" already exists.'); + } $pass = false; } } diff --git a/lib/oauthstore.php b/lib/oauthstore.php index f3ee629fd..1c8e72500 100644 --- a/lib/oauthstore.php +++ b/lib/oauthstore.php @@ -55,6 +55,17 @@ class StatusNetOAuthDataStore extends OAuthDataStore } } + function getTokenByKey($token_key) + { + $t = new Token(); + $t->tok = $token_key; + if ($t->find(true)) { + return $t; + } else { + return null; + } + } + // http://oauth.net/core/1.0/#nonce // "The Consumer SHALL then generate a Nonce value that is unique for // all requests with that timestamp." @@ -317,13 +328,18 @@ class StatusNetOAuthDataStore extends OAuthDataStore function add_avatar($profile, $url) { $temp_filename = tempnam(sys_get_temp_dir(), 'listener_avatar'); - copy($url, $temp_filename); - $imagefile = new ImageFile($profile->id, $temp_filename); - $filename = Avatar::filename($profile->id, - image_type_to_extension($imagefile->type), - null, - common_timestamp()); - rename($temp_filename, Avatar::path($filename)); + try { + copy($url, $temp_filename); + $imagefile = new ImageFile($profile->id, $temp_filename); + $filename = Avatar::filename($profile->id, + image_type_to_extension($imagefile->type), + null, + common_timestamp()); + rename($temp_filename, Avatar::path($filename)); + } catch (Exception $e) { + unlink($temp_filename); + throw $e; + } return $profile->setOriginal($filename); } diff --git a/lib/right.php b/lib/right.php index deb451fde..bacbea5f2 100644 --- a/lib/right.php +++ b/lib/right.php @@ -60,5 +60,6 @@ class Right const MAKEGROUPADMIN = 'makegroupadmin'; const GRANTROLE = 'grantrole'; const REVOKEROLE = 'revokerole'; + const DELETEGROUP = 'deletegroup'; } diff --git a/lib/router.php b/lib/router.php index 00b299373..b1cc8d529 100644 --- a/lib/router.php +++ b/lib/router.php @@ -276,7 +276,7 @@ class Router $m->connect('group/new', array('action' => 'newgroup')); - foreach (array('edit', 'join', 'leave') as $v) { + foreach (array('edit', 'join', 'leave', 'delete') as $v) { $m->connect('group/:nickname/'.$v, array('action' => $v.'group'), array('nickname' => '[a-zA-Z0-9]+')); diff --git a/lib/servererroraction.php b/lib/servererroraction.php index 9b5a553dc..54cc99099 100644 --- a/lib/servererroraction.php +++ b/lib/servererroraction.php @@ -96,4 +96,27 @@ class ServerErrorAction extends ErrorAction $this->showPage(); } + + /** + * To specify additional HTTP headers for the action + * + * @return void + */ + function extraHeaders() + { + $status_string = @self::$status[$this->code]; + header('HTTP/1.1 '.$this->code.' '.$status_string); + } + + /** + * Page title. + * + * @return page title + */ + + function title() + { + return @self::$status[$this->code]; + } + } diff --git a/lib/serverexception.php b/lib/serverexception.php index 7dc9765ad..0dfbd04ff 100644 --- a/lib/serverexception.php +++ b/lib/serverexception.php @@ -22,7 +22,7 @@ * @category Exception * @package StatusNet * @author Evan Prodromou <evan@status.net> - * @copyright 2008 StatusNet, Inc. + * @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/ */ diff --git a/lib/statusnet.php b/lib/statusnet.php index 7212a4a47..7cb831696 100644 --- a/lib/statusnet.php +++ b/lib/statusnet.php @@ -336,8 +336,11 @@ class StatusNet foreach ($config_files as $_config_file) { if (@file_exists($_config_file)) { - include($_config_file); - self::$have_config = true; + // Ignore 0-byte config files + if (filesize($_config_file) > 0) { + include($_config_file); + self::$have_config = true; + } } } diff --git a/lib/util.php b/lib/util.php index 35fcfdb09..c05fcf15a 100644 --- a/lib/util.php +++ b/lib/util.php @@ -919,7 +919,12 @@ function common_shorten_links($text, $always = false) function common_validate_utf8($str) { // preg_replace will return NULL on invalid UTF-8 input. - return preg_replace('//u', '', $str); + // + // Note: empty regex //u also caused NULL return on some + // production machines, but none of our test machines. + // + // This should be replaced with a more reliable check. + return preg_replace('/\x00/u', '', $str); } /** |