diff options
Diffstat (limited to 'actions')
30 files changed, 571 insertions, 1522 deletions
diff --git a/actions/all.php b/actions/all.php index f1786462e..61cedce74 100644 --- a/actions/all.php +++ b/actions/all.php @@ -99,19 +99,17 @@ class AllAction extends ProfileAction sprintf(_('Feed for friends of %s (RSS 1.0)'), $this->user->nickname)), new Feed(Feed::RSS2, common_local_url( - 'api', array( - 'apiaction' => 'statuses', - 'method' => 'friends_timeline', - 'argument' => $this->user->nickname.'.rss' + 'ApiTimelineFriends', array( + 'format' => 'rss', + 'id' => $this->user->nickname ) ), sprintf(_('Feed for friends of %s (RSS 2.0)'), $this->user->nickname)), new Feed(Feed::ATOM, common_local_url( - 'api', array( - 'apiaction' => 'statuses', - 'method' => 'friends_timeline', - 'argument' => $this->user->nickname.'.atom' + 'ApiTimelineFriends', array( + 'format' => 'atom', + 'id' => $this->user->nickname ) ), sprintf(_('Feed for friends of %s (Atom)'), $this->user->nickname)) diff --git a/actions/apidirectmessagenew.php b/actions/apidirectmessagenew.php index fa6cafbe8..ca1ee70dd 100644 --- a/actions/apidirectmessagenew.php +++ b/actions/apidirectmessagenew.php @@ -157,7 +157,7 @@ class ApiDirectMessageNewAction extends ApiAuthAction // Note: sending msgs to yourself is allowed by Twitter $errmsg = 'Don\'t send a message to yourself; ' . - 'just say it to yourself quietly instead.' + 'just say it to yourself quietly instead.'; $this->clientError(_($errmsg), 403, $this->format); return; diff --git a/actions/apifavoritecreate.php b/actions/apifavoritecreate.php index a80a6492e..436739770 100644 --- a/actions/apifavoritecreate.php +++ b/actions/apifavoritecreate.php @@ -127,7 +127,7 @@ class ApiFavoriteCreateAction extends ApiAuthAction if (empty($fave)) { $this->clientError( - _('Could not create favorite.') + _('Could not create favorite.'), 403, $this->format ); diff --git a/actions/apistatusesupdate.php b/actions/apistatusesupdate.php index 0d71e1512..898a4bd72 100644 --- a/actions/apistatusesupdate.php +++ b/actions/apistatusesupdate.php @@ -38,6 +38,7 @@ if (!defined('STATUSNET')) { } require_once INSTALLDIR . '/lib/apiauth.php'; +require_once INSTALLDIR . '/lib/mediafile.php'; /** * Updates the authenticating user's status (posts a notice). @@ -60,7 +61,6 @@ class ApiStatusesUpdateAction extends ApiAuthAction var $source = null; var $status = null; var $in_reply_to_status_id = null; - static $reserved_sources = array('web', 'omb', 'mail', 'xmpp', 'api'); /** @@ -76,25 +76,8 @@ class ApiStatusesUpdateAction extends ApiAuthAction { parent::prepare($args); - $this->user = $this->auth_user; - - if (empty($this->user)) { - $this->clientError(_('No such user!'), 404, $this->format); - return false; - } - + $this->user = $this->auth_user; $this->status = $this->trimmed('status'); - - if (empty($this->status)) { - $this->clientError( - 'Client must provide a \'status\' parameter with a value.', - 400, - $this->format - ); - - return false; - } - $this->source = $this->trimmed('source'); if (empty($this->source) || in_array($source, $this->reserved_sources)) { @@ -129,6 +112,27 @@ class ApiStatusesUpdateAction extends ApiAuthAction return; } + if (empty($this->status)) { + $this->clientError( + 'Client must provide a \'status\' parameter with a value.', + 400, + $this->format + ); + return; + } + + if (empty($this->user)) { + $this->clientError(_('No such user!'), 404, $this->format); + return; + } + + // Workaround for PHP returning empty $_FILES when POST length > PHP settings + + if (empty($_POST) && ($_SERVER['CONTENT_LENGTH'] > 0)) { + $this->clientError(_('Unable to handle that much POST data!')); + return; + } + $status_shortened = common_shorten_links($this->status); if (Notice::contentTooLong($status_shortened)) { @@ -187,14 +191,40 @@ class ApiStatusesUpdateAction extends ApiAuthAction } } + $upload = null; + + try { + $upload = MediaFile::fromUpload('media', $this->user); + } catch (ClientException $ce) { + $this->clientError($ce->getMessage()); + return; + } + + if (isset($upload)) { + $status_shortened .= ' ' . $upload->shortUrl(); + + if (Notice::contentTooLong($status_shortened)) { + $upload->delete(); + $msg = _( + 'Max notice size is %d chars, ' . + 'including attachment URL.' + ); + $this->clientError(sprintf($msg, Notice::maxContent())); + } + } + $this->notice = Notice::saveNew( $this->user->id, - html_entity_decode($this->status, ENT_NOQUOTES, 'UTF-8'), + html_entity_decode($status_shortened, ENT_NOQUOTES, 'UTF-8'), $this->source, 1, $reply_to ); + if (isset($upload)) { + $upload->attachToNotice($this->notice); + } + common_broadcast_notice($this->notice); } diff --git a/actions/bookmarklet.php b/actions/bookmarklet.php new file mode 100644 index 000000000..0603a7456 --- /dev/null +++ b/actions/bookmarklet.php @@ -0,0 +1,75 @@ +<?php +/** + * StatusNet, the distributed open-source microblogging tool + * + * Handler for posting new notices + * + * 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 Bookmarklet + * @package StatusNet + * @author Sarven Capadisli <csarven@status.net> + * @copyright 2008-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 . '/actions/newnotice.php'; + +/** + * Action for posting a notice + * + * @category Bookmarklet + * @package StatusNet + * @author Sarven Capadisli <csarven@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/ + */ + +class BookmarkletAction extends NewnoticeAction +{ + function showTitle() + { + $this->element('title', null, _('Post to ').common_config('site', 'name')); + } + + function showHeader() + { + $this->elementStart('div', array('id' => 'header')); + $this->elementStart('address'); + $this->element('a', array('class' => 'url', + 'href' => common_local_url('public')), + ''); + $this->elementEnd('address'); + if (common_logged_in()) { + $this->showNoticeForm(); + } + $this->elementEnd('div'); + } + + function showCore() + { + } + + function showFooter() + { + } +} + diff --git a/actions/emailsettings.php b/actions/emailsettings.php index 6eff06c0d..67b991cdc 100644 --- a/actions/emailsettings.php +++ b/actions/emailsettings.php @@ -326,7 +326,7 @@ class EmailsettingsAction extends AccountSettingsAction $this->showForm(_('Cannot normalize that email address')); return; } - if (!Validate::email($email, true)) { + if (!Validate::email($email, common_config('email', 'check_domain'))) { $this->showForm(_('Not a valid email address')); return; } else if ($user->email == $email) { diff --git a/actions/facebookhome.php b/actions/facebookhome.php deleted file mode 100644 index 70f205205..000000000 --- a/actions/facebookhome.php +++ /dev/null @@ -1,275 +0,0 @@ -<?php -/* - * StatusNet - the distributed open-source microblogging tool - * Copyright (C) 2008, 2009, 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); } - -require_once INSTALLDIR.'/lib/facebookaction.php'; - -class FacebookhomeAction extends FacebookAction -{ - - var $page = null; - - function prepare($argarray) - { - parent::prepare($argarray); - - $this->page = $this->trimmed('page'); - - if (!$this->page) { - $this->page = 1; - } - - return true; - } - - function handle($args) - { - parent::handle($args); - - // If the user has opted not to initially allow the app to have - // Facebook status update permission, store that preference. Only - // promt the user the first time she uses the app - if ($this->arg('skip') || $args['fb_sig_request_method'] == 'GET') { - $this->facebook->api_client->data_setUserPreference( - FACEBOOK_PROMPTED_UPDATE_PREF, 'true'); - } - - if ($this->flink) { - - $this->user = $this->flink->getUser(); - - // If this is the first time the user has started the app - // prompt for Facebook status update permission - if (!$this->facebook->api_client->users_hasAppPermission('publish_stream')) { - - if ($this->facebook->api_client->data_getUserPreference( - FACEBOOK_PROMPTED_UPDATE_PREF) != 'true') { - $this->getUpdatePermission(); - return; - } - } - - // Make sure the user's profile box has the lastest notice - $notice = $this->user->getCurrentNotice(); - if ($notice) { - $this->updateProfileBox($notice); - } - - if ($this->arg('status_submit') == 'Send') { - $this->saveNewNotice(); - } - - // User is authenticated and has already been prompted once for - // Facebook status update permission? Then show the main page - // of the app - $this->showPage(); - - } else { - - // User hasn't authenticated yet, prompt for creds - $this->login(); - } - - } - - function login() - { - - $this->showStylesheets(); - - $nickname = common_canonical_nickname($this->trimmed('nickname')); - $password = $this->arg('password'); - - $msg = null; - - if ($nickname) { - - if (common_check_user($nickname, $password)) { - - $user = User::staticGet('nickname', $nickname); - - if (!$user) { - $this->showLoginForm(_("Server error - couldn't get user!")); - } - - $flink = DB_DataObject::factory('foreign_link'); - $flink->user_id = $user->id; - $flink->foreign_id = $this->fbuid; - $flink->service = FACEBOOK_SERVICE; - $flink->created = common_sql_now(); - $flink->set_flags(true, false, false, false); - - $flink_id = $flink->insert(); - - // XXX: Do some error handling here - - $this->setDefaults(); - - $this->getUpdatePermission(); - return; - - } else { - $msg = _('Incorrect username or password.'); - } - } - - $this->showLoginForm($msg); - $this->showFooter(); - - } - - function setDefaults() - { - $this->facebook->api_client->data_setUserPreference( - FACEBOOK_PROMPTED_UPDATE_PREF, 'false'); - } - - function showNoticeForm() - { - $post_action = "$this->app_uri/index.php"; - - $notice_form = new FacebookNoticeForm($this, $post_action, null, - $post_action, $this->user); - $notice_form->show(); - } - - function title() - { - if ($this->page > 1) { - return sprintf(_("%s and friends, page %d"), $this->user->nickname, $this->page); - } else { - return sprintf(_("%s and friends"), $this->user->nickname); - } - } - - function showContent() - { - $notice = $this->user->noticeInbox(($this->page-1) * NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1); - - $nl = new NoticeList($notice, $this); - - $cnt = $nl->show(); - - $this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE, - $this->page, 'index.php', array('nickname' => $this->user->nickname)); - } - - function showNoticeList($notice) - { - - $nl = new NoticeList($notice, $this); - return $nl->show(); - } - - function getUpdatePermission() { - - $this->showStylesheets(); - - $this->elementStart('div', array('class' => 'facebook_guide')); - - $instructions = sprintf(_('If you would like the %s app to automatically update ' . - 'your Facebook status with your latest notice, you need ' . - 'to give it permission.'), $this->app_name); - - $this->elementStart('p'); - $this->element('span', array('id' => 'permissions_notice'), $instructions); - $this->elementEnd('p'); - - $this->elementStart('form', array('method' => 'post', - 'action' => "index.php", - 'id' => 'facebook-skip-permissions')); - - $this->elementStart('ul', array('id' => 'fb-permissions-list')); - $this->elementStart('li', array('id' => 'fb-permissions-item')); - - $next = urlencode("$this->app_uri/index.php"); - $api_key = common_config('facebook', 'apikey'); - - $auth_url = 'http://www.facebook.com/authorize.php?api_key=' . - $api_key . '&v=1.0&ext_perm=publish_stream&next=' . $next . - '&next_cancel=' . $next . '&submit=skip'; - - $this->elementStart('span', array('class' => 'facebook-button')); - $this->element('a', array('href' => $auth_url), - sprintf(_('Okay, do it!'), $this->app_name)); - $this->elementEnd('span'); - - $this->elementEnd('li'); - - $this->elementStart('li', array('id' => 'fb-permissions-item')); - $this->submit('skip', _('Skip')); - $this->elementEnd('li'); - $this->elementEnd('ul'); - - $this->elementEnd('form'); - $this->elementEnd('div'); - - } - - /** - * Generate pagination links - * - * @param boolean $have_before is there something before? - * @param boolean $have_after is there something after? - * @param integer $page current page - * @param string $action current action - * @param array $args rest of query arguments - * - * @return nothing - */ - function pagination($have_before, $have_after, $page, $action, $args=null) - { - - // Does a little before-after block for next/prev page - - // XXX: Fix so this uses common_local_url() if possible. - - if ($have_before || $have_after) { - $this->elementStart('div', array('class' => 'pagination')); - $this->elementStart('dl', null); - $this->element('dt', null, _('Pagination')); - $this->elementStart('dd', null); - $this->elementStart('ul', array('class' => 'nav')); - } - if ($have_before) { - $pargs = array('page' => $page-1); - $newargs = $args ? array_merge($args, $pargs) : $pargs; - $this->elementStart('li', array('class' => 'nav_prev')); - $this->element('a', array('href' => "$action?page=$newargs[page]", 'rel' => 'prev'), - _('After')); - $this->elementEnd('li'); - } - if ($have_after) { - $pargs = array('page' => $page+1); - $newargs = $args ? array_merge($args, $pargs) : $pargs; - $this->elementStart('li', array('class' => 'nav_next')); - $this->element('a', array('href' => "$action?page=$newargs[page]", 'rel' => 'next'), - _('Before')); - $this->elementEnd('li'); - } - if ($have_before || $have_after) { - $this->elementEnd('ul'); - $this->elementEnd('dd'); - $this->elementEnd('dl'); - $this->elementEnd('div'); - } - } - -} diff --git a/actions/facebookinvite.php b/actions/facebookinvite.php deleted file mode 100644 index 6dfc9d688..000000000 --- a/actions/facebookinvite.php +++ /dev/null @@ -1,145 +0,0 @@ -<?php -/* - * StatusNet - the distributed open-source microblogging tool - * Copyright (C) 2008, 2009, 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); -} - -require_once(INSTALLDIR.'/lib/facebookaction.php'); - -class FacebookinviteAction extends FacebookAction -{ - - function handle($args) - { - parent::handle($args); - $this->showForm(); - } - - /** - * Wrapper for showing a page - * - * Stores an error and shows the page - * - * @param string $error Error, if any - * - * @return void - */ - - function showForm($error=null) - { - $this->error = $error; - $this->showPage(); - } - - /** - * Show the page content - * - * Either shows the registration form or, if registration was successful, - * instructions for using the site. - * - * @return void - */ - - function showContent() - { - if ($this->arg('ids')) { - $this->showSuccessContent(); - } else { - $this->showFormContent(); - } - } - - function showSuccessContent() - { - - $this->element('h2', null, sprintf(_('Thanks for inviting your friends to use %s'), - common_config('site', 'name'))); - $this->element('p', null, _('Invitations have been sent to the following users:')); - - $friend_ids = $_POST['ids']; // XXX: Hmm... is this the best way to access the list? - - $this->elementStart('ul', array('id' => 'facebook-friends')); - - foreach ($friend_ids as $friend) { - $this->elementStart('li'); - $this->element('fb:profile-pic', array('uid' => $friend, 'size' => 'square')); - $this->element('fb:name', array('uid' => $friend, - 'capitalize' => 'true')); - $this->elementEnd('li'); - } - - $this->elementEnd("ul"); - - } - - function showFormContent() - { - $content = sprintf(_('You have been invited to %s'), common_config('site', 'name')) . - htmlentities('<fb:req-choice url="' . $this->app_uri . '" label="Add"/>'); - - $this->elementStart('fb:request-form', array('action' => 'invite.php', - 'method' => 'post', - 'invite' => 'true', - 'type' => common_config('site', 'name'), - 'content' => $content)); - $this->hidden('invite', 'true'); - $actiontext = sprintf(_('Invite your friends to use %s'), common_config('site', 'name')); - - $multi_params = array('showborder' => 'false'); - $multi_params['actiontext'] = $actiontext; - $multi_params['bypass'] = 'cancel'; - - // Get a list of users who are already using the app for exclusion - $exclude_ids = $this->facebook->api_client->friends_getAppUsers(); - $exclude_ids_csv = null; - - // fbml needs these as a csv string, not an array - if ($exclude_ids) { - $exclude_ids_csv = implode(',', $exclude_ids); - $multi_params['exclude_ids'] = $exclude_ids_csv; - } - - $this->element('fb:multi-friend-selector', $multi_params); - $this->elementEnd('fb:request-form'); - - if ($exclude_ids) { - - $this->element('h2', null, sprintf(_('Friends already using %s:'), - common_config('site', 'name'))); - $this->elementStart('ul', array('id' => 'facebook-friends')); - - foreach ($exclude_ids as $friend) { - $this->elementStart('li'); - $this->element('fb:profile-pic', array('uid' => $friend, 'size' => 'square')); - $this->element('fb:name', array('uid' => $friend, - 'capitalize' => 'true')); - $this->elementEnd('li'); - } - - $this->elementEnd("ul"); - } - } - - function title() - { - return sprintf(_('Send invitations')); - } - -} diff --git a/actions/facebooklogin.php b/actions/facebooklogin.php deleted file mode 100644 index 8ac2477ab..000000000 --- a/actions/facebooklogin.php +++ /dev/null @@ -1,101 +0,0 @@ -<?php -/* - * StatusNet - the distributed open-source microblogging tool - * Copyright (C) 2008, 2009, 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); } - -require_once(INSTALLDIR.'/lib/facebookaction.php'); - -class FacebookinviteAction extends FacebookAction -{ - - function handle($args) - { - parent::handle($args); - - $this->error = $error; - - if ($this->flink) { - if (!$this->facebook->api_client->users_hasAppPermission('publish_stream') && - $this->facebook->api_client->data_getUserPreference( - FACEBOOK_PROMPTED_UPDATE_PREF) == 'true') { - - echo '<h1>REDIRECT TO HOME</h1>'; - } - } else { - $this->showPage(); - } - } - - - function showContent() - { - - // If the user has opted not to initially allow the app to have - // Facebook status update permission, store that preference. Only - // promt the user the first time she uses the app - if ($this->arg('skip')) { - $this->facebook->api_client->data_setUserPreference( - FACEBOOK_PROMPTED_UPDATE_PREF, 'true'); - } - - if ($this->flink) { - - $this->user = $this->flink->getUser(); - - // If this is the first time the user has started the app - // prompt for Facebook status update permission - if (!$this->facebook->api_client->users_hasAppPermission('publish_stream')) { - - if ($this->facebook->api_client->data_getUserPreference( - FACEBOOK_PROMPTED_UPDATE_PREF) != 'true') { - $this->getUpdatePermission(); - return; - } - } - - } else { - $this->showLoginForm(); - } - - } - - function showSuccessContent() - { - - - - } - - function showFormContent() - { - - - } - - function title() - { - return sprintf(_('Login')); - } - - function redirectHome() - { - - } - -} diff --git a/actions/facebookremove.php b/actions/facebookremove.php deleted file mode 100644 index ae231c0fb..000000000 --- a/actions/facebookremove.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php -/* - * StatusNet - the distributed open-source microblogging tool - * Copyright (C) 2008, 2009, 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); } - -require_once INSTALLDIR.'/lib/facebookaction.php'; - -class FacebookremoveAction extends FacebookAction -{ - - function handle($args) - { - parent::handle($args); - - $secret = common_config('facebook', 'secret'); - - $sig = ''; - - ksort($_POST); - - foreach ($_POST as $key => $val) { - if (substr($key, 0, 7) == 'fb_sig_') { - $sig .= substr($key, 7) . '=' . $val; - } - } - - $sig .= $secret; - $verify = md5($sig); - - if ($verify == $this->arg('fb_sig')) { - - $flink = Foreign_link::getByForeignID($this->arg('fb_sig_user'), 2); - - common_debug("Removing foreign link to Facebook - local user ID: $flink->user_id, Facebook ID: $flink->foreign_id"); - - $result = $flink->delete(); - - if (!$result) { - common_log_db_error($flink, 'DELETE', __FILE__); - $this->serverError(_('Couldn\'t remove Facebook user.')); - return; - } - - } else { - # Someone bad tried to remove facebook link? - common_log(LOG_ERR, "Someone from $_SERVER[REMOTE_ADDR] " . - 'unsuccessfully tried to remove a foreign link to Facebook!'); - } - } - -} diff --git a/actions/facebooksettings.php b/actions/facebooksettings.php deleted file mode 100644 index 84bdde910..000000000 --- a/actions/facebooksettings.php +++ /dev/null @@ -1,150 +0,0 @@ -<?php -/* - * StatusNet - the distributed open-source microblogging tool - * Copyright (C) 2008, 2009, 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); } - -require_once INSTALLDIR.'/lib/facebookaction.php'; - -class FacebooksettingsAction extends FacebookAction -{ - - function handle($args) - { - parent::handle($args); - $this->showPage(); - } - - /** - * Show the page content - * - * Either shows the registration form or, if registration was successful, - * instructions for using the site. - * - * @return void - */ - - function showContent() - { - if ($this->arg('save')) { - $this->saveSettings(); - } else { - $this->showForm(); - } - } - - function saveSettings() { - - $noticesync = $this->arg('noticesync'); - $replysync = $this->arg('replysync'); - $prefix = $this->trimmed('prefix'); - - $original = clone($this->flink); - $this->flink->set_flags($noticesync, $replysync, false, false); - $result = $this->flink->update($original); - - $this->facebook->api_client->data_setUserPreference(FACEBOOK_NOTICE_PREFIX, - substr($prefix, 0, 128)); - - if ($result === false) { - $this->showForm(_('There was a problem saving your sync preferences!')); - } else { - $this->showForm(_('Sync preferences saved.'), true); - } - } - - function showForm($msg = null, $success = false) { - - if ($msg) { - if ($success) { - $this->element('fb:success', array('message' => $msg)); - } else { - $this->element('fb:error', array('message' => $msg)); - } - } - - if ($this->facebook->api_client->users_hasAppPermission('publish_stream')) { - - $this->elementStart('form', array('method' => 'post', - 'id' => 'facebook_settings')); - - $this->elementStart('ul', 'form_data'); - - $this->elementStart('li'); - - $this->checkbox('noticesync', _('Automatically update my Facebook status with my notices.'), - ($this->flink) ? ($this->flink->noticesync & FOREIGN_NOTICE_SEND) : true); - - $this->elementEnd('li'); - - $this->elementStart('li'); - - $this->checkbox('replysync', _('Send "@" replies to Facebook.'), - ($this->flink) ? ($this->flink->noticesync & FOREIGN_NOTICE_SEND_REPLY) : true); - - $this->elementEnd('li'); - - $this->elementStart('li'); - - $prefix = $this->facebook->api_client->data_getUserPreference(FACEBOOK_NOTICE_PREFIX); - - $this->input('prefix', _('Prefix'), - ($prefix) ? $prefix : null, - _('A string to prefix notices with.')); - - $this->elementEnd('li'); - - $this->elementStart('li'); - - $this->submit('save', _('Save')); - - $this->elementEnd('li'); - - $this->elementEnd('ul'); - - $this->elementEnd('form'); - - } else { - - $instructions = sprintf(_('If you would like %s to automatically update ' . - 'your Facebook status with your latest notice, you need ' . - 'to give it permission.'), $this->app_name); - - $this->elementStart('p'); - $this->element('span', array('id' => 'permissions_notice'), $instructions); - $this->elementEnd('p'); - - $this->elementStart('ul', array('id' => 'fb-permissions-list')); - $this->elementStart('li', array('id' => 'fb-permissions-item')); - $this->elementStart('fb:prompt-permission', array('perms' => 'publish_stream', - 'next_fbjs' => 'document.setLocation(\'' . "$this->app_uri/settings.php" . '\')')); - $this->element('span', array('class' => 'facebook-button'), - sprintf(_('Allow %s to update my Facebook status'), common_config('site', 'name'))); - $this->elementEnd('fb:prompt-permission'); - $this->elementEnd('li'); - $this->elementEnd('ul'); - } - - } - - function title() - { - return _('Sync preferences'); - } - -} diff --git a/actions/getfile.php b/actions/getfile.php new file mode 100644 index 000000000..ecda34c0f --- /dev/null +++ b/actions/getfile.php @@ -0,0 +1,145 @@ +<?php +/** + * StatusNet, the distributed open-source microblogging tool + * + * Returns a given file attachment, allowing private sites to only allow + * access to file attachments after login. + * + * 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 Personal + * @package StatusNet + * @author Jeffery To <jeffery.to@gmail.com> + * @copyright 2008-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 'MIME/Type.php'; + +/** + * Action for getting a file attachment + * + * @category Personal + * @package StatusNet + * @author Jeffery To <jeffery.to@gmail.com> + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +class GetfileAction extends Action +{ + /** + * Path of file to return + */ + + var $path = null; + + /** + * Get file name + * + * @param array $args $_REQUEST array + * + * @return success flag + */ + + function prepare($args) + { + parent::prepare($args); + + $filename = $this->trimmed('filename'); + $path = null; + + if ($filename) { + $path = common_config('attachments', 'dir') . $filename; + } + + if (empty($path) or !file_exists($path)) { + $this->clientError(_('No such file.'), 404); + return false; + } + if (!is_readable($path)) { + $this->clientError(_('Cannot read file.'), 403); + return false; + } + + $this->path = $path; + return true; + } + + /** + * Is this page read-only? + * + * @return boolean true + */ + + function isReadOnly($args) + { + return true; + } + + /** + * Last-modified date for file + * + * @return int last-modified date as unix timestamp + */ + + function lastModified() + { + return filemtime($this->path); + } + + /** + * etag for file + * + * This returns the same data (inode, size, mtime) as Apache would, + * but in decimal instead of hex. + * + * @return string etag http header + */ + function etag() + { + $stat = stat($this->path); + return '"' . $stat['ino'] . '-' . $stat['size'] . '-' . $stat['mtime'] . '"'; + } + + /** + * Handle input, produce output + * + * @param array $args $_REQUEST contents + * + * @return void + */ + + function handle($args) + { + // undo headers set by PHP sessions + $sec = session_cache_expire() * 60; + header('Expires: ' . date(DATE_RFC1123, time() + $sec)); + header('Cache-Control: public, max-age=' . $sec); + header('Pragma: public'); + + parent::handle($args); + + $path = $this->path; + header('Content-Type: ' . MIME_Type::autoDetect($path)); + readfile($path); + } +} diff --git a/actions/groupmembers.php b/actions/groupmembers.php index dcbdd3759..b326a0df7 100644 --- a/actions/groupmembers.php +++ b/actions/groupmembers.php @@ -179,9 +179,12 @@ class GroupMemberListItem extends ProfileListItem function showActions() { $this->startActions(); - $this->showSubscribeButton(); - $this->showMakeAdminForm(); - $this->showGroupBlockForm(); + if (Event::handle('StartProfileListItemActionElements', array($this))) { + $this->showSubscribeButton(); + $this->showMakeAdminForm(); + $this->showGroupBlockForm(); + Event::handle('EndProfileListItemActionElements', array($this)); + } $this->endActions(); } diff --git a/actions/invite.php b/actions/invite.php index 788130c58..3015202e9 100644 --- a/actions/invite.php +++ b/actions/invite.php @@ -68,7 +68,7 @@ class InviteAction extends CurrentUserDesignAction foreach ($addresses as $email) { $email = trim($email); - if (!Validate::email($email, true)) { + if (!Validate::email($email, common_config('email', 'check_domain'))) { $this->showForm(sprintf(_('Invalid email address: %s'), $email)); return; } diff --git a/actions/newmessage.php b/actions/newmessage.php index a0b17fc18..37fca1ca2 100644 --- a/actions/newmessage.php +++ b/actions/newmessage.php @@ -99,7 +99,9 @@ class NewmessageAction extends Action $user = common_current_user(); if (!$user) { - $this->clientError(_('Only logged-in users can send direct messages.'), 403); + /* Go log in, and then come back. */ + common_set_returnto($_SERVER['REQUEST_URI']); + common_redirect(common_local_url('login')); return false; } @@ -221,7 +223,22 @@ class NewmessageAction extends Action } $this->msg = $msg; - $this->showPage(); + if ($this->trimmed('ajax')) { + $this->startHTML('text/xml;charset=UTF-8'); + $this->elementStart('head'); + $this->element('title', null, _('New message')); + $this->elementEnd('head'); + $this->elementStart('body'); + if (common_logged_in()) { + $this->showNoticeForm(); + } + $this->elementEnd('div'); + $this->elementEnd('body'); + $this->endHTML(); + } + else { + $this->showPage(); + } } function showPageNotice() diff --git a/actions/newnotice.php b/actions/newnotice.php index 9ee031f93..fbd7ab6bc 100644 --- a/actions/newnotice.php +++ b/actions/newnotice.php @@ -33,7 +33,8 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } -require_once INSTALLDIR.'/lib/noticelist.php'; +require_once INSTALLDIR . '/lib/noticelist.php'; +require_once INSTALLDIR . '/lib/mediafile.php'; /** * Action for posting new notices @@ -113,33 +114,6 @@ class NewnoticeAction extends Action } } - function getUploadedFileType() { - require_once 'MIME/Type.php'; - - $cmd = &PEAR::getStaticProperty('MIME_Type', 'fileCmd'); - $cmd = common_config('attachments', 'filecommand'); - - $filetype = MIME_Type::autoDetect($_FILES['attach']['tmp_name']); - if (in_array($filetype, common_config('attachments', 'supported'))) { - return $filetype; - } - $media = MIME_Type::getMedia($filetype); - if ('application' !== $media) { - $hint = sprintf(_(' Try using another %s format.'), $media); - } else { - $hint = ''; - } - $this->clientError(sprintf( - _('%s is not a supported filetype on this server.'), $filetype) . $hint); - } - - function isRespectsQuota($user) { - $file = new File; - $ret = $file->isRespectsQuota($user,$_FILES['attach']['size']); - if (true === $ret) return true; - $this->clientError($ret); - } - /** * Save a new notice, based on arguments * @@ -160,18 +134,12 @@ class NewnoticeAction extends Action if (!$content) { $this->clientError(_('No content!')); - } else { - $content_shortened = common_shorten_links($content); - if (Notice::contentTooLong($content_shortened)) { - $this->clientError(sprintf(_('That\'s too long. '. - 'Max notice size is %d chars.'), - Notice::maxContent())); - } + return; } $inter = new CommandInterpreter(); - $cmd = $inter->handle_command($user, $content_shortened); + $cmd = $inter->handle_command($user, $content); if ($cmd) { if ($this->boolean('ajax')) { @@ -182,6 +150,13 @@ class NewnoticeAction extends Action return; } + $content_shortened = common_shorten_links($content); + if (Notice::contentTooLong($content_shortened)) { + $this->clientError(sprintf(_('That\'s too long. '. + 'Max notice size is %d chars.'), + Notice::maxContent())); + } + $replyto = $this->trimmed('inreplyto'); #If an ID of 0 is wrongly passed here, it will cause a database error, #so override it... @@ -189,84 +164,37 @@ class NewnoticeAction extends Action $replyto = 'false'; } - if (isset($_FILES['attach']['error'])) { - switch ($_FILES['attach']['error']) { - case UPLOAD_ERR_NO_FILE: - // no file uploaded, nothing to do - break; - - case UPLOAD_ERR_OK: - $mimetype = $this->getUploadedFileType(); - if (!$this->isRespectsQuota($user)) { - die('clientError() should trigger an exception before reaching here.'); - } - break; - - case UPLOAD_ERR_INI_SIZE: - $this->clientError(_('The uploaded file exceeds the upload_max_filesize directive in php.ini.')); - - case UPLOAD_ERR_FORM_SIZE: - $this->clientError(_('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.')); + $upload = null; + $upload = MediaFile::fromUpload('attach'); - case UPLOAD_ERR_PARTIAL: - $this->clientError(_('The uploaded file was only partially uploaded.')); + if (isset($upload)) { - case UPLOAD_ERR_NO_TMP_DIR: - $this->clientError(_('Missing a temporary folder.')); - - case UPLOAD_ERR_CANT_WRITE: - $this->clientError(_('Failed to write file to disk.')); - - case UPLOAD_ERR_EXTENSION: - $this->clientError(_('File upload stopped by extension.')); - - default: - die('Should never reach here.'); - } - } - - if (isset($mimetype)) { - $filename = $this->saveFile($mimetype); - if (empty($filename)) { - $this->clientError(_('Couldn\'t save file.')); - } - - $fileRecord = $this->storeFile($filename, $mimetype); - - $fileurl = common_local_url('attachment', - array('attachment' => $fileRecord->id)); - - // not sure this is necessary -- Zach - $this->maybeAddRedir($fileRecord->id, $fileurl); - - $short_fileurl = common_shorten_url($fileurl); - if (!$short_fileurl) { - // todo -- Consider forcing default shortener if none selected? - $short_fileurl = $fileurl; - } - $content_shortened .= ' ' . $short_fileurl; + $content_shortened .= ' ' . $upload->shortUrl(); if (Notice::contentTooLong($content_shortened)) { - $this->deleteFile($filename); - $this->clientError(sprintf(_('Max notice size is %d chars, including attachment URL.'), - Notice::maxContent())); + $upload->delete(); + $this->clientError( + sprintf( + _('Max notice size is %d chars, including attachment URL.'), + Notice::maxContent() + ) + ); } - - // Also, not sure this is necessary -- Zach - $this->maybeAddRedir($fileRecord->id, $short_fileurl); } $notice = Notice::saveNew($user->id, $content_shortened, 'web', 1, ($replyto == 'false') ? null : $replyto); - if (isset($mimetype)) { - $this->attachFile($notice, $fileRecord); + if (isset($upload)) { + $upload->attachToNotice($notice); } common_broadcast_notice($notice); if ($this->boolean('ajax')) { - $this->startHTML('text/xml;charset=utf-8'); + header('Content-Type: text/xml;charset=utf-8'); + $this->xw->startDocument('1.0', 'UTF-8'); + $this->elementStart('html'); $this->elementStart('head'); $this->element('title', null, _('Notice posted')); $this->elementEnd('head'); @@ -288,87 +216,6 @@ class NewnoticeAction extends Action } } - function saveFile($mimetype) { - - $cur = common_current_user(); - - if (empty($cur)) { - $this->serverError(_('Somehow lost the login in saveFile')); - } - - $basename = basename($_FILES['attach']['name']); - - $filename = File::filename($cur->getProfile(), $basename, $mimetype); - - $filepath = File::path($filename); - - if (move_uploaded_file($_FILES['attach']['tmp_name'], $filepath)) { - return $filename; - } else { - $this->clientError(_('File could not be moved to destination directory.')); - } - } - - function deleteFile($filename) - { - $filepath = File::path($filename); - @unlink($filepath); - } - - function storeFile($filename, $mimetype) { - - $file = new File; - $file->filename = $filename; - - $file->url = File::url($filename); - - $filepath = File::path($filename); - - $file->size = filesize($filepath); - $file->date = time(); - $file->mimetype = $mimetype; - - $file_id = $file->insert(); - - if (!$file_id) { - common_log_db_error($file, "INSERT", __FILE__); - $this->clientError(_('There was a database error while saving your file. Please try again.')); - } - - return $file; - } - - function rememberFile($file, $short) - { - $this->maybeAddRedir($file->id, $short); - } - - function maybeAddRedir($file_id, $url) - { - $file_redir = File_redirection::staticGet('url', $url); - - if (empty($file_redir)) { - $file_redir = new File_redirection; - $file_redir->url = $url; - $file_redir->file_id = $file_id; - - $result = $file_redir->insert(); - - if (!$result) { - common_log_db_error($file_redir, "INSERT", __FILE__); - $this->clientError(_('There was a database error while saving your file. Please try again.')); - } - } - } - - function attachFile($notice, $filerec) - { - File_to_post::processNew($filerec->id, $notice->id); - - $this->maybeAddRedir($filerec->id, - common_local_url('file', array('notice' => $notice->id))); - } - /** * Show an Ajax-y error message * diff --git a/actions/othersettings.php b/actions/othersettings.php index 011b4fc83..d32a2d651 100644 --- a/actions/othersettings.php +++ b/actions/othersettings.php @@ -103,7 +103,7 @@ class OthersettingsAction extends AccountSettingsAction foreach($_shorteners as $name=>$value) { $services[$name]=$name; - if($value['info']['freeService']){ + if(!empty($value['info']['freeService'])){ // I18N $services[$name].=' (free service)'; } diff --git a/actions/profilesettings.php b/actions/profilesettings.php index 5445d9bb2..0a0cc5997 100644 --- a/actions/profilesettings.php +++ b/actions/profilesettings.php @@ -306,6 +306,16 @@ class ProfilesettingsAction extends AccountSettingsAction $profile->homepage = $homepage; $profile->bio = $bio; $profile->location = $location; + + $loc = Location::fromName($location); + + if (!empty($loc)) { + $profile->lat = $loc->lat; + $profile->lon = $loc->lon; + $profile->location_id = $loc->location_id; + $profile->location_ns = $loc->location_ns; + } + $profile->profileurl = common_profile_url($nickname); common_debug('Old profile: ' . common_log_objstring($orig_profile), __FILE__); diff --git a/actions/public.php b/actions/public.php index 73fad182a..982dfde15 100644 --- a/actions/public.php +++ b/actions/public.php @@ -131,6 +131,13 @@ class PublicAction extends Action return _('Public timeline'); } } + + function extraHead() + { + parent::extraHead(); + $this->element('meta', array('http-equiv' => 'X-XRDS-Location', + 'content' => common_local_url('publicxrds'))); + } /** * Output <head> elements for RSS and Atom feeds @@ -143,14 +150,12 @@ class PublicAction extends Action return array(new Feed(Feed::RSS1, common_local_url('publicrss'), _('Public Stream Feed (RSS 1.0)')), new Feed(Feed::RSS2, - common_local_url('api', - array('apiaction' => 'statuses', - 'method' => 'public_timeline.rss')), + common_local_url('ApiTimelinePublic', + array('format' => 'rss')), _('Public Stream Feed (RSS 2.0)')), new Feed(Feed::ATOM, - common_local_url('api', - array('apiaction' => 'statuses', - 'method' => 'public_timeline.atom')), + common_local_url('ApiTimelinePublic', + array('format' => 'atom')), _('Public Stream Feed (Atom)'))); } diff --git a/actions/publicxrds.php b/actions/publicxrds.php new file mode 100644 index 000000000..5fd4eead7 --- /dev/null +++ b/actions/publicxrds.php @@ -0,0 +1,81 @@ +<?php + +/** + * Public XRDS for OpenID + * + * PHP version 5 + * + * @category Action + * @package StatusNet + * @author Evan Prodromou <evan@status.net> + * @author Robin Millette <millette@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) 2008, 2009, 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); +} + +require_once INSTALLDIR.'/plugins/OpenID/openid.php'; +require_once INSTALLDIR.'/lib/xrdsoutputter.php'; + +/** + * Public XRDS + * + * @category Action + * @package StatusNet + * @author Evan Prodromou <evan@status.net> + * @author Robin Millette <millette@status.net> + * @author Craig Andrews <candrews@integralblue.com> + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://status.net/ + * + * @todo factor out similarities with XrdsAction + */ +class PublicxrdsAction extends Action +{ + /** + * Is read only? + * + * @return boolean true + */ + function isReadOnly($args) + { + return true; + } + + /** + * Class handler. + * + * @param array $args array of arguments + * + * @return nothing + */ + function handle($args) + { + parent::handle($args); + $xrdsOutputter = new XRDSOutputter(); + $xrdsOutputter->startXRDS(); + Event::handle('StartPublicXRDS', array($this,&$xrdsOutputter)); + Event::handle('EndPublicXRDS', array($this,&$xrdsOutputter)); + $xrdsOutputter->endXRDS(); + } +} + diff --git a/actions/register.php b/actions/register.php index 100ab7424..a6c1a903a 100644 --- a/actions/register.php +++ b/actions/register.php @@ -191,7 +191,7 @@ class RegisterAction extends Action if (!$this->boolean('license')) { $this->showForm(_('You can\'t register if you don\'t '. 'agree to the license.')); - } else if ($email && !Validate::email($email, true)) { + } else if ($email && !Validate::email($email, common_config('email', 'check_domain'))) { $this->showForm(_('Not a valid email address.')); } else if (!Validate::string($nickname, array('min_length' => 1, 'max_length' => 64, diff --git a/actions/replies.php b/actions/replies.php index 6003ad30b..a13b5a227 100644 --- a/actions/replies.php +++ b/actions/replies.php @@ -138,11 +138,25 @@ class RepliesAction extends OwnerDesignAction function getFeeds() { - $rssurl = common_local_url('repliesrss', - array('nickname' => $this->user->nickname)); - $rsstitle = sprintf(_('Feed for replies to %s'), $this->user->nickname); - - return array(new Feed(Feed::RSS1, $rssurl, $rsstitle)); + return array(new Feed(Feed::RSS1, + common_local_url('repliesrss', + array('nickname' => $this->user->nickname)), + sprintf(_('Replies feed for %s (RSS 1.0)'), + $this->user->nickname)), + new Feed(Feed::RSS2, + common_local_url('ApiTimelineMentions', + array( + 'id' => $this->user->nickname, + 'format' => 'rss')), + sprintf(_('Replies feed for %s (RSS 2.0)'), + $this->user->nickname)), + new Feed(Feed::ATOM, + common_local_url('ApiTimelineMentions', + array( + 'id' => $this->user->nickname, + 'format' => 'atom')), + sprintf(_('Replies feed for %s (Atom)'), + $this->user->nickname))); } /** diff --git a/actions/showfavorites.php b/actions/showfavorites.php index b96d2af37..b12fcdd9a 100644 --- a/actions/showfavorites.php +++ b/actions/showfavorites.php @@ -164,13 +164,25 @@ class ShowfavoritesAction extends OwnerDesignAction function getFeeds() { - $feedurl = common_local_url('favoritesrss', - array('nickname' => - $this->user->nickname)); - $feedtitle = sprintf(_('Feed for favorites of %s'), - $this->user->nickname); - - return array(new Feed(Feed::RSS1, $feedurl, $feedtitle)); + return array(new Feed(Feed::RSS1, + common_local_url('favoritesrss', + array('nickname' => $this->user->nickname)), + sprintf(_('Feed for favorites of %s (RSS 1.0)'), + $this->user->nickname)), + new Feed(Feed::RSS2, + common_local_url('ApiTimelineFavorites', + array( + 'id' => $this->user->nickname, + 'format' => 'rss')), + sprintf(_('Feed for favorites of %s (RSS 2.0)'), + $this->user->nickname)), + new Feed(Feed::ATOM, + common_local_url('ApiTimelineFavorites', + array( + 'id' => $this->user->nickname, + 'format' => 'atom')), + sprintf(_('Feed for favorites of %s (Atom)'), + $this->user->nickname))); } /** diff --git a/actions/showgroup.php b/actions/showgroup.php index bfe45ddad..a4af29391 100644 --- a/actions/showgroup.php +++ b/actions/showgroup.php @@ -328,17 +328,15 @@ class ShowgroupAction extends GroupDesignAction sprintf(_('Notice feed for %s group (RSS 1.0)'), $this->group->nickname)), new Feed(Feed::RSS2, - common_local_url('api', - array('apiaction' => 'groups', - 'method' => 'timeline', - 'argument' => $this->group->nickname.'.rss')), + common_local_url('ApiTimelineGroup', + array('format' => 'rss', + 'id' => $this->group->nickname)), sprintf(_('Notice feed for %s group (RSS 2.0)'), $this->group->nickname)), new Feed(Feed::ATOM, - common_local_url('api', - array('apiaction' => 'groups', - 'method' => 'timeline', - 'argument' => $this->group->nickname.'.atom')), + common_local_url('ApiTimelineGroup', + array('format' => 'atom', + 'id' => $this->group->nickname)), sprintf(_('Notice feed for %s group (Atom)'), $this->group->nickname)), new Feed(Feed::FOAF, diff --git a/actions/shownotice.php b/actions/shownotice.php index 41408c23c..5d16fdad9 100644 --- a/actions/shownotice.php +++ b/actions/shownotice.php @@ -172,9 +172,9 @@ class ShownoticeAction extends OwnerDesignAction function title() { if (!empty($this->profile->fullname)) { - $base = $this->profile->fullname . ' (' . $this->user->nickname . ') '; + $base = $this->profile->fullname . ' (' . $this->profile->nickname . ') '; } else { - $base = $this->user->nickname; + $base = $this->profile->nickname; } return sprintf(_('%1$s\'s status on %2$s'), diff --git a/actions/showstream.php b/actions/showstream.php index b3a9b1f05..4f4806037 100644 --- a/actions/showstream.php +++ b/actions/showstream.php @@ -128,17 +128,17 @@ class ShowstreamAction extends ProfileAction sprintf(_('Notice feed for %s (RSS 1.0)'), $this->user->nickname)), new Feed(Feed::RSS2, - common_local_url('api', - array('apiaction' => 'statuses', - 'method' => 'user_timeline', - 'argument' => $this->user->nickname.'.rss')), + common_local_url('ApiTimelineUser', + array( + 'id' => $this->user->nickname, + 'format' => 'rss')), sprintf(_('Notice feed for %s (RSS 2.0)'), $this->user->nickname)), new Feed(Feed::ATOM, - common_local_url('api', - array('apiaction' => 'statuses', - 'method' => 'user_timeline', - 'argument' => $this->user->nickname.'.atom')), + common_local_url('ApiTimelineUser', + array( + 'id' => $this->user->nickname, + 'format' => 'atom')), sprintf(_('Notice feed for %s (Atom)'), $this->user->nickname)), new Feed(Feed::FOAF, @@ -348,6 +348,8 @@ class ShowstreamAction extends ProfileAction { if (Event::handle('StartProfilePageActionsSection', array(&$this, $this->profile))) { + $cur = common_current_user(); + $this->elementStart('div', 'entity_actions'); $this->element('h2', null, _('User actions')); $this->elementStart('ul'); @@ -379,21 +381,21 @@ class ShowstreamAction extends ProfileAction } $this->elementEnd('li'); - if ($cur->mutuallySubscribed($user)) { + if ($cur->mutuallySubscribed($this->user)) { // message $this->elementStart('li', 'entity_send-a-message'); - $this->element('a', array('href' => common_local_url('newmessage', array('to' => $user->id)), + $this->element('a', array('href' => common_local_url('newmessage', array('to' => $this->user->id)), 'title' => _('Send a direct message to this user')), _('Message')); $this->elementEnd('li'); // nudge - if ($user->email && $user->emailnotifynudge) { + if ($this->user->email && $this->user->emailnotifynudge) { $this->elementStart('li', 'entity_nudge'); - $nf = new NudgeForm($this, $user); + $nf = new NudgeForm($this, $this->user); $nf->show(); $this->elementEnd('li'); } diff --git a/actions/tag.php b/actions/tag.php index f0ab30308..3a88c1229 100644 --- a/actions/tag.php +++ b/actions/tag.php @@ -86,17 +86,15 @@ class TagAction extends Action sprintf(_('Notice feed for tag %s (RSS 1.0)'), $this->tag)), new Feed(Feed::RSS2, - common_local_url('api', - array('apiaction' => 'tags', - 'method' => 'timeline', - 'argument' => $this->tag.'.rss')), - sprintf(_('Notice feed for %s group (RSS 2.0)'), + common_local_url('ApiTimelineTag', + array('format' => 'rss', + 'tag' => $this->tag)), + sprintf(_('Notice feed for tag %s (RSS 2.0)'), $this->tag)), new Feed(Feed::ATOM, - common_local_url('api', - array('apiaction' => 'tags', - 'method' => 'timeline', - 'argument' => $this->tag.'.atom')), + common_local_url('ApiTimelineTag', + array('format' => 'atom', + 'tag' => $this->tag)), sprintf(_('Notice feed for tag %s (Atom)'), $this->tag))); } diff --git a/actions/twitterauthorization.php b/actions/twitterauthorization.php deleted file mode 100644 index 630ac426f..000000000 --- a/actions/twitterauthorization.php +++ /dev/null @@ -1,201 +0,0 @@ -<?php -/** - * StatusNet, the distributed open-source microblogging tool - * - * Class for doing OAuth authentication against Twitter - * - * 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 TwitterauthorizationAction - * @package StatusNet - * @author Zach Copely <zach@status.net> - * @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); -} - -class TwitterauthorizationAction extends Action -{ - - function prepare($args) - { - parent::prepare($args); - - $this->oauth_token = $this->arg('oauth_token'); - - return true; - } - - /** - * Handler method - * - * @param array $args is ignored since it's now passed in in prepare() - * - * @return nothing - */ - function handle($args) - { - parent::handle($args); - - if (!common_logged_in()) { - $this->clientError(_('Not logged in.'), 403); - } - - $user = common_current_user(); - $flink = Foreign_link::getByUserID($user->id, TWITTER_SERVICE); - - // If there's already a foreign link record, it means we already - // have an access token, and this is unecessary. So go back. - - if (isset($flink)) { - common_redirect(common_local_url('twittersettings')); - } - - // $this->oauth_token is only populated once Twitter authorizes our - // request token. If it's empty we're at the beginning of the auth - // process - - if (empty($this->oauth_token)) { - $this->authorizeRequestToken(); - } else { - $this->saveAccessToken(); - } - } - - /** - * Asks Twitter for a request token, and then redirects to Twitter - * to authorize it. - * - * @return nothing - */ - function authorizeRequestToken() - { - try { - - // Get a new request token and authorize it - - $client = new TwitterOAuthClient(); - $req_tok = - $client->getRequestToken(TwitterOAuthClient::$requestTokenURL); - - // Sock the request token away in the session temporarily - - $_SESSION['twitter_request_token'] = $req_tok->key; - $_SESSION['twitter_request_token_secret'] = $req_tok->secret; - - $auth_link = $client->getAuthorizeLink($req_tok); - - } catch (TwitterOAuthClientException $e) { - $msg = sprintf('OAuth client cURL error - code: %1s, msg: %2s', - $e->getCode(), $e->getMessage()); - $this->serverError(_('Couldn\'t link your Twitter account.')); - } - - common_redirect($auth_link); - } - - /** - * Called when Twitter returns an authorized request token. Exchanges - * it for an access token and stores it. - * - * @return nothing - */ - function saveAccessToken() - { - - // Check to make sure Twitter returned the same request - // token we sent them - - if ($_SESSION['twitter_request_token'] != $this->oauth_token) { - $this->serverError(_('Couldn\'t link your Twitter account.')); - } - - try { - - $client = new TwitterOAuthClient($_SESSION['twitter_request_token'], - $_SESSION['twitter_request_token_secret']); - - // Exchange the request token for an access token - - $atok = $client->getAccessToken(TwitterOAuthClient::$accessTokenURL); - - // Test the access token and get the user's Twitter info - - $client = new TwitterOAuthClient($atok->key, $atok->secret); - $twitter_user = $client->verifyCredentials(); - - } catch (OAuthClientException $e) { - $msg = sprintf('OAuth client cURL error - code: %1$s, msg: %2$s', - $e->getCode(), $e->getMessage()); - $this->serverError(_('Couldn\'t link your Twitter account.')); - } - - // Save the access token and Twitter user info - - $this->saveForeignLink($atok, $twitter_user); - - // Clean up the the mess we made in the session - - unset($_SESSION['twitter_request_token']); - unset($_SESSION['twitter_request_token_secret']); - - common_redirect(common_local_url('twittersettings')); - } - - /** - * Saves a Foreign_link between Twitter user and local user, - * which includes the access token and secret. - * - * @param OAuthToken $access_token the access token to save - * @param mixed $twitter_user twitter API user object - * - * @return nothing - */ - function saveForeignLink($access_token, $twitter_user) - { - $user = common_current_user(); - - $flink = new Foreign_link(); - - $flink->user_id = $user->id; - $flink->foreign_id = $twitter_user->id; - $flink->service = TWITTER_SERVICE; - - $creds = TwitterOAuthClient::packToken($access_token); - - $flink->credentials = $creds; - $flink->created = common_sql_now(); - - // Defaults: noticesync on, everything else off - - $flink->set_flags(true, false, false, false); - - $flink_id = $flink->insert(); - - if (empty($flink_id)) { - common_log_db_error($flink, 'INSERT', __FILE__); - $this->serverError(_('Couldn\'t link your Twitter account.')); - } - - save_twitter_user($twitter_user->id, $twitter_user->screen_name); - } - -} - diff --git a/actions/twittersettings.php b/actions/twittersettings.php deleted file mode 100644 index 89169941e..000000000 --- a/actions/twittersettings.php +++ /dev/null @@ -1,277 +0,0 @@ -<?php -/** - * StatusNet, the distributed open-source microblogging tool - * - * Settings for Twitter integration - * - * 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 Settings - * @package StatusNet - * @author Evan Prodromou <evan@status.net> - * @copyright 2008-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/connectsettingsaction.php'; -require_once INSTALLDIR.'/lib/twitter.php'; - -/** - * Settings for Twitter integration - * - * @category Settings - * @package StatusNet - * @author Evan Prodromou <evan@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 SettingsAction - */ - -class TwittersettingsAction extends ConnectSettingsAction -{ - /** - * Title of the page - * - * @return string Title of the page - */ - - function title() - { - return _('Twitter settings'); - } - - /** - * Instructions for use - * - * @return instructions for use - */ - - function getInstructions() - { - return _('Connect your Twitter account to share your updates ' . - 'with your Twitter friends and vice-versa.'); - } - - /** - * Content area of the page - * - * Shows a form for associating a Twitter account with this - * StatusNet account. Also lets the user set preferences. - * - * @return void - */ - - function showContent() - { - if (!common_config('twitter', 'enabled')) { - $this->element('div', array('class' => 'error'), - _('Twitter is not available.')); - return; - } - - $user = common_current_user(); - - $profile = $user->getProfile(); - - $fuser = null; - - $flink = Foreign_link::getByUserID($user->id, TWITTER_SERVICE); - - if (!empty($flink)) { - $fuser = $flink->getForeignUser(); - } - - $this->elementStart('form', array('method' => 'post', - 'id' => 'form_settings_twitter', - 'class' => 'form_settings', - 'action' => - common_local_url('twittersettings'))); - - $this->hidden('token', common_session_token()); - - $this->elementStart('fieldset', array('id' => 'settings_twitter_account')); - - if (empty($fuser)) { - $this->elementStart('ul', 'form_data'); - $this->elementStart('li', array('id' => 'settings_twitter_login_button')); - $this->element('a', array('href' => common_local_url('twitterauthorization')), - 'Connect my Twitter account'); - $this->elementEnd('li'); - $this->elementEnd('ul'); - - $this->elementEnd('fieldset'); - } else { - $this->element('legend', null, _('Twitter account')); - $this->elementStart('p', array('id' => 'form_confirmed')); - $this->element('a', array('href' => $fuser->uri), $fuser->nickname); - $this->elementEnd('p'); - $this->element('p', 'form_note', - _('Connected Twitter account')); - - $this->submit('remove', _('Remove')); - - $this->elementEnd('fieldset'); - - $this->elementStart('fieldset', array('id' => 'settings_twitter_preferences')); - - $this->element('legend', null, _('Preferences')); - $this->elementStart('ul', 'form_data'); - $this->elementStart('li'); - $this->checkbox('noticesend', - _('Automatically send my notices to Twitter.'), - ($flink) ? - ($flink->noticesync & FOREIGN_NOTICE_SEND) : - true); - $this->elementEnd('li'); - $this->elementStart('li'); - $this->checkbox('replysync', - _('Send local "@" replies to Twitter.'), - ($flink) ? - ($flink->noticesync & FOREIGN_NOTICE_SEND_REPLY) : - true); - $this->elementEnd('li'); - $this->elementStart('li'); - $this->checkbox('friendsync', - _('Subscribe to my Twitter friends here.'), - ($flink) ? - ($flink->friendsync & FOREIGN_FRIEND_RECV) : - false); - $this->elementEnd('li'); - - if (common_config('twitterbridge','enabled')) { - $this->elementStart('li'); - $this->checkbox('noticerecv', - _('Import my Friends Timeline.'), - ($flink) ? - ($flink->noticesync & FOREIGN_NOTICE_RECV) : - false); - $this->elementEnd('li'); - } else { - // preserve setting even if bidrection bridge toggled off - - if ($flink && ($flink->noticesync & FOREIGN_NOTICE_RECV)) { - $this->hidden('noticerecv', true, 'noticerecv'); - } - } - - $this->elementEnd('ul'); - - if ($flink) { - $this->submit('save', _('Save')); - } else { - $this->submit('add', _('Add')); - } - - $this->elementEnd('fieldset'); - } - - $this->elementEnd('form'); - } - - /** - * Handle posts to this form - * - * Based on the button that was pressed, muxes out to other functions - * to do the actual task requested. - * - * All sub-functions reload the form with a message -- success or failure. - * - * @return void - */ - - function handlePost() - { - // CSRF protection - $token = $this->trimmed('token'); - if (!$token || $token != common_session_token()) { - $this->showForm(_('There was a problem with your session token. '. - 'Try again, please.')); - return; - } - - if ($this->arg('save')) { - $this->savePreferences(); - } else if ($this->arg('remove')) { - $this->removeTwitterAccount(); - } else { - $this->showForm(_('Unexpected form submission.')); - } - } - - /** - * Disassociate an existing Twitter account from this account - * - * @return void - */ - - function removeTwitterAccount() - { - $user = common_current_user(); - $flink = Foreign_link::getByUserID($user->id, TWITTER_SERVICE); - - $result = $flink->delete(); - - if (empty($result)) { - common_log_db_error($flink, 'DELETE', __FILE__); - $this->serverError(_('Couldn\'t remove Twitter user.')); - return; - } - - $this->showForm(_('Twitter account removed.'), true); - } - - /** - * Save user's Twitter-bridging preferences - * - * @return void - */ - - function savePreferences() - { - $noticesend = $this->boolean('noticesend'); - $noticerecv = $this->boolean('noticerecv'); - $friendsync = $this->boolean('friendsync'); - $replysync = $this->boolean('replysync'); - - $user = common_current_user(); - $flink = Foreign_link::getByUserID($user->id, TWITTER_SERVICE); - - if (empty($flink)) { - common_log_db_error($flink, 'SELECT', __FILE__); - $this->showForm(_('Couldn\'t save Twitter preferences.')); - return; - } - - $original = clone($flink); - $flink->set_flags($noticesend, $noticerecv, $replysync, $friendsync); - $result = $flink->update($original); - - if ($result === false) { - common_log_db_error($flink, 'UPDATE', __FILE__); - $this->showForm(_('Couldn\'t save Twitter preferences.')); - return; - } - - $this->showForm(_('Twitter preferences saved.'), true); - } - -} diff --git a/actions/xrds.php b/actions/xrds.php index 8ba89fec0..8f09557d1 100644 --- a/actions/xrds.php +++ b/actions/xrds.php @@ -36,6 +36,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { require_once INSTALLDIR.'/lib/omb.php'; require_once INSTALLDIR.'/extlib/libomb/service_provider.php'; require_once INSTALLDIR.'/extlib/libomb/xrds_mapper.php'; +require_once INSTALLDIR.'/lib/xrdsoutputter.php'; /** * XRDS for OpenMicroBlogging @@ -49,6 +50,8 @@ require_once INSTALLDIR.'/extlib/libomb/xrds_mapper.php'; */ class XrdsAction extends Action { + var $user; + /** * Is read only? * @@ -58,60 +61,87 @@ class XrdsAction extends Action { return true; } - - /** - * Class handler. - * - * @param array $args query arguments - * - * @return void - */ - function handle($args) + + function prepare($args) { - parent::handle($args); + parent::prepare($args); $nickname = $this->trimmed('nickname'); - $user = User::staticGet('nickname', $nickname); - if (!$user) { + $this->user = User::staticGet('nickname', $nickname); + if (!$this->user) { $this->clientError(_('No such user.')); return; } - $this->showXrds($user); + return true; } /** - * Show XRDS for a user. + * Class handler. * - * @param class $user XRDS for this user. + * @param array $args query arguments * * @return void */ - function showXrds($user) + function handle($args) { - $srv = new OMB_Service_Provider(profile_to_omb_profile($user->uri, - $user->getProfile())); - /* Use libomb’s default XRDS Writer. */ - $xrds_writer = null; - $srv->writeXRDS(new Laconica_XRDS_Mapper(), $xrds_writer); - } -} + parent::handle($args); + $xrdsOutputter = new XRDSOutputter(); + $xrdsOutputter->startXRDS(); -class Laconica_XRDS_Mapper implements OMB_XRDS_Mapper -{ - protected $urls; + Event::handle('StartUserXRDS', array($this,&$xrdsOutputter)); - public function __construct() - { - $this->urls = array( - OAUTH_ENDPOINT_REQUEST => 'requesttoken', - OAUTH_ENDPOINT_AUTHORIZE => 'userauthorization', - OAUTH_ENDPOINT_ACCESS => 'accesstoken', - OMB_ENDPOINT_POSTNOTICE => 'postnotice', - OMB_ENDPOINT_UPDATEPROFILE => 'updateprofile'); - } + //oauth + $xrdsOutputter->elementStart('XRD', array('xmlns' => 'xri://$xrd*($v*2.0)', + 'xml:id' => 'oauth', + 'xmlns:simple' => 'http://xrds-simple.net/core/1.0', + 'version' => '2.0')); + $xrdsOutputter->element('Type', null, 'xri://$xrds*simple'); + $xrdsOutputter->showXrdsService(OAUTH_ENDPOINT_REQUEST, + common_local_url('requesttoken'), + array(OAUTH_AUTH_HEADER, OAUTH_POST_BODY, OAUTH_HMAC_SHA1)); + $xrdsOutputter->showXrdsService( OAUTH_ENDPOINT_AUTHORIZE, + common_local_url('userauthorization'), + array(OAUTH_AUTH_HEADER, OAUTH_POST_BODY, OAUTH_HMAC_SHA1), + null, + $this->user->getIdentifierURI()); + $xrdsOutputter->showXrdsService(OAUTH_ENDPOINT_ACCESS, + common_local_url('accesstoken'), + array(OAUTH_AUTH_HEADER, OAUTH_POST_BODY, OAUTH_HMAC_SHA1), + null, + $this->user->getIdentifierURI()); + $xrdsOutputter->showXrdsService(OAUTH_ENDPOINT_RESOURCE, + null, + array(OAUTH_AUTH_HEADER, OAUTH_POST_BODY, OAUTH_HMAC_SHA1), + null, + $this->user->getIdentifierURI()); + $xrdsOutputter->elementEnd('XRD'); + + //omb + $xrdsOutputter->elementStart('XRD', array('xmlns' => 'xri://$xrd*($v*2.0)', + 'xml:id' => 'oauth', + 'xmlns:simple' => 'http://xrds-simple.net/core/1.0', + 'version' => '2.0')); + $xrdsOutputter->element('Type', null, 'xri://$xrds*simple'); + $xrdsOutputter->showXrdsService(OMB_ENDPOINT_POSTNOTICE, + common_local_url('postnotice')); + $xrdsOutputter->showXrdsService(OMB_ENDPOINT_UPDATEPROFILE, + common_local_url('updateprofile')); + $xrdsOutputter->elementEnd('XRD'); + + //misc + $xrdsOutputter->elementStart('XRD', array('xmlns' => 'xri://$xrd*($v*2.0)', + 'xml:id' => 'oauth', + 'xmlns:simple' => 'http://xrds-simple.net/core/1.0', + 'version' => '2.0')); + $xrdsOutputter->showXrdsService(OAUTH_DISCOVERY, + '#oauth'); + $xrdsOutputter->showXrdsService(OMB_VERSION, + '#omb'); + $xrdsOutputter->elementEnd('XRD'); - public function getURL($action) - { - return common_local_url($this->urls[$action]); + Event::handle('EndUserXRDS', array($this,&$xrdsOutputter)); + + $xrdsOutputter->endXRDS(); + } } ?> |