From 5efe588174c71979fc1970353c9a556ea441f138 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 26 Aug 2009 00:59:06 +0000 Subject: Moved the rest of the Twitter stuff into the TwitterBridge plugin --- .../TwitterBridge/daemons/synctwitterfriends.php | 280 +++++++++++ .../TwitterBridge/daemons/twitterqueuehandler.php | 73 +++ .../TwitterBridge/daemons/twitterstatusfetcher.php | 559 +++++++++++++++++++++ 3 files changed, 912 insertions(+) create mode 100755 plugins/TwitterBridge/daemons/synctwitterfriends.php create mode 100755 plugins/TwitterBridge/daemons/twitterqueuehandler.php create mode 100755 plugins/TwitterBridge/daemons/twitterstatusfetcher.php (limited to 'plugins/TwitterBridge/daemons') diff --git a/plugins/TwitterBridge/daemons/synctwitterfriends.php b/plugins/TwitterBridge/daemons/synctwitterfriends.php new file mode 100755 index 000000000..b7be5d043 --- /dev/null +++ b/plugins/TwitterBridge/daemons/synctwitterfriends.php @@ -0,0 +1,280 @@ +#!/usr/bin/env php +. + */ + +define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..')); + +$shortoptions = 'di::'; +$longoptions = array('id::', 'debug'); + +$helptext = << + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +$helptext = <<_id); + } + + /** + * Find all the Twitter foreign links for users who have requested + * automatically subscribing to their Twitter friends locally. + * + * @return array flinks an array of Foreign_link objects + */ + function getObjects() + { + $flinks = array(); + $flink = new Foreign_link(); + + $conn = &$flink->getDatabaseConnection(); + + $flink->service = TWITTER_SERVICE; + $flink->orderBy('last_friendsync'); + $flink->limit(25); // sync this many users during this run + $flink->find(); + + while ($flink->fetch()) { + if (($flink->friendsync & FOREIGN_FRIEND_RECV) == FOREIGN_FRIEND_RECV) { + $flinks[] = clone($flink); + } + } + + $conn->disconnect(); + + global $_DB_DATAOBJECT; + unset($_DB_DATAOBJECT['CONNECTIONS']); + + return $flinks; + } + + function childTask($flink) { + + // Each child ps needs its own DB connection + + // Note: DataObject::getDatabaseConnection() creates + // a new connection if there isn't one already + + $conn = &$flink->getDatabaseConnection(); + + $this->subscribeTwitterFriends($flink); + + $flink->last_friendsync = common_sql_now(); + $flink->update(); + + $conn->disconnect(); + + // XXX: Couldn't find a less brutal way to blow + // away a cached connection + + global $_DB_DATAOBJECT; + unset($_DB_DATAOBJECT['CONNECTIONS']); + } + + function fetchTwitterFriends($flink) + { + $friends = array(); + + $token = TwitterOAuthClient::unpackToken($flink->credentials); + + $client = new TwitterOAuthClient($token->key, $token->secret); + + try { + $friends_ids = $client->friendsIds(); + } catch (OAuthCurlException $e) { + common_log(LOG_WARNING, $this->name() . + ' - cURL error getting friend ids ' . + $e->getCode() . ' - ' . $e->getMessage()); + return $friends; + } + + if (empty($friends_ids)) { + common_debug($this->name() . + " - Twitter user $flink->foreign_id " . + 'doesn\'t have any friends!'); + return $friends; + } + + common_debug($this->name() . ' - Twitter\'s API says Twitter user id ' . + "$flink->foreign_id has " . + count($friends_ids) . ' friends.'); + + // Calculate how many pages to get... + $pages = ceil(count($friends_ids) / 100); + + if ($pages == 0) { + common_debug($this->name() . " - $user seems to have no friends."); + } + + for ($i = 1; $i <= $pages; $i++) { + + try { + $more_friends = $client->statusesFriends(null, null, null, $i); + } catch (OAuthCurlException $e) { + common_log(LOG_WARNING, $this->name() . + ' - cURL error getting Twitter statuses/friends ' . + "page $i - " . $e->getCode() . ' - ' . + $e->getMessage()); + } + + if (empty($more_friends)) { + common_log(LOG_WARNING, $this->name() . + " - Couldn't retrieve page $i " . + "of Twitter user $flink->foreign_id friends."); + continue; + } else { + $friends = array_merge($friends, $more_friends); + } + } + + return $friends; + } + + function subscribeTwitterFriends($flink) + { + $friends = $this->fetchTwitterFriends($flink); + + if (empty($friends)) { + common_debug($this->name() . + ' - Couldn\'t get friends from Twitter for ' . + "Twitter user $flink->foreign_id."); + return false; + } + + $user = $flink->getUser(); + + foreach ($friends as $friend) { + + $friend_name = $friend->screen_name; + $friend_id = (int) $friend->id; + + // Update or create the Foreign_user record for each + // Twitter friend + + if (!save_twitter_user($friend_id, $friend_name)) { + common_log(LOG_WARNING, $this-name() . + " - Couldn't save $screen_name's friend, $friend_name."); + continue; + } + + // Check to see if there's a related local user + + $friend_flink = Foreign_link::getByForeignID($friend_id, + TWITTER_SERVICE); + + if (!empty($friend_flink)) { + + // Get associated user and subscribe her + + $friend_user = User::staticGet('id', $friend_flink->user_id); + + if (!empty($friend_user)) { + $result = subs_subscribe_to($user, $friend_user); + + if ($result === true) { + common_log(LOG_INFO, + $this->name() . ' - Subscribed ' . + "$friend_user->nickname to $user->nickname."); + } else { + common_debug($this->name() . + ' - Tried subscribing ' . + "$friend_user->nickname to $user->nickname - " . + $result); + } + } + } + } + + return true; + } + +} + +$id = null; +$debug = null; + +if (have_option('i')) { + $id = get_option_value('i'); +} else if (have_option('--id')) { + $id = get_option_value('--id'); +} else if (count($args) > 0) { + $id = $args[0]; +} else { + $id = null; +} + +if (have_option('d') || have_option('debug')) { + $debug = true; +} + +$syncer = new SyncTwitterFriendsDaemon($id, 60, 2, $debug); +$syncer->runOnce(); + diff --git a/plugins/TwitterBridge/daemons/twitterqueuehandler.php b/plugins/TwitterBridge/daemons/twitterqueuehandler.php new file mode 100755 index 000000000..9aa9d1ed0 --- /dev/null +++ b/plugins/TwitterBridge/daemons/twitterqueuehandler.php @@ -0,0 +1,73 @@ +#!/usr/bin/env php +. + */ + +define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..')); + +$shortoptions = 'i::'; +$longoptions = array('id::'); + +$helptext = <<log(LOG_INFO, "INITIALIZE"); + return true; + } + + function handle_notice($notice) + { + return broadcast_twitter($notice); + } + + function finish() + { + } + +} + +if (have_option('i')) { + $id = get_option_value('i'); +} else if (have_option('--id')) { + $id = get_option_value('--id'); +} else if (count($args) > 0) { + $id = $args[0]; +} else { + $id = null; +} + +$handler = new TwitterQueueHandler($id); + +$handler->runOnce(); diff --git a/plugins/TwitterBridge/daemons/twitterstatusfetcher.php b/plugins/TwitterBridge/daemons/twitterstatusfetcher.php new file mode 100755 index 000000000..3023bf423 --- /dev/null +++ b/plugins/TwitterBridge/daemons/twitterstatusfetcher.php @@ -0,0 +1,559 @@ +#!/usr/bin/env php +. + */ + +define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..')); + +// Tune number of processes and how often to poll Twitter +// XXX: Should these things be in config.php? +define('MAXCHILDREN', 2); +define('POLL_INTERVAL', 60); // in seconds + +$shortoptions = 'di::'; +$longoptions = array('id::', 'debug'); + +$helptext = << + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +// NOTE: an Avatar path MUST be set in config.php for this +// script to work: e.g.: $config['avatar']['path'] = '/laconica/avatar'; + +class TwitterStatusFetcher extends ParallelizingDaemon +{ + /** + * Constructor + * + * @param string $id the name/id of this daemon + * @param int $interval sleep this long before doing everything again + * @param int $max_children maximum number of child processes at a time + * @param boolean $debug debug output flag + * + * @return void + * + **/ + function __construct($id = null, $interval = 60, + $max_children = 2, $debug = null) + { + parent::__construct($id, $interval, $max_children, $debug); + } + + /** + * Name of this daemon + * + * @return string Name of the daemon. + */ + + function name() + { + return ('twitterstatusfetcher.'.$this->_id); + } + + /** + * Find all the Twitter foreign links for users who have requested + * importing of their friends' timelines + * + * @return array flinks an array of Foreign_link objects + */ + + function getObjects() + { + global $_DB_DATAOBJECT; + + $flink = new Foreign_link(); + $conn = &$flink->getDatabaseConnection(); + + $flink->service = TWITTER_SERVICE; + $flink->orderBy('last_noticesync'); + $flink->find(); + + $flinks = array(); + + while ($flink->fetch()) { + + if (($flink->noticesync & FOREIGN_NOTICE_RECV) == + FOREIGN_NOTICE_RECV) { + $flinks[] = clone($flink); + } + } + + $flink->free(); + unset($flink); + + $conn->disconnect(); + unset($_DB_DATAOBJECT['CONNECTIONS']); + + return $flinks; + } + + function childTask($flink) { + + // Each child ps needs its own DB connection + + // Note: DataObject::getDatabaseConnection() creates + // a new connection if there isn't one already + + $conn = &$flink->getDatabaseConnection(); + + $this->getTimeline($flink); + + $flink->last_friendsync = common_sql_now(); + $flink->update(); + + $conn->disconnect(); + + // XXX: Couldn't find a less brutal way to blow + // away a cached connection + + global $_DB_DATAOBJECT; + unset($_DB_DATAOBJECT['CONNECTIONS']); + } + + function getTimeline($flink) + { + if (empty($flink)) { + common_log(LOG_WARNING, $this->name() . + " - Can't retrieve Foreign_link for foreign ID $fid"); + return; + } + + common_debug($this->name() . ' - Trying to get timeline for Twitter user ' . + $flink->foreign_id); + + // XXX: Biggest remaining issue - How do we know at which status + // to start importing? How many statuses? Right now I'm going + // with the default last 20. + + $token = TwitterOAuthClient::unpackToken($flink->credentials); + + $client = new TwitterOAuthClient($token->key, $token->secret); + + $timeline = null; + + try { + $timeline = $client->statusesFriendsTimeline(); + } catch (OAuthClientCurlException $e) { + common_log(LOG_WARNING, $this->name() . + ' - OAuth client unable to get friends timeline for user ' . + $flink->user_id . ' - code: ' . + $e->getCode() . 'msg: ' . $e->getMessage()); + } + + if (empty($timeline)) { + common_log(LOG_WARNING, $this->name() . " - Empty timeline."); + return; + } + + // Reverse to preserve order + + foreach (array_reverse($timeline) as $status) { + + // Hacktastic: filter out stuff coming from this Laconica + + $source = mb_strtolower(common_config('integration', 'source')); + + if (preg_match("/$source/", mb_strtolower($status->source))) { + common_debug($this->name() . ' - Skipping import of status ' . + $status->id . ' with source ' . $source); + continue; + } + + $this->saveStatus($status, $flink); + } + + // Okay, record the time we synced with Twitter for posterity + + $flink->last_noticesync = common_sql_now(); + $flink->update(); + } + + function saveStatus($status, $flink) + { + $id = $this->ensureProfile($status->user); + + $profile = Profile::staticGet($id); + + if (empty($profile)) { + common_log(LOG_ERR, $this->name() . + ' - Problem saving notice. No associated Profile.'); + return null; + } + + // XXX: change of screen name? + + $uri = 'http://twitter.com/' . $status->user->screen_name . + '/status/' . $status->id; + + $notice = Notice::staticGet('uri', $uri); + + // check to see if we've already imported the status + + if (empty($notice)) { + + $notice = new Notice(); + + $notice->profile_id = $id; + $notice->uri = $uri; + $notice->created = strftime('%Y-%m-%d %H:%M:%S', + strtotime($status->created_at)); + $notice->content = common_shorten_links($status->text); // XXX + $notice->rendered = common_render_content($notice->content, $notice); + $notice->source = 'twitter'; + $notice->reply_to = null; // XXX: lookup reply + $notice->is_local = Notice::GATEWAY; + + if (Event::handle('StartNoticeSave', array(&$notice))) { + $id = $notice->insert(); + Event::handle('EndNoticeSave', array($notice)); + } + } + + if (!Notice_inbox::pkeyGet(array('notice_id' => $notice->id, + 'user_id' => $flink->user_id))) { + // Add to inbox + $inbox = new Notice_inbox(); + + $inbox->user_id = $flink->user_id; + $inbox->notice_id = $notice->id; + $inbox->created = $notice->created; + $inbox->source = NOTICE_INBOX_SOURCE_GATEWAY; // From a private source + + $inbox->insert(); + } + } + + function ensureProfile($user) + { + // check to see if there's already a profile for this user + + $profileurl = 'http://twitter.com/' . $user->screen_name; + $profile = Profile::staticGet('profileurl', $profileurl); + + if (!empty($profile)) { + common_debug($this->name() . + " - Profile for $profile->nickname found."); + + // Check to see if the user's Avatar has changed + + $this->checkAvatar($user, $profile); + return $profile->id; + + } else { + common_debug($this->name() . ' - Adding profile and remote profile ' . + "for Twitter user: $profileurl."); + + $profile = new Profile(); + $profile->query("BEGIN"); + + $profile->nickname = $user->screen_name; + $profile->fullname = $user->name; + $profile->homepage = $user->url; + $profile->bio = $user->description; + $profile->location = $user->location; + $profile->profileurl = $profileurl; + $profile->created = common_sql_now(); + + $id = $profile->insert(); + + if (empty($id)) { + common_log_db_error($profile, 'INSERT', __FILE__); + $profile->query("ROLLBACK"); + return false; + } + + // check for remote profile + + $remote_pro = Remote_profile::staticGet('uri', $profileurl); + + if (empty($remote_pro)) { + + $remote_pro = new Remote_profile(); + + $remote_pro->id = $id; + $remote_pro->uri = $profileurl; + $remote_pro->created = common_sql_now(); + + $rid = $remote_pro->insert(); + + if (empty($rid)) { + common_log_db_error($profile, 'INSERT', __FILE__); + $profile->query("ROLLBACK"); + return false; + } + } + + $profile->query("COMMIT"); + + $this->saveAvatars($user, $id); + + return $id; + } + } + + function checkAvatar($twitter_user, $profile) + { + global $config; + + $path_parts = pathinfo($twitter_user->profile_image_url); + + $newname = 'Twitter_' . $twitter_user->id . '_' . + $path_parts['basename']; + + $oldname = $profile->getAvatar(48)->filename; + + if ($newname != $oldname) { + common_debug($this->name() . ' - Avatar for Twitter user ' . + "$profile->nickname has changed."); + common_debug($this->name() . " - old: $oldname new: $newname"); + + $this->updateAvatars($twitter_user, $profile); + } + + if ($this->missingAvatarFile($profile)) { + common_debug($this->name() . ' - Twitter user ' . + $profile->nickname . + ' is missing one or more local avatars.'); + common_debug($this->name() ." - old: $oldname new: $newname"); + + $this->updateAvatars($twitter_user, $profile); + } + + } + + function updateAvatars($twitter_user, $profile) { + + global $config; + + $path_parts = pathinfo($twitter_user->profile_image_url); + + $img_root = substr($path_parts['basename'], 0, -11); + $ext = $path_parts['extension']; + $mediatype = $this->getMediatype($ext); + + foreach (array('mini', 'normal', 'bigger') as $size) { + $url = $path_parts['dirname'] . '/' . + $img_root . '_' . $size . ".$ext"; + $filename = 'Twitter_' . $twitter_user->id . '_' . + $img_root . "_$size.$ext"; + + $this->updateAvatar($profile->id, $size, $mediatype, $filename); + $this->fetchAvatar($url, $filename); + } + } + + function missingAvatarFile($profile) { + + foreach (array(24, 48, 73) as $size) { + + $filename = $profile->getAvatar($size)->filename; + $avatarpath = Avatar::path($filename); + + if (file_exists($avatarpath) == FALSE) { + return true; + } + } + + return false; + } + + function getMediatype($ext) + { + $mediatype = null; + + switch (strtolower($ext)) { + case 'jpg': + $mediatype = 'image/jpg'; + break; + case 'gif': + $mediatype = 'image/gif'; + break; + default: + $mediatype = 'image/png'; + } + + return $mediatype; + } + + function saveAvatars($user, $id) + { + global $config; + + $path_parts = pathinfo($user->profile_image_url); + $ext = $path_parts['extension']; + $end = strlen('_normal' . $ext); + $img_root = substr($path_parts['basename'], 0, -($end+1)); + $mediatype = $this->getMediatype($ext); + + foreach (array('mini', 'normal', 'bigger') as $size) { + $url = $path_parts['dirname'] . '/' . + $img_root . '_' . $size . ".$ext"; + $filename = 'Twitter_' . $user->id . '_' . + $img_root . "_$size.$ext"; + + if ($this->fetchAvatar($url, $filename)) { + $this->newAvatar($id, $size, $mediatype, $filename); + } else { + common_log(LOG_WARNING, $this->id() . + " - Problem fetching Avatar: $url"); + } + } + } + + function updateAvatar($profile_id, $size, $mediatype, $filename) { + + common_debug($this->name() . " - Updating avatar: $size"); + + $profile = Profile::staticGet($profile_id); + + if (empty($profile)) { + common_debug($this->name() . " - Couldn't get profile: $profile_id!"); + return; + } + + $sizes = array('mini' => 24, 'normal' => 48, 'bigger' => 73); + $avatar = $profile->getAvatar($sizes[$size]); + + // Delete the avatar, if present + + if ($avatar) { + $avatar->delete(); + } + + $this->newAvatar($profile->id, $size, $mediatype, $filename); + } + + function newAvatar($profile_id, $size, $mediatype, $filename) + { + global $config; + + $avatar = new Avatar(); + $avatar->profile_id = $profile_id; + + switch($size) { + case 'mini': + $avatar->width = 24; + $avatar->height = 24; + break; + case 'normal': + $avatar->width = 48; + $avatar->height = 48; + break; + default: + + // Note: Twitter's big avatars are a different size than + // Laconica's (Laconica's = 96) + + $avatar->width = 73; + $avatar->height = 73; + } + + $avatar->original = 0; // we don't have the original + $avatar->mediatype = $mediatype; + $avatar->filename = $filename; + $avatar->url = Avatar::url($filename); + + common_debug($this->name() . " - New filename: $avatar->url"); + + $avatar->created = common_sql_now(); + + $id = $avatar->insert(); + + if (empty($id)) { + common_log_db_error($avatar, 'INSERT', __FILE__); + return null; + } + + common_debug($this->name() . + " - Saved new $size avatar for $profile_id."); + + return $id; + } + + function fetchAvatar($url, $filename) + { + $avatar_dir = INSTALLDIR . '/avatar/'; + + $avatarfile = $avatar_dir . $filename; + + $out = fopen($avatarfile, 'wb'); + if (!$out) { + common_log(LOG_WARNING, $this->name() . + " - Couldn't open file $filename"); + return false; + } + + common_debug($this->name() . " - Fetching Twitter avatar: $url"); + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_FILE, $out); + curl_setopt($ch, CURLOPT_BINARYTRANSFER, true); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0); + $result = curl_exec($ch); + curl_close($ch); + + fclose($out); + + return $result; + } +} + +$id = null; +$debug = null; + +if (have_option('i')) { + $id = get_option_value('i'); +} else if (have_option('--id')) { + $id = get_option_value('--id'); +} else if (count($args) > 0) { + $id = $args[0]; +} else { + $id = null; +} + +if (have_option('d') || have_option('debug')) { + $debug = true; +} + +$fetcher = new TwitterStatusFetcher($id, 60, 2, $debug); +$fetcher->runOnce(); + -- cgit v1.2.3-54-g00ecf From 0fd8e758ade32204b452cc9fd40e071f0ec8c0f6 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 14 Oct 2009 04:50:16 +0000 Subject: Make queuing and daemons work via events --- classes/Avatar.php | 2 +- plugins/TwitterBridge/TwitterBridgePlugin.php | 17 +++++++++++++++++ plugins/TwitterBridge/daemons/synctwitterfriends.php | 10 ++-------- plugins/TwitterBridge/daemons/twitterstatusfetcher.php | 9 ++++----- plugins/TwitterBridge/twitter.php | 3 +++ scripts/getvaliddaemons.php | 9 --------- 6 files changed, 27 insertions(+), 23 deletions(-) (limited to 'plugins/TwitterBridge/daemons') diff --git a/classes/Avatar.php b/classes/Avatar.php index 5e8b315fe..64f105179 100644 --- a/classes/Avatar.php +++ b/classes/Avatar.php @@ -81,7 +81,7 @@ class Avatar extends Memcached_DataObject if (empty($server)) { $server = common_config('site', 'server'); } - + common_debug('path = ' . $path); // XXX: protocol return 'http://'.$server.$path.$filename; diff --git a/plugins/TwitterBridge/TwitterBridgePlugin.php b/plugins/TwitterBridge/TwitterBridgePlugin.php index a8de1c664..69bec0651 100644 --- a/plugins/TwitterBridge/TwitterBridgePlugin.php +++ b/plugins/TwitterBridge/TwitterBridgePlugin.php @@ -97,5 +97,22 @@ class TwitterBridgePlugin extends Plugin } } + function onStartEnqueueNotice($notice, $transports) + { + array_push($transports, 'twitter'); + return true; + } + + function onGetValidDaemons($daemons) + { + array_push($daemons, INSTALLDIR . '/plugins/TwitterBridge/daemons/twitterqueuehandler.php'); + array_push($daemons, INSTALLDIR . '/plugins/TwitterBridge/daemons/synctwitterfriends.php'); + + if (common_config('twitterbridge', 'enabled')) { + array_push($daemons, INSTALLDIR . '/plugins/TwitterBridge/daemons/twitterstatusfetcher.php'); + } + + return true; + } } \ No newline at end of file diff --git a/plugins/TwitterBridge/daemons/synctwitterfriends.php b/plugins/TwitterBridge/daemons/synctwitterfriends.php index 0668c6222..ed2bf48a2 100755 --- a/plugins/TwitterBridge/daemons/synctwitterfriends.php +++ b/plugins/TwitterBridge/daemons/synctwitterfriends.php @@ -33,6 +33,8 @@ END_OF_TRIM_HELP; require_once INSTALLDIR . '/scripts/commandline.inc'; require_once INSTALLDIR . '/lib/parallelizingdaemon.php'; require_once INSTALLDIR . '/plugins/TwitterBridge/twitter.php'; +require_once INSTALLDIR . '/plugins/TwitterBridge/twitterbasicauthclient.php'; +require_once INSTALLDIR . '/plugins/TwitterBridge/twitteroauthclient.php'; /** * Daemon to sync local friends with Twitter friends @@ -45,14 +47,6 @@ require_once INSTALLDIR . '/plugins/TwitterBridge/twitter.php'; * @link http://status.net/ */ -$helptext = <<filename = $filename; $avatar->url = Avatar::url($filename); - common_debug($this->name() . " - New filename: $avatar->url"); - $avatar->created = common_sql_now(); $id = $avatar->insert(); @@ -516,9 +517,7 @@ class TwitterStatusFetcher extends ParallelizingDaemon function fetchAvatar($url, $filename) { - $avatar_dir = INSTALLDIR . '/avatar/'; - - $avatarfile = $avatar_dir . $filename; + $avatarfile = Avatar::path($filename); $out = fopen($avatarfile, 'wb'); if (!$out) { diff --git a/plugins/TwitterBridge/twitter.php b/plugins/TwitterBridge/twitter.php index afc3f55ba..ac1f49c36 100644 --- a/plugins/TwitterBridge/twitter.php +++ b/plugins/TwitterBridge/twitter.php @@ -23,6 +23,9 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { define('TWITTER_SERVICE', 1); // Twitter is foreign_service ID 1 +require_once INSTALLDIR . '/plugins/TwitterBridge/twitterbasicauthclient.php'; +require_once INSTALLDIR . '/plugins/TwitterBridge/twitteroauthclient.php'; + function updateTwitter_user($twitter_id, $screen_name) { $uri = 'http://twitter.com/' . $screen_name; diff --git a/scripts/getvaliddaemons.php b/scripts/getvaliddaemons.php index 6dd019712..7caea1bb7 100755 --- a/scripts/getvaliddaemons.php +++ b/scripts/getvaliddaemons.php @@ -49,15 +49,6 @@ if(common_config('xmpp','enabled')) { $daemons[] = INSTALLDIR.'/scripts/xmppconfirmhandler.php'; } -if(common_config('twitterbridge','enabled')) { - $daemons[] = INSTALLDIR.'/scripts/twitterstatusfetcher.php'; -} - -if (common_config('twitter', 'enabled')) { - $daemons[] = INSTALLDIR.'/scripts/twitterqueuehandler.php'; - $daemons[] = INSTALLDIR.'/scripts/synctwitterfriends.php'; -} - if (common_config('sms', 'enabled')) { $daemons[] = INSTALLDIR.'/scripts/smsqueuehandler.php'; } -- cgit v1.2.3-54-g00ecf From fa37967858c3c29000797e510e5f98aca8ab558f Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 28 Oct 2009 15:29:20 -0400 Subject: Rebuilt HTTPClient class as an extension of PEAR HTTP_Request2 package, adding redirect handling and convenience functions. Caching support will be added in future work after unit tests have been added. * extlib: add PEAR HTTP_Request2 0.4.1 alpha * extlib: update PEAR Net_URL2 to 0.3.0 beta for HTTP_Request2 compatibility * moved direct usage of CURL and file_get_contents to HTTPClient class, excluding external-sourced libraries Note some plugins haven't been tested yet. --- classes/File_redirection.php | 68 +- extlib/HTTP/Request2.php | 844 ++++++++++++++++++ extlib/HTTP/Request2/Adapter.php | 152 ++++ extlib/HTTP/Request2/Adapter/Curl.php | 383 ++++++++ extlib/HTTP/Request2/Adapter/Mock.php | 171 ++++ extlib/HTTP/Request2/Adapter/Socket.php | 971 +++++++++++++++++++++ extlib/HTTP/Request2/Exception.php | 62 ++ extlib/HTTP/Request2/MultipartBody.php | 274 ++++++ extlib/HTTP/Request2/Observer/Log.php | 215 +++++ extlib/HTTP/Request2/Response.php | 549 ++++++++++++ extlib/Net/URL2.php | 471 ++++++---- install.php | 7 + lib/Shorturl_api.php | 23 +- lib/curlclient.php | 179 ---- lib/default.php | 2 - lib/httpclient.php | 180 +++- lib/oauthclient.php | 65 +- lib/ping.php | 14 +- lib/snapshot.php | 21 +- plugins/BlogspamNetPlugin.php | 17 +- plugins/LinkbackPlugin.php | 36 +- plugins/SimpleUrl/SimpleUrlPlugin.php | 11 +- .../TwitterBridge/daemons/synctwitterfriends.php | 4 +- .../TwitterBridge/daemons/twitterstatusfetcher.php | 45 +- plugins/TwitterBridge/twitter.php | 2 +- plugins/TwitterBridge/twitterauthorization.php | 2 +- plugins/TwitterBridge/twitterbasicauthclient.php | 66 +- plugins/WikiHashtagsPlugin.php | 12 +- scripts/enjitqueuehandler.php | 64 +- 29 files changed, 4241 insertions(+), 669 deletions(-) create mode 100644 extlib/HTTP/Request2.php create mode 100644 extlib/HTTP/Request2/Adapter.php create mode 100644 extlib/HTTP/Request2/Adapter/Curl.php create mode 100644 extlib/HTTP/Request2/Adapter/Mock.php create mode 100644 extlib/HTTP/Request2/Adapter/Socket.php create mode 100644 extlib/HTTP/Request2/Exception.php create mode 100644 extlib/HTTP/Request2/MultipartBody.php create mode 100644 extlib/HTTP/Request2/Observer/Log.php create mode 100644 extlib/HTTP/Request2/Response.php delete mode 100644 lib/curlclient.php (limited to 'plugins/TwitterBridge/daemons') diff --git a/classes/File_redirection.php b/classes/File_redirection.php index 79052bf7d..b7945699a 100644 --- a/classes/File_redirection.php +++ b/classes/File_redirection.php @@ -47,18 +47,15 @@ class File_redirection extends Memcached_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE - function _commonCurl($url, $redirs) { - $curlh = curl_init(); - curl_setopt($curlh, CURLOPT_URL, $url); - curl_setopt($curlh, CURLOPT_AUTOREFERER, true); // # setup referer header when folowing redirects - curl_setopt($curlh, CURLOPT_CONNECTTIMEOUT, 10); // # seconds to wait - curl_setopt($curlh, CURLOPT_MAXREDIRS, $redirs); // # max number of http redirections to follow - curl_setopt($curlh, CURLOPT_USERAGENT, USER_AGENT); - curl_setopt($curlh, CURLOPT_FOLLOWLOCATION, true); // Follow redirects - curl_setopt($curlh, CURLOPT_RETURNTRANSFER, true); - curl_setopt($curlh, CURLOPT_FILETIME, true); - curl_setopt($curlh, CURLOPT_HEADER, true); // Include header in output - return $curlh; + static function _commonHttp($url, $redirs) { + $request = new HTTPClient($url); + $request->setConfig(array( + 'connect_timeout' => 10, // # seconds to wait + 'max_redirs' => $redirs, // # max number of http redirections to follow + 'follow_redirects' => true, // Follow redirects + 'store_body' => false, // We won't need body content here. + )); + return $request; } function _redirectWhere_imp($short_url, $redirs = 10, $protected = false) { @@ -82,32 +79,39 @@ class File_redirection extends Memcached_DataObject if(strpos($short_url,'://') === false){ return $short_url; } - $curlh = File_redirection::_commonCurl($short_url, $redirs); - // Don't include body in output - curl_setopt($curlh, CURLOPT_NOBODY, true); - curl_exec($curlh); - $info = curl_getinfo($curlh); - curl_close($curlh); - - if (405 == $info['http_code']) { - $curlh = File_redirection::_commonCurl($short_url, $redirs); - curl_exec($curlh); - $info = curl_getinfo($curlh); - curl_close($curlh); + try { + $request = self::_commonHttp($short_url, $redirs); + // Don't include body in output + $request->setMethod(HTTP_Request2::METHOD_HEAD); + $response = $request->send(); + + if (405 == $response->getCode()) { + // Server doesn't support HEAD method? Can this really happen? + // We'll try again as a GET and ignore the response data. + $request = self::_commonHttp($short_url, $redirs); + $response = $request->send(); + } + } catch (Exception $e) { + // Invalid URL or failure to reach server + return $short_url; } - if (!empty($info['redirect_count']) && File::isProtected($info['url'])) { - return File_redirection::_redirectWhere_imp($short_url, $info['redirect_count'] - 1, true); + if ($response->getRedirectCount() && File::isProtected($response->getUrl())) { + // Bump back up the redirect chain until we find a non-protected URL + return self::_redirectWhere_imp($short_url, $response->getRedirectCount() - 1, true); } - $ret = array('code' => $info['http_code'] - , 'redirects' => $info['redirect_count'] - , 'url' => $info['url']); + $ret = array('code' => $response->getCode() + , 'redirects' => $response->getRedirectCount() + , 'url' => $response->getUrl()); - if (!empty($info['content_type'])) $ret['type'] = $info['content_type']; + $type = $response->getHeader('Content-Type'); + if ($type) $ret['type'] = $type; if ($protected) $ret['protected'] = true; - if (!empty($info['download_content_length'])) $ret['size'] = $info['download_content_length']; - if (isset($info['filetime']) && ($info['filetime'] > 0)) $ret['time'] = $info['filetime']; + $size = $request->getHeader('Content-Length'); // @fixme bytes? + if ($size) $ret['size'] = $size; + $time = $request->getHeader('Last-Modified'); + if ($time) $ret['time'] = strtotime($time); return $ret; } diff --git a/extlib/HTTP/Request2.php b/extlib/HTTP/Request2.php new file mode 100644 index 000000000..e06bb86bc --- /dev/null +++ b/extlib/HTTP/Request2.php @@ -0,0 +1,844 @@ + + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Request2.php 278226 2009-04-03 21:32:48Z avb $ + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** + * A class representing an URL as per RFC 3986. + */ +require_once 'Net/URL2.php'; + +/** + * Exception class for HTTP_Request2 package + */ +require_once 'HTTP/Request2/Exception.php'; + +/** + * Class representing a HTTP request + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @version Release: 0.4.1 + * @link http://tools.ietf.org/html/rfc2616#section-5 + */ +class HTTP_Request2 implements SplSubject +{ + /**#@+ + * Constants for HTTP request methods + * + * @link http://tools.ietf.org/html/rfc2616#section-5.1.1 + */ + const METHOD_OPTIONS = 'OPTIONS'; + const METHOD_GET = 'GET'; + const METHOD_HEAD = 'HEAD'; + const METHOD_POST = 'POST'; + const METHOD_PUT = 'PUT'; + const METHOD_DELETE = 'DELETE'; + const METHOD_TRACE = 'TRACE'; + const METHOD_CONNECT = 'CONNECT'; + /**#@-*/ + + /**#@+ + * Constants for HTTP authentication schemes + * + * @link http://tools.ietf.org/html/rfc2617 + */ + const AUTH_BASIC = 'basic'; + const AUTH_DIGEST = 'digest'; + /**#@-*/ + + /** + * Regular expression used to check for invalid symbols in RFC 2616 tokens + * @link http://pear.php.net/bugs/bug.php?id=15630 + */ + const REGEXP_INVALID_TOKEN = '![\x00-\x1f\x7f-\xff()<>@,;:\\\\"/\[\]?={}\s]!'; + + /** + * Regular expression used to check for invalid symbols in cookie strings + * @link http://pear.php.net/bugs/bug.php?id=15630 + * @link http://cgi.netscape.com/newsref/std/cookie_spec.html + */ + const REGEXP_INVALID_COOKIE = '/[\s,;]/'; + + /** + * Fileinfo magic database resource + * @var resource + * @see detectMimeType() + */ + private static $_fileinfoDb; + + /** + * Observers attached to the request (instances of SplObserver) + * @var array + */ + protected $observers = array(); + + /** + * Request URL + * @var Net_URL2 + */ + protected $url; + + /** + * Request method + * @var string + */ + protected $method = self::METHOD_GET; + + /** + * Authentication data + * @var array + * @see getAuth() + */ + protected $auth; + + /** + * Request headers + * @var array + */ + protected $headers = array(); + + /** + * Configuration parameters + * @var array + * @see setConfig() + */ + protected $config = array( + 'adapter' => 'HTTP_Request2_Adapter_Socket', + 'connect_timeout' => 10, + 'timeout' => 0, + 'use_brackets' => true, + 'protocol_version' => '1.1', + 'buffer_size' => 16384, + 'store_body' => true, + + 'proxy_host' => '', + 'proxy_port' => '', + 'proxy_user' => '', + 'proxy_password' => '', + 'proxy_auth_scheme' => self::AUTH_BASIC, + + 'ssl_verify_peer' => true, + 'ssl_verify_host' => true, + 'ssl_cafile' => null, + 'ssl_capath' => null, + 'ssl_local_cert' => null, + 'ssl_passphrase' => null, + + 'digest_compat_ie' => false + ); + + /** + * Last event in request / response handling, intended for observers + * @var array + * @see getLastEvent() + */ + protected $lastEvent = array( + 'name' => 'start', + 'data' => null + ); + + /** + * Request body + * @var string|resource + * @see setBody() + */ + protected $body = ''; + + /** + * Array of POST parameters + * @var array + */ + protected $postParams = array(); + + /** + * Array of file uploads (for multipart/form-data POST requests) + * @var array + */ + protected $uploads = array(); + + /** + * Adapter used to perform actual HTTP request + * @var HTTP_Request2_Adapter + */ + protected $adapter; + + + /** + * Constructor. Can set request URL, method and configuration array. + * + * Also sets a default value for User-Agent header. + * + * @param string|Net_Url2 Request URL + * @param string Request method + * @param array Configuration for this Request instance + */ + public function __construct($url = null, $method = self::METHOD_GET, array $config = array()) + { + if (!empty($url)) { + $this->setUrl($url); + } + if (!empty($method)) { + $this->setMethod($method); + } + $this->setConfig($config); + $this->setHeader('user-agent', 'HTTP_Request2/0.4.1 ' . + '(http://pear.php.net/package/http_request2) ' . + 'PHP/' . phpversion()); + } + + /** + * Sets the URL for this request + * + * If the URL has userinfo part (username & password) these will be removed + * and converted to auth data. If the URL does not have a path component, + * that will be set to '/'. + * + * @param string|Net_URL2 Request URL + * @return HTTP_Request2 + * @throws HTTP_Request2_Exception + */ + public function setUrl($url) + { + if (is_string($url)) { + $url = new Net_URL2($url); + } + if (!$url instanceof Net_URL2) { + throw new HTTP_Request2_Exception('Parameter is not a valid HTTP URL'); + } + // URL contains username / password? + if ($url->getUserinfo()) { + $username = $url->getUser(); + $password = $url->getPassword(); + $this->setAuth(rawurldecode($username), $password? rawurldecode($password): ''); + $url->setUserinfo(''); + } + if ('' == $url->getPath()) { + $url->setPath('/'); + } + $this->url = $url; + + return $this; + } + + /** + * Returns the request URL + * + * @return Net_URL2 + */ + public function getUrl() + { + return $this->url; + } + + /** + * Sets the request method + * + * @param string + * @return HTTP_Request2 + * @throws HTTP_Request2_Exception if the method name is invalid + */ + public function setMethod($method) + { + // Method name should be a token: http://tools.ietf.org/html/rfc2616#section-5.1.1 + if (preg_match(self::REGEXP_INVALID_TOKEN, $method)) { + throw new HTTP_Request2_Exception("Invalid request method '{$method}'"); + } + $this->method = $method; + + return $this; + } + + /** + * Returns the request method + * + * @return string + */ + public function getMethod() + { + return $this->method; + } + + /** + * Sets the configuration parameter(s) + * + * The following parameters are available: + *
    + *
  • 'adapter' - adapter to use (string)
  • + *
  • 'connect_timeout' - Connection timeout in seconds (integer)
  • + *
  • 'timeout' - Total number of seconds a request can take. + * Use 0 for no limit, should be greater than + * 'connect_timeout' if set (integer)
  • + *
  • 'use_brackets' - Whether to append [] to array variable names (bool)
  • + *
  • 'protocol_version' - HTTP Version to use, '1.0' or '1.1' (string)
  • + *
  • 'buffer_size' - Buffer size to use for reading and writing (int)
  • + *
  • 'store_body' - Whether to store response body in response object. + * Set to false if receiving a huge response and + * using an Observer to save it (boolean)
  • + *
  • 'proxy_host' - Proxy server host (string)
  • + *
  • 'proxy_port' - Proxy server port (integer)
  • + *
  • 'proxy_user' - Proxy auth username (string)
  • + *
  • 'proxy_password' - Proxy auth password (string)
  • + *
  • 'proxy_auth_scheme' - Proxy auth scheme, one of HTTP_Request2::AUTH_* constants (string)
  • + *
  • 'ssl_verify_peer' - Whether to verify peer's SSL certificate (bool)
  • + *
  • 'ssl_verify_host' - Whether to check that Common Name in SSL + * certificate matches host name (bool)
  • + *
  • 'ssl_cafile' - Cerificate Authority file to verify the peer + * with (use with 'ssl_verify_peer') (string)
  • + *
  • 'ssl_capath' - Directory holding multiple Certificate + * Authority files (string)
  • + *
  • 'ssl_local_cert' - Name of a file containing local cerificate (string)
  • + *
  • 'ssl_passphrase' - Passphrase with which local certificate + * was encoded (string)
  • + *
  • 'digest_compat_ie' - Whether to imitate behaviour of MSIE 5 and 6 + * in using URL without query string in digest + * authentication (boolean)
  • + *
+ * + * @param string|array configuration parameter name or array + * ('parameter name' => 'parameter value') + * @param mixed parameter value if $nameOrConfig is not an array + * @return HTTP_Request2 + * @throws HTTP_Request2_Exception If the parameter is unknown + */ + public function setConfig($nameOrConfig, $value = null) + { + if (is_array($nameOrConfig)) { + foreach ($nameOrConfig as $name => $value) { + $this->setConfig($name, $value); + } + + } else { + if (!array_key_exists($nameOrConfig, $this->config)) { + throw new HTTP_Request2_Exception( + "Unknown configuration parameter '{$nameOrConfig}'" + ); + } + $this->config[$nameOrConfig] = $value; + } + + return $this; + } + + /** + * Returns the value(s) of the configuration parameter(s) + * + * @param string parameter name + * @return mixed value of $name parameter, array of all configuration + * parameters if $name is not given + * @throws HTTP_Request2_Exception If the parameter is unknown + */ + public function getConfig($name = null) + { + if (null === $name) { + return $this->config; + } elseif (!array_key_exists($name, $this->config)) { + throw new HTTP_Request2_Exception( + "Unknown configuration parameter '{$name}'" + ); + } + return $this->config[$name]; + } + + /** + * Sets the autentification data + * + * @param string user name + * @param string password + * @param string authentication scheme + * @return HTTP_Request2 + */ + public function setAuth($user, $password = '', $scheme = self::AUTH_BASIC) + { + if (empty($user)) { + $this->auth = null; + } else { + $this->auth = array( + 'user' => (string)$user, + 'password' => (string)$password, + 'scheme' => $scheme + ); + } + + return $this; + } + + /** + * Returns the authentication data + * + * The array has the keys 'user', 'password' and 'scheme', where 'scheme' + * is one of the HTTP_Request2::AUTH_* constants. + * + * @return array + */ + public function getAuth() + { + return $this->auth; + } + + /** + * Sets request header(s) + * + * The first parameter may be either a full header string 'header: value' or + * header name. In the former case $value parameter is ignored, in the latter + * the header's value will either be set to $value or the header will be + * removed if $value is null. The first parameter can also be an array of + * headers, in that case method will be called recursively. + * + * Note that headers are treated case insensitively as per RFC 2616. + * + * + * $req->setHeader('Foo: Bar'); // sets the value of 'Foo' header to 'Bar' + * $req->setHeader('FoO', 'Baz'); // sets the value of 'Foo' header to 'Baz' + * $req->setHeader(array('foo' => 'Quux')); // sets the value of 'Foo' header to 'Quux' + * $req->setHeader('FOO'); // removes 'Foo' header from request + * + * + * @param string|array header name, header string ('Header: value') + * or an array of headers + * @param string|null header value, header will be removed if null + * @return HTTP_Request2 + * @throws HTTP_Request2_Exception + */ + public function setHeader($name, $value = null) + { + if (is_array($name)) { + foreach ($name as $k => $v) { + if (is_string($k)) { + $this->setHeader($k, $v); + } else { + $this->setHeader($v); + } + } + } else { + if (null === $value && strpos($name, ':')) { + list($name, $value) = array_map('trim', explode(':', $name, 2)); + } + // Header name should be a token: http://tools.ietf.org/html/rfc2616#section-4.2 + if (preg_match(self::REGEXP_INVALID_TOKEN, $name)) { + throw new HTTP_Request2_Exception("Invalid header name '{$name}'"); + } + // Header names are case insensitive anyway + $name = strtolower($name); + if (null === $value) { + unset($this->headers[$name]); + } else { + $this->headers[$name] = $value; + } + } + + return $this; + } + + /** + * Returns the request headers + * + * The array is of the form ('header name' => 'header value'), header names + * are lowercased + * + * @return array + */ + public function getHeaders() + { + return $this->headers; + } + + /** + * Appends a cookie to "Cookie:" header + * + * @param string cookie name + * @param string cookie value + * @return HTTP_Request2 + * @throws HTTP_Request2_Exception + */ + public function addCookie($name, $value) + { + $cookie = $name . '=' . $value; + if (preg_match(self::REGEXP_INVALID_COOKIE, $cookie)) { + throw new HTTP_Request2_Exception("Invalid cookie: '{$cookie}'"); + } + $cookies = empty($this->headers['cookie'])? '': $this->headers['cookie'] . '; '; + $this->setHeader('cookie', $cookies . $cookie); + + return $this; + } + + /** + * Sets the request body + * + * @param string Either a string with the body or filename containing body + * @param bool Whether first parameter is a filename + * @return HTTP_Request2 + * @throws HTTP_Request2_Exception + */ + public function setBody($body, $isFilename = false) + { + if (!$isFilename) { + $this->body = (string)$body; + } else { + if (!($fp = @fopen($body, 'rb'))) { + throw new HTTP_Request2_Exception("Cannot open file {$body}"); + } + $this->body = $fp; + if (empty($this->headers['content-type'])) { + $this->setHeader('content-type', self::detectMimeType($body)); + } + } + + return $this; + } + + /** + * Returns the request body + * + * @return string|resource|HTTP_Request2_MultipartBody + */ + public function getBody() + { + if (self::METHOD_POST == $this->method && + (!empty($this->postParams) || !empty($this->uploads)) + ) { + if ('application/x-www-form-urlencoded' == $this->headers['content-type']) { + $body = http_build_query($this->postParams, '', '&'); + if (!$this->getConfig('use_brackets')) { + $body = preg_replace('/%5B\d+%5D=/', '=', $body); + } + // support RFC 3986 by not encoding '~' symbol (request #15368) + return str_replace('%7E', '~', $body); + + } elseif ('multipart/form-data' == $this->headers['content-type']) { + require_once 'HTTP/Request2/MultipartBody.php'; + return new HTTP_Request2_MultipartBody( + $this->postParams, $this->uploads, $this->getConfig('use_brackets') + ); + } + } + return $this->body; + } + + /** + * Adds a file to form-based file upload + * + * Used to emulate file upload via a HTML form. The method also sets + * Content-Type of HTTP request to 'multipart/form-data'. + * + * If you just want to send the contents of a file as the body of HTTP + * request you should use setBody() method. + * + * @param string name of file-upload field + * @param mixed full name of local file + * @param string filename to send in the request + * @param string content-type of file being uploaded + * @return HTTP_Request2 + * @throws HTTP_Request2_Exception + */ + public function addUpload($fieldName, $filename, $sendFilename = null, + $contentType = null) + { + if (!is_array($filename)) { + if (!($fp = @fopen($filename, 'rb'))) { + throw new HTTP_Request2_Exception("Cannot open file {$filename}"); + } + $this->uploads[$fieldName] = array( + 'fp' => $fp, + 'filename' => empty($sendFilename)? basename($filename): $sendFilename, + 'size' => filesize($filename), + 'type' => empty($contentType)? self::detectMimeType($filename): $contentType + ); + } else { + $fps = $names = $sizes = $types = array(); + foreach ($filename as $f) { + if (!is_array($f)) { + $f = array($f); + } + if (!($fp = @fopen($f[0], 'rb'))) { + throw new HTTP_Request2_Exception("Cannot open file {$f[0]}"); + } + $fps[] = $fp; + $names[] = empty($f[1])? basename($f[0]): $f[1]; + $sizes[] = filesize($f[0]); + $types[] = empty($f[2])? self::detectMimeType($f[0]): $f[2]; + } + $this->uploads[$fieldName] = array( + 'fp' => $fps, 'filename' => $names, 'size' => $sizes, 'type' => $types + ); + } + if (empty($this->headers['content-type']) || + 'application/x-www-form-urlencoded' == $this->headers['content-type'] + ) { + $this->setHeader('content-type', 'multipart/form-data'); + } + + return $this; + } + + /** + * Adds POST parameter(s) to the request. + * + * @param string|array parameter name or array ('name' => 'value') + * @param mixed parameter value (can be an array) + * @return HTTP_Request2 + */ + public function addPostParameter($name, $value = null) + { + if (!is_array($name)) { + $this->postParams[$name] = $value; + } else { + foreach ($name as $k => $v) { + $this->addPostParameter($k, $v); + } + } + if (empty($this->headers['content-type'])) { + $this->setHeader('content-type', 'application/x-www-form-urlencoded'); + } + + return $this; + } + + /** + * Attaches a new observer + * + * @param SplObserver + */ + public function attach(SplObserver $observer) + { + foreach ($this->observers as $attached) { + if ($attached === $observer) { + return; + } + } + $this->observers[] = $observer; + } + + /** + * Detaches an existing observer + * + * @param SplObserver + */ + public function detach(SplObserver $observer) + { + foreach ($this->observers as $key => $attached) { + if ($attached === $observer) { + unset($this->observers[$key]); + return; + } + } + } + + /** + * Notifies all observers + */ + public function notify() + { + foreach ($this->observers as $observer) { + $observer->update($this); + } + } + + /** + * Sets the last event + * + * Adapters should use this method to set the current state of the request + * and notify the observers. + * + * @param string event name + * @param mixed event data + */ + public function setLastEvent($name, $data = null) + { + $this->lastEvent = array( + 'name' => $name, + 'data' => $data + ); + $this->notify(); + } + + /** + * Returns the last event + * + * Observers should use this method to access the last change in request. + * The following event names are possible: + *
    + *
  • 'connect' - after connection to remote server, + * data is the destination (string)
  • + *
  • 'disconnect' - after disconnection from server
  • + *
  • 'sentHeaders' - after sending the request headers, + * data is the headers sent (string)
  • + *
  • 'sentBodyPart' - after sending a part of the request body, + * data is the length of that part (int)
  • + *
  • 'receivedHeaders' - after receiving the response headers, + * data is HTTP_Request2_Response object
  • + *
  • 'receivedBodyPart' - after receiving a part of the response + * body, data is that part (string)
  • + *
  • 'receivedEncodedBodyPart' - as 'receivedBodyPart', but data is still + * encoded by Content-Encoding
  • + *
  • 'receivedBody' - after receiving the complete response + * body, data is HTTP_Request2_Response object
  • + *
+ * Different adapters may not send all the event types. Mock adapter does + * not send any events to the observers. + * + * @return array The array has two keys: 'name' and 'data' + */ + public function getLastEvent() + { + return $this->lastEvent; + } + + /** + * Sets the adapter used to actually perform the request + * + * You can pass either an instance of a class implementing HTTP_Request2_Adapter + * or a class name. The method will only try to include a file if the class + * name starts with HTTP_Request2_Adapter_, it will also try to prepend this + * prefix to the class name if it doesn't contain any underscores, so that + * + * $request->setAdapter('curl'); + * + * will work. + * + * @param string|HTTP_Request2_Adapter + * @return HTTP_Request2 + * @throws HTTP_Request2_Exception + */ + public function setAdapter($adapter) + { + if (is_string($adapter)) { + if (!class_exists($adapter, false)) { + if (false === strpos($adapter, '_')) { + $adapter = 'HTTP_Request2_Adapter_' . ucfirst($adapter); + } + if (preg_match('/^HTTP_Request2_Adapter_([a-zA-Z0-9]+)$/', $adapter)) { + include_once str_replace('_', DIRECTORY_SEPARATOR, $adapter) . '.php'; + } + if (!class_exists($adapter, false)) { + throw new HTTP_Request2_Exception("Class {$adapter} not found"); + } + } + $adapter = new $adapter; + } + if (!$adapter instanceof HTTP_Request2_Adapter) { + throw new HTTP_Request2_Exception('Parameter is not a HTTP request adapter'); + } + $this->adapter = $adapter; + + return $this; + } + + /** + * Sends the request and returns the response + * + * @throws HTTP_Request2_Exception + * @return HTTP_Request2_Response + */ + public function send() + { + // Sanity check for URL + if (!$this->url instanceof Net_URL2) { + throw new HTTP_Request2_Exception('No URL given'); + } elseif (!$this->url->isAbsolute()) { + throw new HTTP_Request2_Exception('Absolute URL required'); + } elseif (!in_array(strtolower($this->url->getScheme()), array('https', 'http'))) { + throw new HTTP_Request2_Exception('Not a HTTP URL'); + } + if (empty($this->adapter)) { + $this->setAdapter($this->getConfig('adapter')); + } + // magic_quotes_runtime may break file uploads and chunked response + // processing; see bug #4543 + if ($magicQuotes = ini_get('magic_quotes_runtime')) { + ini_set('magic_quotes_runtime', false); + } + // force using single byte encoding if mbstring extension overloads + // strlen() and substr(); see bug #1781, bug #10605 + if (extension_loaded('mbstring') && (2 & ini_get('mbstring.func_overload'))) { + $oldEncoding = mb_internal_encoding(); + mb_internal_encoding('iso-8859-1'); + } + + try { + $response = $this->adapter->sendRequest($this); + } catch (Exception $e) { + } + // cleanup in either case (poor man's "finally" clause) + if ($magicQuotes) { + ini_set('magic_quotes_runtime', true); + } + if (!empty($oldEncoding)) { + mb_internal_encoding($oldEncoding); + } + // rethrow the exception + if (!empty($e)) { + throw $e; + } + return $response; + } + + /** + * Tries to detect MIME type of a file + * + * The method will try to use fileinfo extension if it is available, + * deprecated mime_content_type() function in the other case. If neither + * works, default 'application/octet-stream' MIME type is returned + * + * @param string filename + * @return string file MIME type + */ + protected static function detectMimeType($filename) + { + // finfo extension from PECL available + if (function_exists('finfo_open')) { + if (!isset(self::$_fileinfoDb)) { + self::$_fileinfoDb = @finfo_open(FILEINFO_MIME); + } + if (self::$_fileinfoDb) { + $info = finfo_file(self::$_fileinfoDb, $filename); + } + } + // (deprecated) mime_content_type function available + if (empty($info) && function_exists('mime_content_type')) { + return mime_content_type($filename); + } + return empty($info)? 'application/octet-stream': $info; + } +} +?> \ No newline at end of file diff --git a/extlib/HTTP/Request2/Adapter.php b/extlib/HTTP/Request2/Adapter.php new file mode 100644 index 000000000..39b092b34 --- /dev/null +++ b/extlib/HTTP/Request2/Adapter.php @@ -0,0 +1,152 @@ + + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Adapter.php 274684 2009-01-26 23:07:27Z avb $ + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** + * Class representing a HTTP response + */ +require_once 'HTTP/Request2/Response.php'; + +/** + * Base class for HTTP_Request2 adapters + * + * HTTP_Request2 class itself only defines methods for aggregating the request + * data, all actual work of sending the request to the remote server and + * receiving its response is performed by adapters. + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @version Release: 0.4.1 + */ +abstract class HTTP_Request2_Adapter +{ + /** + * A list of methods that MUST NOT have a request body, per RFC 2616 + * @var array + */ + protected static $bodyDisallowed = array('TRACE'); + + /** + * Methods having defined semantics for request body + * + * Content-Length header (indicating that the body follows, section 4.3 of + * RFC 2616) will be sent for these methods even if no body was added + * + * @var array + * @link http://pear.php.net/bugs/bug.php?id=12900 + * @link http://pear.php.net/bugs/bug.php?id=14740 + */ + protected static $bodyRequired = array('POST', 'PUT'); + + /** + * Request being sent + * @var HTTP_Request2 + */ + protected $request; + + /** + * Request body + * @var string|resource|HTTP_Request2_MultipartBody + * @see HTTP_Request2::getBody() + */ + protected $requestBody; + + /** + * Length of the request body + * @var integer + */ + protected $contentLength; + + /** + * Sends request to the remote server and returns its response + * + * @param HTTP_Request2 + * @return HTTP_Request2_Response + * @throws HTTP_Request2_Exception + */ + abstract public function sendRequest(HTTP_Request2 $request); + + /** + * Calculates length of the request body, adds proper headers + * + * @param array associative array of request headers, this method will + * add proper 'Content-Length' and 'Content-Type' headers + * to this array (or remove them if not needed) + */ + protected function calculateRequestLength(&$headers) + { + $this->requestBody = $this->request->getBody(); + + if (is_string($this->requestBody)) { + $this->contentLength = strlen($this->requestBody); + } elseif (is_resource($this->requestBody)) { + $stat = fstat($this->requestBody); + $this->contentLength = $stat['size']; + rewind($this->requestBody); + } else { + $this->contentLength = $this->requestBody->getLength(); + $headers['content-type'] = 'multipart/form-data; boundary=' . + $this->requestBody->getBoundary(); + $this->requestBody->rewind(); + } + + if (in_array($this->request->getMethod(), self::$bodyDisallowed) || + 0 == $this->contentLength + ) { + unset($headers['content-type']); + // No body: send a Content-Length header nonetheless (request #12900), + // but do that only for methods that require a body (bug #14740) + if (in_array($this->request->getMethod(), self::$bodyRequired)) { + $headers['content-length'] = 0; + } else { + unset($headers['content-length']); + } + } else { + if (empty($headers['content-type'])) { + $headers['content-type'] = 'application/x-www-form-urlencoded'; + } + $headers['content-length'] = $this->contentLength; + } + } +} +?> diff --git a/extlib/HTTP/Request2/Adapter/Curl.php b/extlib/HTTP/Request2/Adapter/Curl.php new file mode 100644 index 000000000..4d4de0dcc --- /dev/null +++ b/extlib/HTTP/Request2/Adapter/Curl.php @@ -0,0 +1,383 @@ + + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Curl.php 278226 2009-04-03 21:32:48Z avb $ + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** + * Base class for HTTP_Request2 adapters + */ +require_once 'HTTP/Request2/Adapter.php'; + +/** + * Adapter for HTTP_Request2 wrapping around cURL extension + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @version Release: 0.4.1 + */ +class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter +{ + /** + * Mapping of header names to cURL options + * @var array + */ + protected static $headerMap = array( + 'accept-encoding' => CURLOPT_ENCODING, + 'cookie' => CURLOPT_COOKIE, + 'referer' => CURLOPT_REFERER, + 'user-agent' => CURLOPT_USERAGENT + ); + + /** + * Mapping of SSL context options to cURL options + * @var array + */ + protected static $sslContextMap = array( + 'ssl_verify_peer' => CURLOPT_SSL_VERIFYPEER, + 'ssl_cafile' => CURLOPT_CAINFO, + 'ssl_capath' => CURLOPT_CAPATH, + 'ssl_local_cert' => CURLOPT_SSLCERT, + 'ssl_passphrase' => CURLOPT_SSLCERTPASSWD + ); + + /** + * Response being received + * @var HTTP_Request2_Response + */ + protected $response; + + /** + * Whether 'sentHeaders' event was sent to observers + * @var boolean + */ + protected $eventSentHeaders = false; + + /** + * Whether 'receivedHeaders' event was sent to observers + * @var boolean + */ + protected $eventReceivedHeaders = false; + + /** + * Position within request body + * @var integer + * @see callbackReadBody() + */ + protected $position = 0; + + /** + * Information about last transfer, as returned by curl_getinfo() + * @var array + */ + protected $lastInfo; + + /** + * Sends request to the remote server and returns its response + * + * @param HTTP_Request2 + * @return HTTP_Request2_Response + * @throws HTTP_Request2_Exception + */ + public function sendRequest(HTTP_Request2 $request) + { + if (!extension_loaded('curl')) { + throw new HTTP_Request2_Exception('cURL extension not available'); + } + + $this->request = $request; + $this->response = null; + $this->position = 0; + $this->eventSentHeaders = false; + $this->eventReceivedHeaders = false; + + try { + if (false === curl_exec($ch = $this->createCurlHandle())) { + $errorMessage = 'Error sending request: #' . curl_errno($ch) . + ' ' . curl_error($ch); + } + } catch (Exception $e) { + } + $this->lastInfo = curl_getinfo($ch); + curl_close($ch); + + if (!empty($e)) { + throw $e; + } elseif (!empty($errorMessage)) { + throw new HTTP_Request2_Exception($errorMessage); + } + + if (0 < $this->lastInfo['size_download']) { + $this->request->setLastEvent('receivedBody', $this->response); + } + return $this->response; + } + + /** + * Returns information about last transfer + * + * @return array associative array as returned by curl_getinfo() + */ + public function getInfo() + { + return $this->lastInfo; + } + + /** + * Creates a new cURL handle and populates it with data from the request + * + * @return resource a cURL handle, as created by curl_init() + * @throws HTTP_Request2_Exception + */ + protected function createCurlHandle() + { + $ch = curl_init(); + + curl_setopt_array($ch, array( + // setup callbacks + CURLOPT_READFUNCTION => array($this, 'callbackReadBody'), + CURLOPT_HEADERFUNCTION => array($this, 'callbackWriteHeader'), + CURLOPT_WRITEFUNCTION => array($this, 'callbackWriteBody'), + // disallow redirects + CURLOPT_FOLLOWLOCATION => false, + // buffer size + CURLOPT_BUFFERSIZE => $this->request->getConfig('buffer_size'), + // connection timeout + CURLOPT_CONNECTTIMEOUT => $this->request->getConfig('connect_timeout'), + // save full outgoing headers, in case someone is interested + CURLINFO_HEADER_OUT => true, + // request url + CURLOPT_URL => $this->request->getUrl()->getUrl() + )); + + // request timeout + if ($timeout = $this->request->getConfig('timeout')) { + curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); + } + + // set HTTP version + switch ($this->request->getConfig('protocol_version')) { + case '1.0': + curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + break; + case '1.1': + curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + } + + // set request method + switch ($this->request->getMethod()) { + case HTTP_Request2::METHOD_GET: + curl_setopt($ch, CURLOPT_HTTPGET, true); + break; + case HTTP_Request2::METHOD_POST: + curl_setopt($ch, CURLOPT_POST, true); + break; + default: + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $this->request->getMethod()); + } + + // set proxy, if needed + if ($host = $this->request->getConfig('proxy_host')) { + if (!($port = $this->request->getConfig('proxy_port'))) { + throw new HTTP_Request2_Exception('Proxy port not provided'); + } + curl_setopt($ch, CURLOPT_PROXY, $host . ':' . $port); + if ($user = $this->request->getConfig('proxy_user')) { + curl_setopt($ch, CURLOPT_PROXYUSERPWD, $user . ':' . + $this->request->getConfig('proxy_password')); + switch ($this->request->getConfig('proxy_auth_scheme')) { + case HTTP_Request2::AUTH_BASIC: + curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC); + break; + case HTTP_Request2::AUTH_DIGEST: + curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_DIGEST); + } + } + } + + // set authentication data + if ($auth = $this->request->getAuth()) { + curl_setopt($ch, CURLOPT_USERPWD, $auth['user'] . ':' . $auth['password']); + switch ($auth['scheme']) { + case HTTP_Request2::AUTH_BASIC: + curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + break; + case HTTP_Request2::AUTH_DIGEST: + curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST); + } + } + + // set SSL options + if (0 == strcasecmp($this->request->getUrl()->getScheme(), 'https')) { + foreach ($this->request->getConfig() as $name => $value) { + if ('ssl_verify_host' == $name && null !== $value) { + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $value? 2: 0); + } elseif (isset(self::$sslContextMap[$name]) && null !== $value) { + curl_setopt($ch, self::$sslContextMap[$name], $value); + } + } + } + + $headers = $this->request->getHeaders(); + // make cURL automagically send proper header + if (!isset($headers['accept-encoding'])) { + $headers['accept-encoding'] = ''; + } + + // set headers having special cURL keys + foreach (self::$headerMap as $name => $option) { + if (isset($headers[$name])) { + curl_setopt($ch, $option, $headers[$name]); + unset($headers[$name]); + } + } + + $this->calculateRequestLength($headers); + + // set headers not having special keys + $headersFmt = array(); + foreach ($headers as $name => $value) { + $canonicalName = implode('-', array_map('ucfirst', explode('-', $name))); + $headersFmt[] = $canonicalName . ': ' . $value; + } + curl_setopt($ch, CURLOPT_HTTPHEADER, $headersFmt); + + return $ch; + } + + /** + * Callback function called by cURL for reading the request body + * + * @param resource cURL handle + * @param resource file descriptor (not used) + * @param integer maximum length of data to return + * @return string part of the request body, up to $length bytes + */ + protected function callbackReadBody($ch, $fd, $length) + { + if (!$this->eventSentHeaders) { + $this->request->setLastEvent( + 'sentHeaders', curl_getinfo($ch, CURLINFO_HEADER_OUT) + ); + $this->eventSentHeaders = true; + } + if (in_array($this->request->getMethod(), self::$bodyDisallowed) || + 0 == $this->contentLength || $this->position >= $this->contentLength + ) { + return ''; + } + if (is_string($this->requestBody)) { + $string = substr($this->requestBody, $this->position, $length); + } elseif (is_resource($this->requestBody)) { + $string = fread($this->requestBody, $length); + } else { + $string = $this->requestBody->read($length); + } + $this->request->setLastEvent('sentBodyPart', strlen($string)); + $this->position += strlen($string); + return $string; + } + + /** + * Callback function called by cURL for saving the response headers + * + * @param resource cURL handle + * @param string response header (with trailing CRLF) + * @return integer number of bytes saved + * @see HTTP_Request2_Response::parseHeaderLine() + */ + protected function callbackWriteHeader($ch, $string) + { + // we may receive a second set of headers if doing e.g. digest auth + if ($this->eventReceivedHeaders || !$this->eventSentHeaders) { + // don't bother with 100-Continue responses (bug #15785) + if (!$this->eventSentHeaders || + $this->response->getStatus() >= 200 + ) { + $this->request->setLastEvent( + 'sentHeaders', curl_getinfo($ch, CURLINFO_HEADER_OUT) + ); + } + $this->eventSentHeaders = true; + // we'll need a new response object + if ($this->eventReceivedHeaders) { + $this->eventReceivedHeaders = false; + $this->response = null; + } + } + if (empty($this->response)) { + $this->response = new HTTP_Request2_Response($string, false); + } else { + $this->response->parseHeaderLine($string); + if ('' == trim($string)) { + // don't bother with 100-Continue responses (bug #15785) + if (200 <= $this->response->getStatus()) { + $this->request->setLastEvent('receivedHeaders', $this->response); + } + $this->eventReceivedHeaders = true; + } + } + return strlen($string); + } + + /** + * Callback function called by cURL for saving the response body + * + * @param resource cURL handle (not used) + * @param string part of the response body + * @return integer number of bytes saved + * @see HTTP_Request2_Response::appendBody() + */ + protected function callbackWriteBody($ch, $string) + { + // cURL calls WRITEFUNCTION callback without calling HEADERFUNCTION if + // response doesn't start with proper HTTP status line (see bug #15716) + if (empty($this->response)) { + throw new HTTP_Request2_Exception("Malformed response: {$string}"); + } + if ($this->request->getConfig('store_body')) { + $this->response->appendBody($string); + } + $this->request->setLastEvent('receivedBodyPart', $string); + return strlen($string); + } +} +?> diff --git a/extlib/HTTP/Request2/Adapter/Mock.php b/extlib/HTTP/Request2/Adapter/Mock.php new file mode 100644 index 000000000..89688003b --- /dev/null +++ b/extlib/HTTP/Request2/Adapter/Mock.php @@ -0,0 +1,171 @@ + + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Mock.php 274406 2009-01-23 18:01:57Z avb $ + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** + * Base class for HTTP_Request2 adapters + */ +require_once 'HTTP/Request2/Adapter.php'; + +/** + * Mock adapter intended for testing + * + * Can be used to test applications depending on HTTP_Request2 package without + * actually performing any HTTP requests. This adapter will return responses + * previously added via addResponse() + * + * $mock = new HTTP_Request2_Adapter_Mock(); + * $mock->addResponse("HTTP/1.1 ... "); + * + * $request = new HTTP_Request2(); + * $request->setAdapter($mock); + * + * // This will return the response set above + * $response = $req->send(); + * + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @version Release: 0.4.1 + */ +class HTTP_Request2_Adapter_Mock extends HTTP_Request2_Adapter +{ + /** + * A queue of responses to be returned by sendRequest() + * @var array + */ + protected $responses = array(); + + /** + * Returns the next response from the queue built by addResponse() + * + * If the queue is empty will return default empty response with status 400, + * if an Exception object was added to the queue it will be thrown. + * + * @param HTTP_Request2 + * @return HTTP_Request2_Response + * @throws Exception + */ + public function sendRequest(HTTP_Request2 $request) + { + if (count($this->responses) > 0) { + $response = array_shift($this->responses); + if ($response instanceof HTTP_Request2_Response) { + return $response; + } else { + // rethrow the exception, + $class = get_class($response); + $message = $response->getMessage(); + $code = $response->getCode(); + throw new $class($message, $code); + } + } else { + return self::createResponseFromString("HTTP/1.1 400 Bad Request\r\n\r\n"); + } + } + + /** + * Adds response to the queue + * + * @param mixed either a string, a pointer to an open file, + * a HTTP_Request2_Response or Exception object + * @throws HTTP_Request2_Exception + */ + public function addResponse($response) + { + if (is_string($response)) { + $response = self::createResponseFromString($response); + } elseif (is_resource($response)) { + $response = self::createResponseFromFile($response); + } elseif (!$response instanceof HTTP_Request2_Response && + !$response instanceof Exception + ) { + throw new HTTP_Request2_Exception('Parameter is not a valid response'); + } + $this->responses[] = $response; + } + + /** + * Creates a new HTTP_Request2_Response object from a string + * + * @param string + * @return HTTP_Request2_Response + * @throws HTTP_Request2_Exception + */ + public static function createResponseFromString($str) + { + $parts = preg_split('!(\r?\n){2}!m', $str, 2); + $headerLines = explode("\n", $parts[0]); + $response = new HTTP_Request2_Response(array_shift($headerLines)); + foreach ($headerLines as $headerLine) { + $response->parseHeaderLine($headerLine); + } + $response->parseHeaderLine(''); + if (isset($parts[1])) { + $response->appendBody($parts[1]); + } + return $response; + } + + /** + * Creates a new HTTP_Request2_Response object from a file + * + * @param resource file pointer returned by fopen() + * @return HTTP_Request2_Response + * @throws HTTP_Request2_Exception + */ + public static function createResponseFromFile($fp) + { + $response = new HTTP_Request2_Response(fgets($fp)); + do { + $headerLine = fgets($fp); + $response->parseHeaderLine($headerLine); + } while ('' != trim($headerLine)); + + while (!feof($fp)) { + $response->appendBody(fread($fp, 8192)); + } + return $response; + } +} +?> \ No newline at end of file diff --git a/extlib/HTTP/Request2/Adapter/Socket.php b/extlib/HTTP/Request2/Adapter/Socket.php new file mode 100644 index 000000000..ff44d4959 --- /dev/null +++ b/extlib/HTTP/Request2/Adapter/Socket.php @@ -0,0 +1,971 @@ + + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Socket.php 279760 2009-05-03 10:46:42Z avb $ + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** + * Base class for HTTP_Request2 adapters + */ +require_once 'HTTP/Request2/Adapter.php'; + +/** + * Socket-based adapter for HTTP_Request2 + * + * This adapter uses only PHP sockets and will work on almost any PHP + * environment. Code is based on original HTTP_Request PEAR package. + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @version Release: 0.4.1 + */ +class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter +{ + /** + * Regular expression for 'token' rule from RFC 2616 + */ + const REGEXP_TOKEN = '[^\x00-\x1f\x7f-\xff()<>@,;:\\\\"/\[\]?={}\s]+'; + + /** + * Regular expression for 'quoted-string' rule from RFC 2616 + */ + const REGEXP_QUOTED_STRING = '"(?:\\\\.|[^\\\\"])*"'; + + /** + * Connected sockets, needed for Keep-Alive support + * @var array + * @see connect() + */ + protected static $sockets = array(); + + /** + * Data for digest authentication scheme + * + * The keys for the array are URL prefixes. + * + * The values are associative arrays with data (realm, nonce, nonce-count, + * opaque...) needed for digest authentication. Stored here to prevent making + * duplicate requests to digest-protected resources after we have already + * received the challenge. + * + * @var array + */ + protected static $challenges = array(); + + /** + * Connected socket + * @var resource + * @see connect() + */ + protected $socket; + + /** + * Challenge used for server digest authentication + * @var array + */ + protected $serverChallenge; + + /** + * Challenge used for proxy digest authentication + * @var array + */ + protected $proxyChallenge; + + /** + * Global timeout, exception will be raised if request continues past this time + * @var integer + */ + protected $timeout = null; + + /** + * Remaining length of the current chunk, when reading chunked response + * @var integer + * @see readChunked() + */ + protected $chunkLength = 0; + + /** + * Sends request to the remote server and returns its response + * + * @param HTTP_Request2 + * @return HTTP_Request2_Response + * @throws HTTP_Request2_Exception + */ + public function sendRequest(HTTP_Request2 $request) + { + $this->request = $request; + $keepAlive = $this->connect(); + $headers = $this->prepareHeaders(); + + // Use global request timeout if given, see feature requests #5735, #8964 + if ($timeout = $request->getConfig('timeout')) { + $this->timeout = time() + $timeout; + } else { + $this->timeout = null; + } + + try { + if (false === @fwrite($this->socket, $headers, strlen($headers))) { + throw new HTTP_Request2_Exception('Error writing request'); + } + // provide request headers to the observer, see request #7633 + $this->request->setLastEvent('sentHeaders', $headers); + $this->writeBody(); + + if ($this->timeout && time() > $this->timeout) { + throw new HTTP_Request2_Exception( + 'Request timed out after ' . + $request->getConfig('timeout') . ' second(s)' + ); + } + + $response = $this->readResponse(); + + if (!$this->canKeepAlive($keepAlive, $response)) { + $this->disconnect(); + } + + if ($this->shouldUseProxyDigestAuth($response)) { + return $this->sendRequest($request); + } + if ($this->shouldUseServerDigestAuth($response)) { + return $this->sendRequest($request); + } + if ($authInfo = $response->getHeader('authentication-info')) { + $this->updateChallenge($this->serverChallenge, $authInfo); + } + if ($proxyInfo = $response->getHeader('proxy-authentication-info')) { + $this->updateChallenge($this->proxyChallenge, $proxyInfo); + } + + } catch (Exception $e) { + $this->disconnect(); + throw $e; + } + + return $response; + } + + /** + * Connects to the remote server + * + * @return bool whether the connection can be persistent + * @throws HTTP_Request2_Exception + */ + protected function connect() + { + $secure = 0 == strcasecmp($this->request->getUrl()->getScheme(), 'https'); + $tunnel = HTTP_Request2::METHOD_CONNECT == $this->request->getMethod(); + $headers = $this->request->getHeaders(); + $reqHost = $this->request->getUrl()->getHost(); + if (!($reqPort = $this->request->getUrl()->getPort())) { + $reqPort = $secure? 443: 80; + } + + if ($host = $this->request->getConfig('proxy_host')) { + if (!($port = $this->request->getConfig('proxy_port'))) { + throw new HTTP_Request2_Exception('Proxy port not provided'); + } + $proxy = true; + } else { + $host = $reqHost; + $port = $reqPort; + $proxy = false; + } + + if ($tunnel && !$proxy) { + throw new HTTP_Request2_Exception( + "Trying to perform CONNECT request without proxy" + ); + } + if ($secure && !in_array('ssl', stream_get_transports())) { + throw new HTTP_Request2_Exception( + 'Need OpenSSL support for https:// requests' + ); + } + + // RFC 2068, section 19.7.1: A client MUST NOT send the Keep-Alive + // connection token to a proxy server... + if ($proxy && !$secure && + !empty($headers['connection']) && 'Keep-Alive' == $headers['connection'] + ) { + $this->request->setHeader('connection'); + } + + $keepAlive = ('1.1' == $this->request->getConfig('protocol_version') && + empty($headers['connection'])) || + (!empty($headers['connection']) && + 'Keep-Alive' == $headers['connection']); + $host = ((!$secure || $proxy)? 'tcp://': 'ssl://') . $host; + + $options = array(); + if ($secure || $tunnel) { + foreach ($this->request->getConfig() as $name => $value) { + if ('ssl_' == substr($name, 0, 4) && null !== $value) { + if ('ssl_verify_host' == $name) { + if ($value) { + $options['CN_match'] = $reqHost; + } + } else { + $options[substr($name, 4)] = $value; + } + } + } + ksort($options); + } + + // Changing SSL context options after connection is established does *not* + // work, we need a new connection if options change + $remote = $host . ':' . $port; + $socketKey = $remote . (($secure && $proxy)? "->{$reqHost}:{$reqPort}": '') . + (empty($options)? '': ':' . serialize($options)); + unset($this->socket); + + // We use persistent connections and have a connected socket? + // Ensure that the socket is still connected, see bug #16149 + if ($keepAlive && !empty(self::$sockets[$socketKey]) && + !feof(self::$sockets[$socketKey]) + ) { + $this->socket =& self::$sockets[$socketKey]; + + } elseif ($secure && $proxy && !$tunnel) { + $this->establishTunnel(); + $this->request->setLastEvent( + 'connect', "ssl://{$reqHost}:{$reqPort} via {$host}:{$port}" + ); + self::$sockets[$socketKey] =& $this->socket; + + } else { + // Set SSL context options if doing HTTPS request or creating a tunnel + $context = stream_context_create(); + foreach ($options as $name => $value) { + if (!stream_context_set_option($context, 'ssl', $name, $value)) { + throw new HTTP_Request2_Exception( + "Error setting SSL context option '{$name}'" + ); + } + } + $this->socket = @stream_socket_client( + $remote, $errno, $errstr, + $this->request->getConfig('connect_timeout'), + STREAM_CLIENT_CONNECT, $context + ); + if (!$this->socket) { + throw new HTTP_Request2_Exception( + "Unable to connect to {$remote}. Error #{$errno}: {$errstr}" + ); + } + $this->request->setLastEvent('connect', $remote); + self::$sockets[$socketKey] =& $this->socket; + } + return $keepAlive; + } + + /** + * Establishes a tunnel to a secure remote server via HTTP CONNECT request + * + * This method will fail if 'ssl_verify_peer' is enabled. Probably because PHP + * sees that we are connected to a proxy server (duh!) rather than the server + * that presents its certificate. + * + * @link http://tools.ietf.org/html/rfc2817#section-5.2 + * @throws HTTP_Request2_Exception + */ + protected function establishTunnel() + { + $donor = new self; + $connect = new HTTP_Request2( + $this->request->getUrl(), HTTP_Request2::METHOD_CONNECT, + array_merge($this->request->getConfig(), + array('adapter' => $donor)) + ); + $response = $connect->send(); + // Need any successful (2XX) response + if (200 > $response->getStatus() || 300 <= $response->getStatus()) { + throw new HTTP_Request2_Exception( + 'Failed to connect via HTTPS proxy. Proxy response: ' . + $response->getStatus() . ' ' . $response->getReasonPhrase() + ); + } + $this->socket = $donor->socket; + + $modes = array( + STREAM_CRYPTO_METHOD_TLS_CLIENT, + STREAM_CRYPTO_METHOD_SSLv3_CLIENT, + STREAM_CRYPTO_METHOD_SSLv23_CLIENT, + STREAM_CRYPTO_METHOD_SSLv2_CLIENT + ); + + foreach ($modes as $mode) { + if (stream_socket_enable_crypto($this->socket, true, $mode)) { + return; + } + } + throw new HTTP_Request2_Exception( + 'Failed to enable secure connection when connecting through proxy' + ); + } + + /** + * Checks whether current connection may be reused or should be closed + * + * @param boolean whether connection could be persistent + * in the first place + * @param HTTP_Request2_Response response object to check + * @return boolean + */ + protected function canKeepAlive($requestKeepAlive, HTTP_Request2_Response $response) + { + // Do not close socket on successful CONNECT request + if (HTTP_Request2::METHOD_CONNECT == $this->request->getMethod() && + 200 <= $response->getStatus() && 300 > $response->getStatus() + ) { + return true; + } + + $lengthKnown = 'chunked' == strtolower($response->getHeader('transfer-encoding')) || + null !== $response->getHeader('content-length'); + $persistent = 'keep-alive' == strtolower($response->getHeader('connection')) || + (null === $response->getHeader('connection') && + '1.1' == $response->getVersion()); + return $requestKeepAlive && $lengthKnown && $persistent; + } + + /** + * Disconnects from the remote server + */ + protected function disconnect() + { + if (is_resource($this->socket)) { + fclose($this->socket); + $this->socket = null; + $this->request->setLastEvent('disconnect'); + } + } + + /** + * Checks whether another request should be performed with server digest auth + * + * Several conditions should be satisfied for it to return true: + * - response status should be 401 + * - auth credentials should be set in the request object + * - response should contain WWW-Authenticate header with digest challenge + * - there is either no challenge stored for this URL or new challenge + * contains stale=true parameter (in other case we probably just failed + * due to invalid username / password) + * + * The method stores challenge values in $challenges static property + * + * @param HTTP_Request2_Response response to check + * @return boolean whether another request should be performed + * @throws HTTP_Request2_Exception in case of unsupported challenge parameters + */ + protected function shouldUseServerDigestAuth(HTTP_Request2_Response $response) + { + // no sense repeating a request if we don't have credentials + if (401 != $response->getStatus() || !$this->request->getAuth()) { + return false; + } + if (!$challenge = $this->parseDigestChallenge($response->getHeader('www-authenticate'))) { + return false; + } + + $url = $this->request->getUrl(); + $scheme = $url->getScheme(); + $host = $scheme . '://' . $url->getHost(); + if ($port = $url->getPort()) { + if ((0 == strcasecmp($scheme, 'http') && 80 != $port) || + (0 == strcasecmp($scheme, 'https') && 443 != $port) + ) { + $host .= ':' . $port; + } + } + + if (!empty($challenge['domain'])) { + $prefixes = array(); + foreach (preg_split('/\\s+/', $challenge['domain']) as $prefix) { + // don't bother with different servers + if ('/' == substr($prefix, 0, 1)) { + $prefixes[] = $host . $prefix; + } + } + } + if (empty($prefixes)) { + $prefixes = array($host . '/'); + } + + $ret = true; + foreach ($prefixes as $prefix) { + if (!empty(self::$challenges[$prefix]) && + (empty($challenge['stale']) || strcasecmp('true', $challenge['stale'])) + ) { + // probably credentials are invalid + $ret = false; + } + self::$challenges[$prefix] =& $challenge; + } + return $ret; + } + + /** + * Checks whether another request should be performed with proxy digest auth + * + * Several conditions should be satisfied for it to return true: + * - response status should be 407 + * - proxy auth credentials should be set in the request object + * - response should contain Proxy-Authenticate header with digest challenge + * - there is either no challenge stored for this proxy or new challenge + * contains stale=true parameter (in other case we probably just failed + * due to invalid username / password) + * + * The method stores challenge values in $challenges static property + * + * @param HTTP_Request2_Response response to check + * @return boolean whether another request should be performed + * @throws HTTP_Request2_Exception in case of unsupported challenge parameters + */ + protected function shouldUseProxyDigestAuth(HTTP_Request2_Response $response) + { + if (407 != $response->getStatus() || !$this->request->getConfig('proxy_user')) { + return false; + } + if (!($challenge = $this->parseDigestChallenge($response->getHeader('proxy-authenticate')))) { + return false; + } + + $key = 'proxy://' . $this->request->getConfig('proxy_host') . + ':' . $this->request->getConfig('proxy_port'); + + if (!empty(self::$challenges[$key]) && + (empty($challenge['stale']) || strcasecmp('true', $challenge['stale'])) + ) { + $ret = false; + } else { + $ret = true; + } + self::$challenges[$key] = $challenge; + return $ret; + } + + /** + * Extracts digest method challenge from (WWW|Proxy)-Authenticate header value + * + * There is a problem with implementation of RFC 2617: several of the parameters + * here are defined as quoted-string and thus may contain backslash escaped + * double quotes (RFC 2616, section 2.2). However, RFC 2617 defines unq(X) as + * just value of quoted-string X without surrounding quotes, it doesn't speak + * about removing backslash escaping. + * + * Now realm parameter is user-defined and human-readable, strange things + * happen when it contains quotes: + * - Apache allows quotes in realm, but apparently uses realm value without + * backslashes for digest computation + * - Squid allows (manually escaped) quotes there, but it is impossible to + * authorize with either escaped or unescaped quotes used in digest, + * probably it can't parse the response (?) + * - Both IE and Firefox display realm value with backslashes in + * the password popup and apparently use the same value for digest + * + * HTTP_Request2 follows IE and Firefox (and hopefully RFC 2617) in + * quoted-string handling, unfortunately that means failure to authorize + * sometimes + * + * @param string value of WWW-Authenticate or Proxy-Authenticate header + * @return mixed associative array with challenge parameters, false if + * no challenge is present in header value + * @throws HTTP_Request2_Exception in case of unsupported challenge parameters + */ + protected function parseDigestChallenge($headerValue) + { + $authParam = '(' . self::REGEXP_TOKEN . ')\\s*=\\s*(' . + self::REGEXP_TOKEN . '|' . self::REGEXP_QUOTED_STRING . ')'; + $challenge = "!(?<=^|\\s|,)Digest ({$authParam}\\s*(,\\s*|$))+!"; + if (!preg_match($challenge, $headerValue, $matches)) { + return false; + } + + preg_match_all('!' . $authParam . '!', $matches[0], $params); + $paramsAry = array(); + $knownParams = array('realm', 'domain', 'nonce', 'opaque', 'stale', + 'algorithm', 'qop'); + for ($i = 0; $i < count($params[0]); $i++) { + // section 3.2.1: Any unrecognized directive MUST be ignored. + if (in_array($params[1][$i], $knownParams)) { + if ('"' == substr($params[2][$i], 0, 1)) { + $paramsAry[$params[1][$i]] = substr($params[2][$i], 1, -1); + } else { + $paramsAry[$params[1][$i]] = $params[2][$i]; + } + } + } + // we only support qop=auth + if (!empty($paramsAry['qop']) && + !in_array('auth', array_map('trim', explode(',', $paramsAry['qop']))) + ) { + throw new HTTP_Request2_Exception( + "Only 'auth' qop is currently supported in digest authentication, " . + "server requested '{$paramsAry['qop']}'" + ); + } + // we only support algorithm=MD5 + if (!empty($paramsAry['algorithm']) && 'MD5' != $paramsAry['algorithm']) { + throw new HTTP_Request2_Exception( + "Only 'MD5' algorithm is currently supported in digest authentication, " . + "server requested '{$paramsAry['algorithm']}'" + ); + } + + return $paramsAry; + } + + /** + * Parses [Proxy-]Authentication-Info header value and updates challenge + * + * @param array challenge to update + * @param string value of [Proxy-]Authentication-Info header + * @todo validate server rspauth response + */ + protected function updateChallenge(&$challenge, $headerValue) + { + $authParam = '!(' . self::REGEXP_TOKEN . ')\\s*=\\s*(' . + self::REGEXP_TOKEN . '|' . self::REGEXP_QUOTED_STRING . ')!'; + $paramsAry = array(); + + preg_match_all($authParam, $headerValue, $params); + for ($i = 0; $i < count($params[0]); $i++) { + if ('"' == substr($params[2][$i], 0, 1)) { + $paramsAry[$params[1][$i]] = substr($params[2][$i], 1, -1); + } else { + $paramsAry[$params[1][$i]] = $params[2][$i]; + } + } + // for now, just update the nonce value + if (!empty($paramsAry['nextnonce'])) { + $challenge['nonce'] = $paramsAry['nextnonce']; + $challenge['nc'] = 1; + } + } + + /** + * Creates a value for [Proxy-]Authorization header when using digest authentication + * + * @param string user name + * @param string password + * @param string request URL + * @param array digest challenge parameters + * @return string value of [Proxy-]Authorization request header + * @link http://tools.ietf.org/html/rfc2617#section-3.2.2 + */ + protected function createDigestResponse($user, $password, $url, &$challenge) + { + if (false !== ($q = strpos($url, '?')) && + $this->request->getConfig('digest_compat_ie') + ) { + $url = substr($url, 0, $q); + } + + $a1 = md5($user . ':' . $challenge['realm'] . ':' . $password); + $a2 = md5($this->request->getMethod() . ':' . $url); + + if (empty($challenge['qop'])) { + $digest = md5($a1 . ':' . $challenge['nonce'] . ':' . $a2); + } else { + $challenge['cnonce'] = 'Req2.' . rand(); + if (empty($challenge['nc'])) { + $challenge['nc'] = 1; + } + $nc = sprintf('%08x', $challenge['nc']++); + $digest = md5($a1 . ':' . $challenge['nonce'] . ':' . $nc . ':' . + $challenge['cnonce'] . ':auth:' . $a2); + } + return 'Digest username="' . str_replace(array('\\', '"'), array('\\\\', '\\"'), $user) . '", ' . + 'realm="' . $challenge['realm'] . '", ' . + 'nonce="' . $challenge['nonce'] . '", ' . + 'uri="' . $url . '", ' . + 'response="' . $digest . '"' . + (!empty($challenge['opaque'])? + ', opaque="' . $challenge['opaque'] . '"': + '') . + (!empty($challenge['qop'])? + ', qop="auth", nc=' . $nc . ', cnonce="' . $challenge['cnonce'] . '"': + ''); + } + + /** + * Adds 'Authorization' header (if needed) to request headers array + * + * @param array request headers + * @param string request host (needed for digest authentication) + * @param string request URL (needed for digest authentication) + * @throws HTTP_Request2_Exception + */ + protected function addAuthorizationHeader(&$headers, $requestHost, $requestUrl) + { + if (!($auth = $this->request->getAuth())) { + return; + } + switch ($auth['scheme']) { + case HTTP_Request2::AUTH_BASIC: + $headers['authorization'] = + 'Basic ' . base64_encode($auth['user'] . ':' . $auth['password']); + break; + + case HTTP_Request2::AUTH_DIGEST: + unset($this->serverChallenge); + $fullUrl = ('/' == $requestUrl[0])? + $this->request->getUrl()->getScheme() . '://' . + $requestHost . $requestUrl: + $requestUrl; + foreach (array_keys(self::$challenges) as $key) { + if ($key == substr($fullUrl, 0, strlen($key))) { + $headers['authorization'] = $this->createDigestResponse( + $auth['user'], $auth['password'], + $requestUrl, self::$challenges[$key] + ); + $this->serverChallenge =& self::$challenges[$key]; + break; + } + } + break; + + default: + throw new HTTP_Request2_Exception( + "Unknown HTTP authentication scheme '{$auth['scheme']}'" + ); + } + } + + /** + * Adds 'Proxy-Authorization' header (if needed) to request headers array + * + * @param array request headers + * @param string request URL (needed for digest authentication) + * @throws HTTP_Request2_Exception + */ + protected function addProxyAuthorizationHeader(&$headers, $requestUrl) + { + if (!$this->request->getConfig('proxy_host') || + !($user = $this->request->getConfig('proxy_user')) || + (0 == strcasecmp('https', $this->request->getUrl()->getScheme()) && + HTTP_Request2::METHOD_CONNECT != $this->request->getMethod()) + ) { + return; + } + + $password = $this->request->getConfig('proxy_password'); + switch ($this->request->getConfig('proxy_auth_scheme')) { + case HTTP_Request2::AUTH_BASIC: + $headers['proxy-authorization'] = + 'Basic ' . base64_encode($user . ':' . $password); + break; + + case HTTP_Request2::AUTH_DIGEST: + unset($this->proxyChallenge); + $proxyUrl = 'proxy://' . $this->request->getConfig('proxy_host') . + ':' . $this->request->getConfig('proxy_port'); + if (!empty(self::$challenges[$proxyUrl])) { + $headers['proxy-authorization'] = $this->createDigestResponse( + $user, $password, + $requestUrl, self::$challenges[$proxyUrl] + ); + $this->proxyChallenge =& self::$challenges[$proxyUrl]; + } + break; + + default: + throw new HTTP_Request2_Exception( + "Unknown HTTP authentication scheme '" . + $this->request->getConfig('proxy_auth_scheme') . "'" + ); + } + } + + + /** + * Creates the string with the Request-Line and request headers + * + * @return string + * @throws HTTP_Request2_Exception + */ + protected function prepareHeaders() + { + $headers = $this->request->getHeaders(); + $url = $this->request->getUrl(); + $connect = HTTP_Request2::METHOD_CONNECT == $this->request->getMethod(); + $host = $url->getHost(); + + $defaultPort = 0 == strcasecmp($url->getScheme(), 'https')? 443: 80; + if (($port = $url->getPort()) && $port != $defaultPort || $connect) { + $host .= ':' . (empty($port)? $defaultPort: $port); + } + // Do not overwrite explicitly set 'Host' header, see bug #16146 + if (!isset($headers['host'])) { + $headers['host'] = $host; + } + + if ($connect) { + $requestUrl = $host; + + } else { + if (!$this->request->getConfig('proxy_host') || + 0 == strcasecmp($url->getScheme(), 'https') + ) { + $requestUrl = ''; + } else { + $requestUrl = $url->getScheme() . '://' . $host; + } + $path = $url->getPath(); + $query = $url->getQuery(); + $requestUrl .= (empty($path)? '/': $path) . (empty($query)? '': '?' . $query); + } + + if ('1.1' == $this->request->getConfig('protocol_version') && + extension_loaded('zlib') && !isset($headers['accept-encoding']) + ) { + $headers['accept-encoding'] = 'gzip, deflate'; + } + + $this->addAuthorizationHeader($headers, $host, $requestUrl); + $this->addProxyAuthorizationHeader($headers, $requestUrl); + $this->calculateRequestLength($headers); + + $headersStr = $this->request->getMethod() . ' ' . $requestUrl . ' HTTP/' . + $this->request->getConfig('protocol_version') . "\r\n"; + foreach ($headers as $name => $value) { + $canonicalName = implode('-', array_map('ucfirst', explode('-', $name))); + $headersStr .= $canonicalName . ': ' . $value . "\r\n"; + } + return $headersStr . "\r\n"; + } + + /** + * Sends the request body + * + * @throws HTTP_Request2_Exception + */ + protected function writeBody() + { + if (in_array($this->request->getMethod(), self::$bodyDisallowed) || + 0 == $this->contentLength + ) { + return; + } + + $position = 0; + $bufferSize = $this->request->getConfig('buffer_size'); + while ($position < $this->contentLength) { + if (is_string($this->requestBody)) { + $str = substr($this->requestBody, $position, $bufferSize); + } elseif (is_resource($this->requestBody)) { + $str = fread($this->requestBody, $bufferSize); + } else { + $str = $this->requestBody->read($bufferSize); + } + if (false === @fwrite($this->socket, $str, strlen($str))) { + throw new HTTP_Request2_Exception('Error writing request'); + } + // Provide the length of written string to the observer, request #7630 + $this->request->setLastEvent('sentBodyPart', strlen($str)); + $position += strlen($str); + } + } + + /** + * Reads the remote server's response + * + * @return HTTP_Request2_Response + * @throws HTTP_Request2_Exception + */ + protected function readResponse() + { + $bufferSize = $this->request->getConfig('buffer_size'); + + do { + $response = new HTTP_Request2_Response($this->readLine($bufferSize), true); + do { + $headerLine = $this->readLine($bufferSize); + $response->parseHeaderLine($headerLine); + } while ('' != $headerLine); + } while (in_array($response->getStatus(), array(100, 101))); + + $this->request->setLastEvent('receivedHeaders', $response); + + // No body possible in such responses + if (HTTP_Request2::METHOD_HEAD == $this->request->getMethod() || + (HTTP_Request2::METHOD_CONNECT == $this->request->getMethod() && + 200 <= $response->getStatus() && 300 > $response->getStatus()) || + in_array($response->getStatus(), array(204, 304)) + ) { + return $response; + } + + $chunked = 'chunked' == $response->getHeader('transfer-encoding'); + $length = $response->getHeader('content-length'); + $hasBody = false; + if ($chunked || null === $length || 0 < intval($length)) { + // RFC 2616, section 4.4: + // 3. ... If a message is received with both a + // Transfer-Encoding header field and a Content-Length header field, + // the latter MUST be ignored. + $toRead = ($chunked || null === $length)? null: $length; + $this->chunkLength = 0; + + while (!feof($this->socket) && (is_null($toRead) || 0 < $toRead)) { + if ($chunked) { + $data = $this->readChunked($bufferSize); + } elseif (is_null($toRead)) { + $data = $this->fread($bufferSize); + } else { + $data = $this->fread(min($toRead, $bufferSize)); + $toRead -= strlen($data); + } + if ('' == $data && (!$this->chunkLength || feof($this->socket))) { + break; + } + + $hasBody = true; + if ($this->request->getConfig('store_body')) { + $response->appendBody($data); + } + if (!in_array($response->getHeader('content-encoding'), array('identity', null))) { + $this->request->setLastEvent('receivedEncodedBodyPart', $data); + } else { + $this->request->setLastEvent('receivedBodyPart', $data); + } + } + } + + if ($hasBody) { + $this->request->setLastEvent('receivedBody', $response); + } + return $response; + } + + /** + * Reads until either the end of the socket or a newline, whichever comes first + * + * Strips the trailing newline from the returned data, handles global + * request timeout. Method idea borrowed from Net_Socket PEAR package. + * + * @param int buffer size to use for reading + * @return Available data up to the newline (not including newline) + * @throws HTTP_Request2_Exception In case of timeout + */ + protected function readLine($bufferSize) + { + $line = ''; + while (!feof($this->socket)) { + if ($this->timeout) { + stream_set_timeout($this->socket, max($this->timeout - time(), 1)); + } + $line .= @fgets($this->socket, $bufferSize); + $info = stream_get_meta_data($this->socket); + if ($info['timed_out'] || $this->timeout && time() > $this->timeout) { + throw new HTTP_Request2_Exception( + 'Request timed out after ' . + $this->request->getConfig('timeout') . ' second(s)' + ); + } + if (substr($line, -1) == "\n") { + return rtrim($line, "\r\n"); + } + } + return $line; + } + + /** + * Wrapper around fread(), handles global request timeout + * + * @param int Reads up to this number of bytes + * @return Data read from socket + * @throws HTTP_Request2_Exception In case of timeout + */ + protected function fread($length) + { + if ($this->timeout) { + stream_set_timeout($this->socket, max($this->timeout - time(), 1)); + } + $data = fread($this->socket, $length); + $info = stream_get_meta_data($this->socket); + if ($info['timed_out'] || $this->timeout && time() > $this->timeout) { + throw new HTTP_Request2_Exception( + 'Request timed out after ' . + $this->request->getConfig('timeout') . ' second(s)' + ); + } + return $data; + } + + /** + * Reads a part of response body encoded with chunked Transfer-Encoding + * + * @param int buffer size to use for reading + * @return string + * @throws HTTP_Request2_Exception + */ + protected function readChunked($bufferSize) + { + // at start of the next chunk? + if (0 == $this->chunkLength) { + $line = $this->readLine($bufferSize); + if (!preg_match('/^([0-9a-f]+)/i', $line, $matches)) { + throw new HTTP_Request2_Exception( + "Cannot decode chunked response, invalid chunk length '{$line}'" + ); + } else { + $this->chunkLength = hexdec($matches[1]); + // Chunk with zero length indicates the end + if (0 == $this->chunkLength) { + $this->readLine($bufferSize); + return ''; + } + } + } + $data = $this->fread(min($this->chunkLength, $bufferSize)); + $this->chunkLength -= strlen($data); + if (0 == $this->chunkLength) { + $this->readLine($bufferSize); // Trailing CRLF + } + return $data; + } +} + +?> \ No newline at end of file diff --git a/extlib/HTTP/Request2/Exception.php b/extlib/HTTP/Request2/Exception.php new file mode 100644 index 000000000..bfef7d6c2 --- /dev/null +++ b/extlib/HTTP/Request2/Exception.php @@ -0,0 +1,62 @@ + + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Exception.php 273003 2009-01-07 19:28:22Z avb $ + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** + * Base class for exceptions in PEAR + */ +require_once 'PEAR/Exception.php'; + +/** + * Exception class for HTTP_Request2 package + * + * Such a class is required by the Exception RFC: + * http://pear.php.net/pepr/pepr-proposal-show.php?id=132 + * + * @category HTTP + * @package HTTP_Request2 + * @version Release: 0.4.1 + */ +class HTTP_Request2_Exception extends PEAR_Exception +{ +} +?> \ No newline at end of file diff --git a/extlib/HTTP/Request2/MultipartBody.php b/extlib/HTTP/Request2/MultipartBody.php new file mode 100644 index 000000000..d8afd8344 --- /dev/null +++ b/extlib/HTTP/Request2/MultipartBody.php @@ -0,0 +1,274 @@ + + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: MultipartBody.php 287306 2009-08-14 15:22:52Z avb $ + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** + * Class for building multipart/form-data request body + * + * The class helps to reduce memory consumption by streaming large file uploads + * from disk, it also allows monitoring of upload progress (see request #7630) + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @version Release: 0.4.1 + * @link http://tools.ietf.org/html/rfc1867 + */ +class HTTP_Request2_MultipartBody +{ + /** + * MIME boundary + * @var string + */ + private $_boundary; + + /** + * Form parameters added via {@link HTTP_Request2::addPostParameter()} + * @var array + */ + private $_params = array(); + + /** + * File uploads added via {@link HTTP_Request2::addUpload()} + * @var array + */ + private $_uploads = array(); + + /** + * Header for parts with parameters + * @var string + */ + private $_headerParam = "--%s\r\nContent-Disposition: form-data; name=\"%s\"\r\n\r\n"; + + /** + * Header for parts with uploads + * @var string + */ + private $_headerUpload = "--%s\r\nContent-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\nContent-Type: %s\r\n\r\n"; + + /** + * Current position in parameter and upload arrays + * + * First number is index of "current" part, second number is position within + * "current" part + * + * @var array + */ + private $_pos = array(0, 0); + + + /** + * Constructor. Sets the arrays with POST data. + * + * @param array values of form fields set via {@link HTTP_Request2::addPostParameter()} + * @param array file uploads set via {@link HTTP_Request2::addUpload()} + * @param bool whether to append brackets to array variable names + */ + public function __construct(array $params, array $uploads, $useBrackets = true) + { + $this->_params = self::_flattenArray('', $params, $useBrackets); + foreach ($uploads as $fieldName => $f) { + if (!is_array($f['fp'])) { + $this->_uploads[] = $f + array('name' => $fieldName); + } else { + for ($i = 0; $i < count($f['fp']); $i++) { + $upload = array( + 'name' => ($useBrackets? $fieldName . '[' . $i . ']': $fieldName) + ); + foreach (array('fp', 'filename', 'size', 'type') as $key) { + $upload[$key] = $f[$key][$i]; + } + $this->_uploads[] = $upload; + } + } + } + } + + /** + * Returns the length of the body to use in Content-Length header + * + * @return integer + */ + public function getLength() + { + $boundaryLength = strlen($this->getBoundary()); + $headerParamLength = strlen($this->_headerParam) - 4 + $boundaryLength; + $headerUploadLength = strlen($this->_headerUpload) - 8 + $boundaryLength; + $length = $boundaryLength + 6; + foreach ($this->_params as $p) { + $length += $headerParamLength + strlen($p[0]) + strlen($p[1]) + 2; + } + foreach ($this->_uploads as $u) { + $length += $headerUploadLength + strlen($u['name']) + strlen($u['type']) + + strlen($u['filename']) + $u['size'] + 2; + } + return $length; + } + + /** + * Returns the boundary to use in Content-Type header + * + * @return string + */ + public function getBoundary() + { + if (empty($this->_boundary)) { + $this->_boundary = '--' . md5('PEAR-HTTP_Request2-' . microtime()); + } + return $this->_boundary; + } + + /** + * Returns next chunk of request body + * + * @param integer Amount of bytes to read + * @return string Up to $length bytes of data, empty string if at end + */ + public function read($length) + { + $ret = ''; + $boundary = $this->getBoundary(); + $paramCount = count($this->_params); + $uploadCount = count($this->_uploads); + while ($length > 0 && $this->_pos[0] <= $paramCount + $uploadCount) { + $oldLength = $length; + if ($this->_pos[0] < $paramCount) { + $param = sprintf($this->_headerParam, $boundary, + $this->_params[$this->_pos[0]][0]) . + $this->_params[$this->_pos[0]][1] . "\r\n"; + $ret .= substr($param, $this->_pos[1], $length); + $length -= min(strlen($param) - $this->_pos[1], $length); + + } elseif ($this->_pos[0] < $paramCount + $uploadCount) { + $pos = $this->_pos[0] - $paramCount; + $header = sprintf($this->_headerUpload, $boundary, + $this->_uploads[$pos]['name'], + $this->_uploads[$pos]['filename'], + $this->_uploads[$pos]['type']); + if ($this->_pos[1] < strlen($header)) { + $ret .= substr($header, $this->_pos[1], $length); + $length -= min(strlen($header) - $this->_pos[1], $length); + } + $filePos = max(0, $this->_pos[1] - strlen($header)); + if ($length > 0 && $filePos < $this->_uploads[$pos]['size']) { + $ret .= fread($this->_uploads[$pos]['fp'], $length); + $length -= min($length, $this->_uploads[$pos]['size'] - $filePos); + } + if ($length > 0) { + $start = $this->_pos[1] + ($oldLength - $length) - + strlen($header) - $this->_uploads[$pos]['size']; + $ret .= substr("\r\n", $start, $length); + $length -= min(2 - $start, $length); + } + + } else { + $closing = '--' . $boundary . "--\r\n"; + $ret .= substr($closing, $this->_pos[1], $length); + $length -= min(strlen($closing) - $this->_pos[1], $length); + } + if ($length > 0) { + $this->_pos = array($this->_pos[0] + 1, 0); + } else { + $this->_pos[1] += $oldLength; + } + } + return $ret; + } + + /** + * Sets the current position to the start of the body + * + * This allows reusing the same body in another request + */ + public function rewind() + { + $this->_pos = array(0, 0); + foreach ($this->_uploads as $u) { + rewind($u['fp']); + } + } + + /** + * Returns the body as string + * + * Note that it reads all file uploads into memory so it is a good idea not + * to use this method with large file uploads and rely on read() instead. + * + * @return string + */ + public function __toString() + { + $this->rewind(); + return $this->read($this->getLength()); + } + + + /** + * Helper function to change the (probably multidimensional) associative array + * into the simple one. + * + * @param string name for item + * @param mixed item's values + * @param bool whether to append [] to array variables' names + * @return array array with the following items: array('item name', 'item value'); + */ + private static function _flattenArray($name, $values, $useBrackets) + { + if (!is_array($values)) { + return array(array($name, $values)); + } else { + $ret = array(); + foreach ($values as $k => $v) { + if (empty($name)) { + $newName = $k; + } elseif ($useBrackets) { + $newName = $name . '[' . $k . ']'; + } else { + $newName = $name; + } + $ret = array_merge($ret, self::_flattenArray($newName, $v, $useBrackets)); + } + return $ret; + } + } +} +?> diff --git a/extlib/HTTP/Request2/Observer/Log.php b/extlib/HTTP/Request2/Observer/Log.php new file mode 100644 index 000000000..b1a055278 --- /dev/null +++ b/extlib/HTTP/Request2/Observer/Log.php @@ -0,0 +1,215 @@ + + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category HTTP + * @package HTTP_Request2 + * @author David Jean Louis + * @author Alexey Borzov + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Log.php 272593 2009-01-02 16:27:14Z avb $ + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** + * Exception class for HTTP_Request2 package + */ +require_once 'HTTP/Request2/Exception.php'; + +/** + * A debug observer useful for debugging / testing. + * + * This observer logs to a log target data corresponding to the various request + * and response events, it logs by default to php://output but can be configured + * to log to a file or via the PEAR Log package. + * + * A simple example: + * + * require_once 'HTTP/Request2.php'; + * require_once 'HTTP/Request2/Observer/Log.php'; + * + * $request = new HTTP_Request2('http://www.example.com'); + * $observer = new HTTP_Request2_Observer_Log(); + * $request->attach($observer); + * $request->send(); + * + * + * A more complex example with PEAR Log: + * + * require_once 'HTTP/Request2.php'; + * require_once 'HTTP/Request2/Observer/Log.php'; + * require_once 'Log.php'; + * + * $request = new HTTP_Request2('http://www.example.com'); + * // we want to log with PEAR log + * $observer = new HTTP_Request2_Observer_Log(Log::factory('console')); + * + * // we only want to log received headers + * $observer->events = array('receivedHeaders'); + * + * $request->attach($observer); + * $request->send(); + * + * + * @category HTTP + * @package HTTP_Request2 + * @author David Jean Louis + * @author Alexey Borzov + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version Release: 0.4.1 + * @link http://pear.php.net/package/HTTP_Request2 + */ +class HTTP_Request2_Observer_Log implements SplObserver +{ + // properties {{{ + + /** + * The log target, it can be a a resource or a PEAR Log instance. + * + * @var resource|Log $target + */ + protected $target = null; + + /** + * The events to log. + * + * @var array $events + */ + public $events = array( + 'connect', + 'sentHeaders', + 'sentBodyPart', + 'receivedHeaders', + 'receivedBody', + 'disconnect', + ); + + // }}} + // __construct() {{{ + + /** + * Constructor. + * + * @param mixed $target Can be a file path (default: php://output), a resource, + * or an instance of the PEAR Log class. + * @param array $events Array of events to listen to (default: all events) + * + * @return void + */ + public function __construct($target = 'php://output', array $events = array()) + { + if (!empty($events)) { + $this->events = $events; + } + if (is_resource($target) || $target instanceof Log) { + $this->target = $target; + } elseif (false === ($this->target = @fopen($target, 'w'))) { + throw new HTTP_Request2_Exception("Unable to open '{$target}'"); + } + } + + // }}} + // update() {{{ + + /** + * Called when the request notify us of an event. + * + * @param HTTP_Request2 $subject The HTTP_Request2 instance + * + * @return void + */ + public function update(SplSubject $subject) + { + $event = $subject->getLastEvent(); + if (!in_array($event['name'], $this->events)) { + return; + } + + switch ($event['name']) { + case 'connect': + $this->log('* Connected to ' . $event['data']); + break; + case 'sentHeaders': + $headers = explode("\r\n", $event['data']); + array_pop($headers); + foreach ($headers as $header) { + $this->log('> ' . $header); + } + break; + case 'sentBodyPart': + $this->log('> ' . $event['data']); + break; + case 'receivedHeaders': + $this->log(sprintf('< HTTP/%s %s %s', + $event['data']->getVersion(), + $event['data']->getStatus(), + $event['data']->getReasonPhrase())); + $headers = $event['data']->getHeader(); + foreach ($headers as $key => $val) { + $this->log('< ' . $key . ': ' . $val); + } + $this->log('< '); + break; + case 'receivedBody': + $this->log($event['data']->getBody()); + break; + case 'disconnect': + $this->log('* Disconnected'); + break; + } + } + + // }}} + // log() {{{ + + /** + * Log the given message to the configured target. + * + * @param string $message Message to display + * + * @return void + */ + protected function log($message) + { + if ($this->target instanceof Log) { + $this->target->debug($message); + } elseif (is_resource($this->target)) { + fwrite($this->target, $message . "\r\n"); + } + } + + // }}} +} + +?> \ No newline at end of file diff --git a/extlib/HTTP/Request2/Response.php b/extlib/HTTP/Request2/Response.php new file mode 100644 index 000000000..c7c1021fb --- /dev/null +++ b/extlib/HTTP/Request2/Response.php @@ -0,0 +1,549 @@ + + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Response.php 287948 2009-09-01 17:12:18Z avb $ + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** + * Exception class for HTTP_Request2 package + */ +require_once 'HTTP/Request2/Exception.php'; + +/** + * Class representing a HTTP response + * + * The class is designed to be used in "streaming" scenario, building the + * response as it is being received: + * + * $statusLine = read_status_line(); + * $response = new HTTP_Request2_Response($statusLine); + * do { + * $headerLine = read_header_line(); + * $response->parseHeaderLine($headerLine); + * } while ($headerLine != ''); + * + * while ($chunk = read_body()) { + * $response->appendBody($chunk); + * } + * + * var_dump($response->getHeader(), $response->getCookies(), $response->getBody()); + * + * + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @version Release: 0.4.1 + * @link http://tools.ietf.org/html/rfc2616#section-6 + */ +class HTTP_Request2_Response +{ + /** + * HTTP protocol version (e.g. 1.0, 1.1) + * @var string + */ + protected $version; + + /** + * Status code + * @var integer + * @link http://tools.ietf.org/html/rfc2616#section-6.1.1 + */ + protected $code; + + /** + * Reason phrase + * @var string + * @link http://tools.ietf.org/html/rfc2616#section-6.1.1 + */ + protected $reasonPhrase; + + /** + * Associative array of response headers + * @var array + */ + protected $headers = array(); + + /** + * Cookies set in the response + * @var array + */ + protected $cookies = array(); + + /** + * Name of last header processed by parseHederLine() + * + * Used to handle the headers that span multiple lines + * + * @var string + */ + protected $lastHeader = null; + + /** + * Response body + * @var string + */ + protected $body = ''; + + /** + * Whether the body is still encoded by Content-Encoding + * + * cURL provides the decoded body to the callback; if we are reading from + * socket the body is still gzipped / deflated + * + * @var bool + */ + protected $bodyEncoded; + + /** + * Associative array of HTTP status code / reason phrase. + * + * @var array + * @link http://tools.ietf.org/html/rfc2616#section-10 + */ + protected static $phrases = array( + + // 1xx: Informational - Request received, continuing process + 100 => 'Continue', + 101 => 'Switching Protocols', + + // 2xx: Success - The action was successfully received, understood and + // accepted + 200 => 'OK', + 201 => 'Created', + 202 => 'Accepted', + 203 => 'Non-Authoritative Information', + 204 => 'No Content', + 205 => 'Reset Content', + 206 => 'Partial Content', + + // 3xx: Redirection - Further action must be taken in order to complete + // the request + 300 => 'Multiple Choices', + 301 => 'Moved Permanently', + 302 => 'Found', // 1.1 + 303 => 'See Other', + 304 => 'Not Modified', + 305 => 'Use Proxy', + 307 => 'Temporary Redirect', + + // 4xx: Client Error - The request contains bad syntax or cannot be + // fulfilled + 400 => 'Bad Request', + 401 => 'Unauthorized', + 402 => 'Payment Required', + 403 => 'Forbidden', + 404 => 'Not Found', + 405 => 'Method Not Allowed', + 406 => 'Not Acceptable', + 407 => 'Proxy Authentication Required', + 408 => 'Request Timeout', + 409 => 'Conflict', + 410 => 'Gone', + 411 => 'Length Required', + 412 => 'Precondition Failed', + 413 => 'Request Entity Too Large', + 414 => 'Request-URI Too Long', + 415 => 'Unsupported Media Type', + 416 => 'Requested Range Not Satisfiable', + 417 => 'Expectation Failed', + + // 5xx: Server Error - The server failed to fulfill an apparently + // valid request + 500 => 'Internal Server Error', + 501 => 'Not Implemented', + 502 => 'Bad Gateway', + 503 => 'Service Unavailable', + 504 => 'Gateway Timeout', + 505 => 'HTTP Version Not Supported', + 509 => 'Bandwidth Limit Exceeded', + + ); + + /** + * Constructor, parses the response status line + * + * @param string Response status line (e.g. "HTTP/1.1 200 OK") + * @param bool Whether body is still encoded by Content-Encoding + * @throws HTTP_Request2_Exception if status line is invalid according to spec + */ + public function __construct($statusLine, $bodyEncoded = true) + { + if (!preg_match('!^HTTP/(\d\.\d) (\d{3})(?: (.+))?!', $statusLine, $m)) { + throw new HTTP_Request2_Exception("Malformed response: {$statusLine}"); + } + $this->version = $m[1]; + $this->code = intval($m[2]); + if (!empty($m[3])) { + $this->reasonPhrase = trim($m[3]); + } elseif (!empty(self::$phrases[$this->code])) { + $this->reasonPhrase = self::$phrases[$this->code]; + } + $this->bodyEncoded = (bool)$bodyEncoded; + } + + /** + * Parses the line from HTTP response filling $headers array + * + * The method should be called after reading the line from socket or receiving + * it into cURL callback. Passing an empty string here indicates the end of + * response headers and triggers additional processing, so be sure to pass an + * empty string in the end. + * + * @param string Line from HTTP response + */ + public function parseHeaderLine($headerLine) + { + $headerLine = trim($headerLine, "\r\n"); + + // empty string signals the end of headers, process the received ones + if ('' == $headerLine) { + if (!empty($this->headers['set-cookie'])) { + $cookies = is_array($this->headers['set-cookie'])? + $this->headers['set-cookie']: + array($this->headers['set-cookie']); + foreach ($cookies as $cookieString) { + $this->parseCookie($cookieString); + } + unset($this->headers['set-cookie']); + } + foreach (array_keys($this->headers) as $k) { + if (is_array($this->headers[$k])) { + $this->headers[$k] = implode(', ', $this->headers[$k]); + } + } + + // string of the form header-name: header value + } elseif (preg_match('!^([^\x00-\x1f\x7f-\xff()<>@,;:\\\\"/\[\]?={}\s]+):(.+)$!', $headerLine, $m)) { + $name = strtolower($m[1]); + $value = trim($m[2]); + if (empty($this->headers[$name])) { + $this->headers[$name] = $value; + } else { + if (!is_array($this->headers[$name])) { + $this->headers[$name] = array($this->headers[$name]); + } + $this->headers[$name][] = $value; + } + $this->lastHeader = $name; + + // string + } elseif (preg_match('!^\s+(.+)$!', $headerLine, $m) && $this->lastHeader) { + if (!is_array($this->headers[$this->lastHeader])) { + $this->headers[$this->lastHeader] .= ' ' . trim($m[1]); + } else { + $key = count($this->headers[$this->lastHeader]) - 1; + $this->headers[$this->lastHeader][$key] .= ' ' . trim($m[1]); + } + } + } + + /** + * Parses a Set-Cookie header to fill $cookies array + * + * @param string value of Set-Cookie header + * @link http://cgi.netscape.com/newsref/std/cookie_spec.html + */ + protected function parseCookie($cookieString) + { + $cookie = array( + 'expires' => null, + 'domain' => null, + 'path' => null, + 'secure' => false + ); + + // Only a name=value pair + if (!strpos($cookieString, ';')) { + $pos = strpos($cookieString, '='); + $cookie['name'] = trim(substr($cookieString, 0, $pos)); + $cookie['value'] = trim(substr($cookieString, $pos + 1)); + + // Some optional parameters are supplied + } else { + $elements = explode(';', $cookieString); + $pos = strpos($elements[0], '='); + $cookie['name'] = trim(substr($elements[0], 0, $pos)); + $cookie['value'] = trim(substr($elements[0], $pos + 1)); + + for ($i = 1; $i < count($elements); $i++) { + if (false === strpos($elements[$i], '=')) { + $elName = trim($elements[$i]); + $elValue = null; + } else { + list ($elName, $elValue) = array_map('trim', explode('=', $elements[$i])); + } + $elName = strtolower($elName); + if ('secure' == $elName) { + $cookie['secure'] = true; + } elseif ('expires' == $elName) { + $cookie['expires'] = str_replace('"', '', $elValue); + } elseif ('path' == $elName || 'domain' == $elName) { + $cookie[$elName] = urldecode($elValue); + } else { + $cookie[$elName] = $elValue; + } + } + } + $this->cookies[] = $cookie; + } + + /** + * Appends a string to the response body + * @param string + */ + public function appendBody($bodyChunk) + { + $this->body .= $bodyChunk; + } + + /** + * Returns the status code + * @return integer + */ + public function getStatus() + { + return $this->code; + } + + /** + * Returns the reason phrase + * @return string + */ + public function getReasonPhrase() + { + return $this->reasonPhrase; + } + + /** + * Returns either the named header or all response headers + * + * @param string Name of header to return + * @return string|array Value of $headerName header (null if header is + * not present), array of all response headers if + * $headerName is null + */ + public function getHeader($headerName = null) + { + if (null === $headerName) { + return $this->headers; + } else { + $headerName = strtolower($headerName); + return isset($this->headers[$headerName])? $this->headers[$headerName]: null; + } + } + + /** + * Returns cookies set in response + * + * @return array + */ + public function getCookies() + { + return $this->cookies; + } + + /** + * Returns the body of the response + * + * @return string + * @throws HTTP_Request2_Exception if body cannot be decoded + */ + public function getBody() + { + if (!$this->bodyEncoded || + !in_array(strtolower($this->getHeader('content-encoding')), array('gzip', 'deflate')) + ) { + return $this->body; + + } else { + if (extension_loaded('mbstring') && (2 & ini_get('mbstring.func_overload'))) { + $oldEncoding = mb_internal_encoding(); + mb_internal_encoding('iso-8859-1'); + } + + try { + switch (strtolower($this->getHeader('content-encoding'))) { + case 'gzip': + $decoded = self::decodeGzip($this->body); + break; + case 'deflate': + $decoded = self::decodeDeflate($this->body); + } + } catch (Exception $e) { + } + + if (!empty($oldEncoding)) { + mb_internal_encoding($oldEncoding); + } + if (!empty($e)) { + throw $e; + } + return $decoded; + } + } + + /** + * Get the HTTP version of the response + * + * @return string + */ + public function getVersion() + { + return $this->version; + } + + /** + * Decodes the message-body encoded by gzip + * + * The real decoding work is done by gzinflate() built-in function, this + * method only parses the header and checks data for compliance with + * RFC 1952 + * + * @param string gzip-encoded data + * @return string decoded data + * @throws HTTP_Request2_Exception + * @link http://tools.ietf.org/html/rfc1952 + */ + public static function decodeGzip($data) + { + $length = strlen($data); + // If it doesn't look like gzip-encoded data, don't bother + if (18 > $length || strcmp(substr($data, 0, 2), "\x1f\x8b")) { + return $data; + } + if (!function_exists('gzinflate')) { + throw new HTTP_Request2_Exception('Unable to decode body: gzip extension not available'); + } + $method = ord(substr($data, 2, 1)); + if (8 != $method) { + throw new HTTP_Request2_Exception('Error parsing gzip header: unknown compression method'); + } + $flags = ord(substr($data, 3, 1)); + if ($flags & 224) { + throw new HTTP_Request2_Exception('Error parsing gzip header: reserved bits are set'); + } + + // header is 10 bytes minimum. may be longer, though. + $headerLength = 10; + // extra fields, need to skip 'em + if ($flags & 4) { + if ($length - $headerLength - 2 < 8) { + throw new HTTP_Request2_Exception('Error parsing gzip header: data too short'); + } + $extraLength = unpack('v', substr($data, 10, 2)); + if ($length - $headerLength - 2 - $extraLength[1] < 8) { + throw new HTTP_Request2_Exception('Error parsing gzip header: data too short'); + } + $headerLength += $extraLength[1] + 2; + } + // file name, need to skip that + if ($flags & 8) { + if ($length - $headerLength - 1 < 8) { + throw new HTTP_Request2_Exception('Error parsing gzip header: data too short'); + } + $filenameLength = strpos(substr($data, $headerLength), chr(0)); + if (false === $filenameLength || $length - $headerLength - $filenameLength - 1 < 8) { + throw new HTTP_Request2_Exception('Error parsing gzip header: data too short'); + } + $headerLength += $filenameLength + 1; + } + // comment, need to skip that also + if ($flags & 16) { + if ($length - $headerLength - 1 < 8) { + throw new HTTP_Request2_Exception('Error parsing gzip header: data too short'); + } + $commentLength = strpos(substr($data, $headerLength), chr(0)); + if (false === $commentLength || $length - $headerLength - $commentLength - 1 < 8) { + throw new HTTP_Request2_Exception('Error parsing gzip header: data too short'); + } + $headerLength += $commentLength + 1; + } + // have a CRC for header. let's check + if ($flags & 2) { + if ($length - $headerLength - 2 < 8) { + throw new HTTP_Request2_Exception('Error parsing gzip header: data too short'); + } + $crcReal = 0xffff & crc32(substr($data, 0, $headerLength)); + $crcStored = unpack('v', substr($data, $headerLength, 2)); + if ($crcReal != $crcStored[1]) { + throw new HTTP_Request2_Exception('Header CRC check failed'); + } + $headerLength += 2; + } + // unpacked data CRC and size at the end of encoded data + $tmp = unpack('V2', substr($data, -8)); + $dataCrc = $tmp[1]; + $dataSize = $tmp[2]; + + // finally, call the gzinflate() function + // don't pass $dataSize to gzinflate, see bugs #13135, #14370 + $unpacked = gzinflate(substr($data, $headerLength, -8)); + if (false === $unpacked) { + throw new HTTP_Request2_Exception('gzinflate() call failed'); + } elseif ($dataSize != strlen($unpacked)) { + throw new HTTP_Request2_Exception('Data size check failed'); + } elseif ((0xffffffff & $dataCrc) != (0xffffffff & crc32($unpacked))) { + throw new HTTP_Request2_Exception('Data CRC check failed'); + } + return $unpacked; + } + + /** + * Decodes the message-body encoded by deflate + * + * @param string deflate-encoded data + * @return string decoded data + * @throws HTTP_Request2_Exception + */ + public static function decodeDeflate($data) + { + if (!function_exists('gzuncompress')) { + throw new HTTP_Request2_Exception('Unable to decode body: gzip extension not available'); + } + // RFC 2616 defines 'deflate' encoding as zlib format from RFC 1950, + // while many applications send raw deflate stream from RFC 1951. + // We should check for presence of zlib header and use gzuncompress() or + // gzinflate() as needed. See bug #15305 + $header = unpack('n', substr($data, 0, 2)); + return (0 == $header[1] % 31)? gzuncompress($data): gzinflate($data); + } +} +?> \ No newline at end of file diff --git a/extlib/Net/URL2.php b/extlib/Net/URL2.php index 7a654aed8..f7fbcd9ce 100644 --- a/extlib/Net/URL2.php +++ b/extlib/Net/URL2.php @@ -1,44 +1,58 @@ | -// +-----------------------------------------------------------------------+ -// -// $Id: URL2.php,v 1.10 2008/04/26 21:57:08 schmidt Exp $ -// -// Net_URL2 Class (PHP5 Only) - -// This code is released under the BSD License - http://www.opensource.org/licenses/bsd-license.php /** - * @license BSD License + * Net_URL2, a class representing a URL as per RFC 3986. + * + * PHP version 5 + * + * LICENSE: + * + * Copyright (c) 2007-2009, Peytz & Co. A/S + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * * Neither the name of the PHP_LexerGenerator nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category Networking + * @package Net_URL2 + * @author Christian Schmidt + * @copyright 2007-2008 Peytz & Co. A/S + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: URL2.php 286661 2009-08-02 12:50:54Z schmidt $ + * @link http://www.rfc-editor.org/rfc/rfc3986.txt + */ + +/** + * Represents a URL as per RFC 3986. + * + * @category Networking + * @package Net_URL2 + * @author Christian Schmidt + * @copyright 2007-2008 Peytz & Co. ApS + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version Release: @package_version@ + * @link http://pear.php.net/package/Net_URL2 */ class Net_URL2 { @@ -46,24 +60,24 @@ class Net_URL2 * Do strict parsing in resolve() (see RFC 3986, section 5.2.2). Default * is true. */ - const OPTION_STRICT = 'strict'; + const OPTION_STRICT = 'strict'; /** * Represent arrays in query using PHP's [] notation. Default is true. */ - const OPTION_USE_BRACKETS = 'use_brackets'; + const OPTION_USE_BRACKETS = 'use_brackets'; /** * URL-encode query variable keys. Default is true. */ - const OPTION_ENCODE_KEYS = 'encode_keys'; + const OPTION_ENCODE_KEYS = 'encode_keys'; /** * Query variable separators when parsing the query string. Every character * is considered a separator. Default is specified by the * arg_separator.input php.ini setting (this defaults to "&"). */ - const OPTION_SEPARATOR_INPUT = 'input_separator'; + const OPTION_SEPARATOR_INPUT = 'input_separator'; /** * Query variable separator used when generating the query string. Default @@ -75,7 +89,7 @@ class Net_URL2 /** * Default options corresponds to how PHP handles $_GET. */ - private $options = array( + private $_options = array( self::OPTION_STRICT => true, self::OPTION_USE_BRACKETS => true, self::OPTION_ENCODE_KEYS => true, @@ -86,41 +100,43 @@ class Net_URL2 /** * @var string|bool */ - private $scheme = false; + private $_scheme = false; /** * @var string|bool */ - private $userinfo = false; + private $_userinfo = false; /** * @var string|bool */ - private $host = false; + private $_host = false; /** * @var int|bool */ - private $port = false; + private $_port = false; /** * @var string */ - private $path = ''; + private $_path = ''; /** * @var string|bool */ - private $query = false; + private $_query = false; /** * @var string|bool */ - private $fragment = false; + private $_fragment = false; /** + * Constructor. + * * @param string $url an absolute or relative URL - * @param array $options + * @param array $options an array of OPTION_xxx constants */ public function __construct($url, $options = null) { @@ -130,12 +146,12 @@ class Net_URL2 ini_get('arg_separator.output')); if (is_array($options)) { foreach ($options as $optionName => $value) { - $this->setOption($optionName); + $this->setOption($optionName, $value); } } if (preg_match('@^([a-z][a-z0-9.+-]*):@i', $url, $reg)) { - $this->scheme = $reg[1]; + $this->_scheme = $reg[1]; $url = substr($url, strlen($reg[0])); } @@ -145,19 +161,58 @@ class Net_URL2 } $i = strcspn($url, '?#'); - $this->path = substr($url, 0, $i); + $this->_path = substr($url, 0, $i); $url = substr($url, $i); if (preg_match('@^\?([^#]*)@', $url, $reg)) { - $this->query = $reg[1]; + $this->_query = $reg[1]; $url = substr($url, strlen($reg[0])); } if ($url) { - $this->fragment = substr($url, 1); + $this->_fragment = substr($url, 1); } } + /** + * Magic Setter. + * + * This method will magically set the value of a private variable ($var) + * with the value passed as the args + * + * @param string $var The private variable to set. + * @param mixed $arg An argument of any type. + * @return void + */ + public function __set($var, $arg) + { + $method = 'set' . $var; + if (method_exists($this, $method)) { + $this->$method($arg); + } + } + + /** + * Magic Getter. + * + * This is the magic get method to retrieve the private variable + * that was set by either __set() or it's setter... + * + * @param string $var The property name to retrieve. + * @return mixed $this->$var Either a boolean false if the + * property is not set or the value + * of the private property. + */ + public function __get($var) + { + $method = 'get' . $var; + if (method_exists($this, $method)) { + return $this->$method(); + } + + return false; + } + /** * Returns the scheme, e.g. "http" or "urn", or false if there is no * scheme specified, i.e. if this is a relative URL. @@ -166,18 +221,23 @@ class Net_URL2 */ public function getScheme() { - return $this->scheme; + return $this->_scheme; } /** - * @param string|bool $scheme + * Sets the scheme, e.g. "http" or "urn". Specify false if there is no + * scheme specified, i.e. if this is a relative URL. + * + * @param string|bool $scheme e.g. "http" or "urn", or false if there is no + * scheme specified, i.e. if this is a relative + * URL * * @return void * @see getScheme() */ public function setScheme($scheme) { - $this->scheme = $scheme; + $this->_scheme = $scheme; } /** @@ -188,7 +248,9 @@ class Net_URL2 */ public function getUser() { - return $this->userinfo !== false ? preg_replace('@:.*$@', '', $this->userinfo) : false; + return $this->_userinfo !== false + ? preg_replace('@:.*$@', '', $this->_userinfo) + : false; } /** @@ -201,7 +263,9 @@ class Net_URL2 */ public function getPassword() { - return $this->userinfo !== false ? substr(strstr($this->userinfo, ':'), 1) : false; + return $this->_userinfo !== false + ? substr(strstr($this->_userinfo, ':'), 1) + : false; } /** @@ -212,7 +276,7 @@ class Net_URL2 */ public function getUserinfo() { - return $this->userinfo; + return $this->_userinfo; } /** @@ -220,15 +284,15 @@ class Net_URL2 * in the userinfo part as username ":" password. * * @param string|bool $userinfo userinfo or username - * @param string|bool $password + * @param string|bool $password optional password, or false * * @return void */ public function setUserinfo($userinfo, $password = false) { - $this->userinfo = $userinfo; + $this->_userinfo = $userinfo; if ($password !== false) { - $this->userinfo .= ':' . $password; + $this->_userinfo .= ':' . $password; } } @@ -236,21 +300,24 @@ class Net_URL2 * Returns the host part, or false if there is no authority part, e.g. * relative URLs. * - * @return string|bool + * @return string|bool a hostname, an IP address, or false */ public function getHost() { - return $this->host; + return $this->_host; } /** - * @param string|bool $host + * Sets the host part. Specify false if there is no authority part, e.g. + * relative URLs. + * + * @param string|bool $host a hostname, an IP address, or false * * @return void */ public function setHost($host) { - $this->host = $host; + $this->_host = $host; } /** @@ -261,65 +328,72 @@ class Net_URL2 */ public function getPort() { - return $this->port; + return $this->_port; } /** - * @param int|bool $port + * Sets the port number. Specify false if there is no port number specified, + * i.e. if the default port is to be used. + * + * @param int|bool $port a port number, or false * * @return void */ public function setPort($port) { - $this->port = intval($port); + $this->_port = intval($port); } /** * Returns the authority part, i.e. [ userinfo "@" ] host [ ":" port ], or - * false if there is no authority none. + * false if there is no authority. * * @return string|bool */ public function getAuthority() { - if (!$this->host) { + if (!$this->_host) { return false; } $authority = ''; - if ($this->userinfo !== false) { - $authority .= $this->userinfo . '@'; + if ($this->_userinfo !== false) { + $authority .= $this->_userinfo . '@'; } - $authority .= $this->host; + $authority .= $this->_host; - if ($this->port !== false) { - $authority .= ':' . $this->port; + if ($this->_port !== false) { + $authority .= ':' . $this->_port; } return $authority; } /** - * @param string|false $authority + * Sets the authority part, i.e. [ userinfo "@" ] host [ ":" port ]. Specify + * false if there is no authority. + * + * @param string|false $authority a hostname or an IP addresse, possibly + * with userinfo prefixed and port number + * appended, e.g. "foo:bar@example.org:81". * * @return void */ public function setAuthority($authority) { - $this->user = false; - $this->pass = false; - $this->host = false; - $this->port = false; - if (preg_match('@^(([^\@]+)\@)?([^:]+)(:(\d*))?$@', $authority, $reg)) { + $this->_userinfo = false; + $this->_host = false; + $this->_port = false; + if (preg_match('@^(([^\@]*)\@)?([^:]+)(:(\d*))?$@', $authority, $reg)) { if ($reg[1]) { - $this->userinfo = $reg[2]; + $this->_userinfo = $reg[2]; } - $this->host = $reg[3]; + $this->_host = $reg[3]; if (isset($reg[5])) { - $this->port = intval($reg[5]); + $this->_port = intval($reg[5]); } } } @@ -331,65 +405,74 @@ class Net_URL2 */ public function getPath() { - return $this->path; + return $this->_path; } /** - * @param string $path + * Sets the path part (possibly an empty string). + * + * @param string $path a path * * @return void */ public function setPath($path) { - $this->path = $path; + $this->_path = $path; } /** * Returns the query string (excluding the leading "?"), or false if "?" - * isn't present in the URL. + * is not present in the URL. * * @return string|bool * @see self::getQueryVariables() */ public function getQuery() { - return $this->query; + return $this->_query; } /** - * @param string|bool $query + * Sets the query string (excluding the leading "?"). Specify false if "?" + * is not present in the URL. + * + * @param string|bool $query a query string, e.g. "foo=1&bar=2" * * @return void * @see self::setQueryVariables() */ public function setQuery($query) { - $this->query = $query; + $this->_query = $query; } /** - * Returns the fragment name, or false if "#" isn't present in the URL. + * Returns the fragment name, or false if "#" is not present in the URL. * * @return string|bool */ public function getFragment() { - return $this->fragment; + return $this->_fragment; } /** - * @param string|bool $fragment + * Sets the fragment name. Specify false if "#" is not present in the URL. + * + * @param string|bool $fragment a fragment excluding the leading "#", or + * false * * @return void */ public function setFragment($fragment) { - $this->fragment = $fragment; + $this->_fragment = $fragment; } /** * Returns the query string like an array as the variables would appear in - * $_GET in a PHP script. + * $_GET in a PHP script. If the URL does not contain a "?", an empty array + * is returned. * * @return array */ @@ -398,7 +481,7 @@ class Net_URL2 $pattern = '/[' . preg_quote($this->getOption(self::OPTION_SEPARATOR_INPUT), '/') . ']/'; - $parts = preg_split($pattern, $this->query, -1, PREG_SPLIT_NO_EMPTY); + $parts = preg_split($pattern, $this->_query, -1, PREG_SPLIT_NO_EMPTY); $return = array(); foreach ($parts as $part) { @@ -445,6 +528,8 @@ class Net_URL2 } /** + * Sets the query string to the specified variable in the query string. + * * @param array $array (name => value) array * * @return void @@ -452,11 +537,11 @@ class Net_URL2 public function setQueryVariables(array $array) { if (!$array) { - $this->query = false; + $this->_query = false; } else { foreach ($array as $name => $value) { if ($this->getOption(self::OPTION_ENCODE_KEYS)) { - $name = rawurlencode($name); + $name = self::urlencode($name); } if (is_array($value)) { @@ -466,19 +551,21 @@ class Net_URL2 : ($name . '=' . $v); } } elseif (!is_null($value)) { - $parts[] = $name . '=' . $value; + $parts[] = $name . '=' . self::urlencode($value); } else { $parts[] = $name; } } - $this->query = implode($this->getOption(self::OPTION_SEPARATOR_OUTPUT), - $parts); + $this->_query = implode($this->getOption(self::OPTION_SEPARATOR_OUTPUT), + $parts); } } /** - * @param string $name - * @param mixed $value + * Sets the specified variable in the query string. + * + * @param string $name variable name + * @param mixed $value variable value * * @return array */ @@ -490,7 +577,9 @@ class Net_URL2 } /** - * @param string $name + * Removes the specifed variable from the query string. + * + * @param string $name a query string variable, e.g. "foo" in "?foo=1" * * @return void */ @@ -511,27 +600,38 @@ class Net_URL2 // See RFC 3986, section 5.3 $url = ""; - if ($this->scheme !== false) { - $url .= $this->scheme . ':'; + if ($this->_scheme !== false) { + $url .= $this->_scheme . ':'; } $authority = $this->getAuthority(); if ($authority !== false) { $url .= '//' . $authority; } - $url .= $this->path; + $url .= $this->_path; - if ($this->query !== false) { - $url .= '?' . $this->query; + if ($this->_query !== false) { + $url .= '?' . $this->_query; } - if ($this->fragment !== false) { - $url .= '#' . $this->fragment; + if ($this->_fragment !== false) { + $url .= '#' . $this->_fragment; } return $url; } + /** + * Returns a string representation of this URL. + * + * @return string + * @see toString() + */ + public function __toString() + { + return $this->getURL(); + } + /** * Returns a normalized string representation of this URL. This is useful * for comparison of URLs. @@ -555,36 +655,38 @@ class Net_URL2 // See RFC 3886, section 6 // Schemes are case-insensitive - if ($this->scheme) { - $this->scheme = strtolower($this->scheme); + if ($this->_scheme) { + $this->_scheme = strtolower($this->_scheme); } // Hostnames are case-insensitive - if ($this->host) { - $this->host = strtolower($this->host); + if ($this->_host) { + $this->_host = strtolower($this->_host); } // Remove default port number for known schemes (RFC 3986, section 6.2.3) - if ($this->port && - $this->scheme && - $this->port == getservbyname($this->scheme, 'tcp')) { + if ($this->_port && + $this->_scheme && + $this->_port == getservbyname($this->_scheme, 'tcp')) { - $this->port = false; + $this->_port = false; } // Normalize case of %XX percentage-encodings (RFC 3986, section 6.2.2.1) - foreach (array('userinfo', 'host', 'path') as $part) { + foreach (array('_userinfo', '_host', '_path') as $part) { if ($this->$part) { - $this->$part = preg_replace('/%[0-9a-f]{2}/ie', 'strtoupper("\0")', $this->$part); + $this->$part = preg_replace('/%[0-9a-f]{2}/ie', + 'strtoupper("\0")', + $this->$part); } } // Path segment normalization (RFC 3986, section 6.2.2.3) - $this->path = self::removeDotSegments($this->path); + $this->_path = self::removeDotSegments($this->_path); // Scheme based normalization (RFC 3986, section 6.2.3) - if ($this->host && !$this->path) { - $this->path = '/'; + if ($this->_host && !$this->_path) { + $this->_path = '/'; } } @@ -595,7 +697,7 @@ class Net_URL2 */ public function isAbsolute() { - return (bool) $this->scheme; + return (bool) $this->_scheme; } /** @@ -608,7 +710,7 @@ class Net_URL2 */ public function resolve($reference) { - if (is_string($reference)) { + if (!$reference instanceof Net_URL2) { $reference = new self($reference); } if (!$this->isAbsolute()) { @@ -617,54 +719,54 @@ class Net_URL2 // A non-strict parser may ignore a scheme in the reference if it is // identical to the base URI's scheme. - if (!$this->getOption(self::OPTION_STRICT) && $reference->scheme == $this->scheme) { - $reference->scheme = false; + if (!$this->getOption(self::OPTION_STRICT) && $reference->_scheme == $this->_scheme) { + $reference->_scheme = false; } $target = new self(''); - if ($reference->scheme !== false) { - $target->scheme = $reference->scheme; + if ($reference->_scheme !== false) { + $target->_scheme = $reference->_scheme; $target->setAuthority($reference->getAuthority()); - $target->path = self::removeDotSegments($reference->path); - $target->query = $reference->query; + $target->_path = self::removeDotSegments($reference->_path); + $target->_query = $reference->_query; } else { $authority = $reference->getAuthority(); if ($authority !== false) { $target->setAuthority($authority); - $target->path = self::removeDotSegments($reference->path); - $target->query = $reference->query; + $target->_path = self::removeDotSegments($reference->_path); + $target->_query = $reference->_query; } else { - if ($reference->path == '') { - $target->path = $this->path; - if ($reference->query !== false) { - $target->query = $reference->query; + if ($reference->_path == '') { + $target->_path = $this->_path; + if ($reference->_query !== false) { + $target->_query = $reference->_query; } else { - $target->query = $this->query; + $target->_query = $this->_query; } } else { - if (substr($reference->path, 0, 1) == '/') { - $target->path = self::removeDotSegments($reference->path); + if (substr($reference->_path, 0, 1) == '/') { + $target->_path = self::removeDotSegments($reference->_path); } else { // Merge paths (RFC 3986, section 5.2.3) - if ($this->host !== false && $this->path == '') { - $target->path = '/' . $this->path; + if ($this->_host !== false && $this->_path == '') { + $target->_path = '/' . $this->_path; } else { - $i = strrpos($this->path, '/'); + $i = strrpos($this->_path, '/'); if ($i !== false) { - $target->path = substr($this->path, 0, $i + 1); + $target->_path = substr($this->_path, 0, $i + 1); } - $target->path .= $reference->path; + $target->_path .= $reference->_path; } - $target->path = self::removeDotSegments($target->path); + $target->_path = self::removeDotSegments($target->_path); } - $target->query = $reference->query; + $target->_query = $reference->_query; } $target->setAuthority($this->getAuthority()); } - $target->scheme = $this->scheme; + $target->_scheme = $this->_scheme; } - $target->fragment = $reference->fragment; + $target->_fragment = $reference->_fragment; return $target; } @@ -677,7 +779,7 @@ class Net_URL2 * * @return string a path */ - private static function removeDotSegments($path) + public static function removeDotSegments($path) { $output = ''; @@ -685,28 +787,25 @@ class Net_URL2 // method $j = 0; while ($path && $j++ < 100) { - // Step A if (substr($path, 0, 2) == './') { + // Step 2.A $path = substr($path, 2); } elseif (substr($path, 0, 3) == '../') { + // Step 2.A $path = substr($path, 3); - - // Step B } elseif (substr($path, 0, 3) == '/./' || $path == '/.') { + // Step 2.B $path = '/' . substr($path, 3); - - // Step C } elseif (substr($path, 0, 4) == '/../' || $path == '/..') { - $path = '/' . substr($path, 4); - $i = strrpos($output, '/'); + // Step 2.C + $path = '/' . substr($path, 4); + $i = strrpos($output, '/'); $output = $i === false ? '' : substr($output, 0, $i); - - // Step D } elseif ($path == '.' || $path == '..') { + // Step 2.D $path = ''; - - // Step E } else { + // Step 2.E $i = strpos($path, '/'); if ($i === 0) { $i = strpos($path, '/', 1); @@ -722,6 +821,22 @@ class Net_URL2 return $output; } + /** + * Percent-encodes all non-alphanumeric characters except these: _ . - ~ + * Similar to PHP's rawurlencode(), except that it also encodes ~ in PHP + * 5.2.x and earlier. + * + * @param $raw the string to encode + * @return string + */ + public static function urlencode($string) + { + $encoded = rawurlencode($string); + // This is only necessary in PHP < 5.3. + $encoded = str_replace('%7E', '~', $encoded); + return $encoded; + } + /** * Returns a Net_URL2 instance representing the canonical URL of the * currently executing PHP script. @@ -737,13 +852,13 @@ class Net_URL2 // Begin with a relative URL $url = new self($_SERVER['PHP_SELF']); - $url->scheme = isset($_SERVER['HTTPS']) ? 'https' : 'http'; - $url->host = $_SERVER['SERVER_NAME']; + $url->_scheme = isset($_SERVER['HTTPS']) ? 'https' : 'http'; + $url->_host = $_SERVER['SERVER_NAME']; $port = intval($_SERVER['SERVER_PORT']); - if ($url->scheme == 'http' && $port != 80 || - $url->scheme == 'https' && $port != 443) { + if ($url->_scheme == 'http' && $port != 80 || + $url->_scheme == 'https' && $port != 443) { - $url->port = $port; + $url->_port = $port; } return $url; } @@ -773,7 +888,7 @@ class Net_URL2 // Begin with a relative URL $url = new self($_SERVER['REQUEST_URI']); - $url->scheme = isset($_SERVER['HTTPS']) ? 'https' : 'http'; + $url->_scheme = isset($_SERVER['HTTPS']) ? 'https' : 'http'; // Set host and possibly port $url->setAuthority($_SERVER['HTTP_HOST']); return $url; @@ -792,10 +907,10 @@ class Net_URL2 */ function setOption($optionName, $value) { - if (!array_key_exists($optionName, $this->options)) { + if (!array_key_exists($optionName, $this->_options)) { return false; } - $this->options[$optionName] = $value; + $this->_options[$optionName] = $value; } /** @@ -807,7 +922,7 @@ class Net_URL2 */ function getOption($optionName) { - return isset($this->options[$optionName]) - ? $this->options[$optionName] : false; + return isset($this->_options[$optionName]) + ? $this->_options[$optionName] : false; } } diff --git a/install.php b/install.php index 6bfc4c2e2..d34e92dab 100644 --- a/install.php +++ b/install.php @@ -93,6 +93,13 @@ $external_libraries=array( 'include'=>'HTTP/Request.php', 'check_class'=>'HTTP_Request' ), + array( + 'name'=>'HTTP_Request2', + 'pear'=>'HTTP_Request2', + 'url'=>'http://pear.php.net/package/HTTP_Request2', + 'include'=>'HTTP/Request2.php', + 'check_class'=>'HTTP_Request2' + ), array( 'name'=>'Mail', 'pear'=>'Mail', diff --git a/lib/Shorturl_api.php b/lib/Shorturl_api.php index 18ae7719b..ef0d8dda4 100644 --- a/lib/Shorturl_api.php +++ b/lib/Shorturl_api.php @@ -41,22 +41,17 @@ abstract class ShortUrlApi return strlen($url) >= common_config('site', 'shorturllength'); } - protected function http_post($data) { - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $this->service_url); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch, CURLOPT_POST, 1); - curl_setopt($ch, CURLOPT_POSTFIELDS, $data); - $response = curl_exec($ch); - $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); - curl_close($ch); - if (($code < 200) || ($code >= 400)) return false; - return $response; + protected function http_post($data) + { + $request = new HTTPClient($this->service_url); + return $request->post($data); } - protected function http_get($url) { - $encoded_url = urlencode($url); - return file_get_contents("{$this->service_url}$encoded_url"); + protected function http_get($url) + { + $service = $this->service_url . urlencode($url); + $request = new HTTPClient($service); + return $request->get(); } protected function tidy($response) { diff --git a/lib/curlclient.php b/lib/curlclient.php deleted file mode 100644 index c307c2984..000000000 --- a/lib/curlclient.php +++ /dev/null @@ -1,179 +0,0 @@ -. - * - * @category HTTP - * @package StatusNet - * @author Evan Prodromou - * @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')) { - exit(1); -} - -define(CURLCLIENT_VERSION, "0.1"); - -/** - * Wrapper for Curl - * - * Makes Curl HTTP client calls within our HTTPClient framework - * - * @category HTTP - * @package StatusNet - * @author Evan Prodromou - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://status.net/ - */ - -class CurlClient extends HTTPClient -{ - function __construct() - { - } - - function head($url, $headers=null) - { - $ch = curl_init($url); - - $this->setup($ch); - - curl_setopt_array($ch, - array(CURLOPT_NOBODY => true)); - - if (!is_null($headers)) { - curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); - } - - $result = curl_exec($ch); - - curl_close($ch); - - return $this->parseResults($result); - } - - function get($url, $headers=null) - { - $ch = curl_init($url); - - $this->setup($ch); - - if (!is_null($headers)) { - curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); - } - - $result = curl_exec($ch); - - curl_close($ch); - - return $this->parseResults($result); - } - - function post($url, $headers=null, $body=null) - { - $ch = curl_init($url); - - $this->setup($ch); - - curl_setopt($ch, CURLOPT_POST, true); - - if (!is_null($body)) { - curl_setopt($ch, CURLOPT_POSTFIELDS, $body); - } - - if (!is_null($headers)) { - curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); - } - - $result = curl_exec($ch); - - curl_close($ch); - - return $this->parseResults($result); - } - - function setup($ch) - { - curl_setopt_array($ch, - array(CURLOPT_USERAGENT => $this->userAgent(), - CURLOPT_HEADER => true, - CURLOPT_RETURNTRANSFER => true)); - } - - function userAgent() - { - $version = curl_version(); - return parent::userAgent() . " CurlClient/".CURLCLIENT_VERSION . " cURL/" . $version['version']; - } - - function parseResults($results) - { - $resp = new HTTPResponse(); - - $lines = explode("\r\n", $results); - - if (preg_match("#^HTTP/1.[01] (\d\d\d) .+$#", $lines[0], $match)) { - $resp->code = $match[1]; - } else { - throw Exception("Bad format: initial line is not HTTP status line"); - } - - $lastk = null; - - for ($i = 1; $i < count($lines); $i++) { - $l =& $lines[$i]; - if (mb_strlen($l) == 0) { - $resp->body = implode("\r\n", array_slice($lines, $i + 1)); - break; - } - if (preg_match("#^(\S+):\s+(.*)$#", $l, $match)) { - $k = $match[1]; - $v = $match[2]; - - if (array_key_exists($k, $resp->headers)) { - if (is_array($resp->headers[$k])) { - $resp->headers[$k][] = $v; - } else { - $resp->headers[$k] = array($resp->headers[$k], $v); - } - } else { - $resp->headers[$k] = $v; - } - $lastk = $k; - } else if (preg_match("#^\s+(.*)$#", $l, $match)) { - // continuation line - if (is_null($lastk)) { - throw Exception("Bad format: initial whitespace in headers"); - } - $h =& $resp->headers[$lastk]; - if (is_array($h)) { - $n = count($h); - $h[$n-1] .= $match[1]; - } else { - $h .= $match[1]; - } - } - } - - return $resp; - } -} diff --git a/lib/default.php b/lib/default.php index 7ec8558b0..f6cc4b725 100644 --- a/lib/default.php +++ b/lib/default.php @@ -228,8 +228,6 @@ $default = array('contentlimit' => null), 'message' => array('contentlimit' => null), - 'http' => - array('client' => 'curl'), // XXX: should this be the default? 'location' => array('namespace' => 1), // 1 = geonames, 2 = Yahoo Where on Earth ); diff --git a/lib/httpclient.php b/lib/httpclient.php index f16e31e10..ee894e983 100644 --- a/lib/httpclient.php +++ b/lib/httpclient.php @@ -31,6 +31,9 @@ if (!defined('STATUSNET')) { exit(1); } +require_once 'HTTP/Request2.php'; +require_once 'HTTP/Request2/Response.php'; + /** * Useful structure for HTTP responses * @@ -38,18 +41,42 @@ if (!defined('STATUSNET')) { * ways of doing them. This class hides the specifics of what underlying * library (curl or PHP-HTTP or whatever) that's used. * + * This extends the HTTP_Request2_Response class with methods to get info + * about any followed redirects. + * * @category HTTP - * @package StatusNet - * @author Evan Prodromou - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://status.net/ + * @package StatusNet + * @author Evan Prodromou + * @author Brion Vibber + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ */ - -class HTTPResponse +class HTTPResponse extends HTTP_Request2_Response { - public $code = null; - public $headers = array(); - public $body = null; + function __construct(HTTP_Request2_Response $response, $url, $redirects=0) + { + foreach (get_object_vars($response) as $key => $val) { + $this->$key = $val; + } + $this->url = strval($url); + $this->redirectCount = intval($redirects); + } + + /** + * Get the count of redirects that have been followed, if any. + * @return int + */ + function getRedirectCount() { + return $this->redirectCount; + } + + /** + * Gets the final target URL, after any redirects have been followed. + * @return string URL + */ + function getUrl() { + return $this->url; + } } /** @@ -59,64 +86,133 @@ class HTTPResponse * ways of doing them. This class hides the specifics of what underlying * library (curl or PHP-HTTP or whatever) that's used. * + * This extends the PEAR HTTP_Request2 package: + * - sends StatusNet-specific User-Agent header + * - 'follow_redirects' config option, defaulting off + * - 'max_redirs' config option, defaulting to 10 + * - extended response class adds getRedirectCount() and getUrl() methods + * - get() and post() convenience functions return body content directly + * * @category HTTP * @package StatusNet * @author Evan Prodromou + * @author Brion Vibber * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ */ -class HTTPClient +class HTTPClient extends HTTP_Request2 { - static $_client = null; - static function start() + function __construct($url=null, $method=self::METHOD_GET, $config=array()) { - if (!is_null(self::$_client)) { - return self::$_client; - } - - $type = common_config('http', 'client'); - - switch ($type) { - case 'curl': - self::$_client = new CurlClient(); - break; - default: - throw new Exception("Unknown HTTP client type '$type'"); - break; - } - - return self::$_client; + $this->config['max_redirs'] = 10; + $this->config['follow_redirects'] = false; + parent::__construct($url, $method, $config); + $this->setHeader('User-Agent', $this->userAgent()); } - function head($url, $headers) + /** + * Convenience function to run a get request and return the response body. + * Use when you don't need to get into details of the response. + * + * @return mixed string on success, false on failure + */ + function get() { - throw new Exception("HEAD method unimplemented"); + $this->setMethod(self::METHOD_GET); + return $this->doRequest(); } - function get($url, $headers) + /** + * Convenience function to post form data and return the response body. + * Use when you don't need to get into details of the response. + * + * @param array associative array of form data to submit + * @return mixed string on success, false on failure + */ + public function post($data=array()) { - throw new Exception("GET method unimplemented"); + $this->setMethod(self::METHOD_POST); + if ($data) { + $this->addPostParameter($data); + } + return $this->doRequest(); } - function post($url, $headers, $body) + /** + * @return mixed string on success, false on failure + */ + protected function doRequest() { - throw new Exception("POST method unimplemented"); + try { + $response = $this->send(); + $code = $response->getStatus(); + if (($code < 200) || ($code >= 400)) { + return false; + } + return $response->getBody(); + } catch (HTTP_Request2_Exception $e) { + $this->log(LOG_ERR, $e->getMessage()); + return false; + } } - - function put($url, $headers, $body) - { - throw new Exception("PUT method unimplemented"); + + protected function log($level, $detail) { + $method = $this->getMethod(); + $url = $this->getUrl(); + common_log($level, __CLASS__ . ": HTTP $method $url - $detail"); } - function delete($url, $headers) + /** + * Pulls up StatusNet's customized user-agent string, so services + * we hit can track down the responsible software. + */ + function userAgent() { - throw new Exception("DELETE method unimplemented"); + return "StatusNet/".STATUSNET_VERSION." (".STATUSNET_CODENAME.")"; } - function userAgent() + function send() { - return "StatusNet/".STATUSNET_VERSION." (".STATUSNET_CODENAME.")"; + $maxRedirs = intval($this->config['max_redirs']); + if (empty($this->config['follow_redirects'])) { + $maxRedirs = 0; + } + $redirs = 0; + do { + try { + $response = parent::send(); + } catch (HTTP_Request2_Exception $e) { + $this->log(LOG_ERR, $e->getMessage()); + throw $e; + } + $code = $response->getStatus(); + if ($code >= 200 && $code < 300) { + $reason = $response->getReasonPhrase(); + $this->log(LOG_INFO, "$code $reason"); + } elseif ($code >= 300 && $code < 400) { + $url = $this->getUrl(); + $target = $response->getHeader('Location'); + + if (++$redirs >= $maxRedirs) { + common_log(LOG_ERR, __CLASS__ . ": Too many redirects: skipping $code redirect from $url to $target"); + break; + } + try { + $this->setUrl($target); + $this->setHeader('Referer', $url); + common_log(LOG_INFO, __CLASS__ . ": Following $code redirect from $url to $target"); + continue; + } catch (HTTP_Request2_Exception $e) { + common_log(LOG_ERR, __CLASS__ . ": Invalid $code redirect from $url to $target"); + } + } else { + $reason = $response->getReasonPhrase(); + $this->log(LOG_ERR, "$code $reason"); + } + break; + } while ($maxRedirs); + return new HTTPResponse($response, $this->getUrl(), $redirs); } } diff --git a/lib/oauthclient.php b/lib/oauthclient.php index f1827726e..1a86e2460 100644 --- a/lib/oauthclient.php +++ b/lib/oauthclient.php @@ -43,7 +43,7 @@ require_once 'OAuth.php'; * @link http://status.net/ * */ -class OAuthClientCurlException extends Exception +class OAuthClientException extends Exception { } @@ -97,9 +97,14 @@ class OAuthClient function getRequestToken($url) { $response = $this->oAuthGet($url); - parse_str($response); - $token = new OAuthToken($oauth_token, $oauth_token_secret); - return $token; + $arr = array(); + parse_str($response, $arr); + if (isset($arr['oauth_token']) && isset($arr['oauth_token_secret'])) { + $token = new OAuthToken($arr['oauth_token'], @$arr['oauth_token_secret']); + return $token; + } else { + throw new OAuthClientException(); + } } /** @@ -177,7 +182,7 @@ class OAuthClient } /** - * Make a HTTP request using cURL. + * Make a HTTP request. * * @param string $url Where to make the * @param array $params post parameters @@ -186,40 +191,32 @@ class OAuthClient */ function httpRequest($url, $params = null) { - $options = array( - CURLOPT_RETURNTRANSFER => true, - CURLOPT_FAILONERROR => true, - CURLOPT_HEADER => false, - CURLOPT_FOLLOWLOCATION => true, - CURLOPT_USERAGENT => 'StatusNet', - CURLOPT_CONNECTTIMEOUT => 120, - CURLOPT_TIMEOUT => 120, - CURLOPT_HTTPAUTH => CURLAUTH_ANY, - CURLOPT_SSL_VERIFYPEER => false, - - // Twitter is strict about accepting invalid "Expect" headers - - CURLOPT_HTTPHEADER => array('Expect:') - ); + $request = new HTTPClient($url); + $request->setConfig(array( + 'connect_timeout' => 120, + 'timeout' => 120, + 'follow_redirects' => true, + 'ssl_verify_peer' => false, + )); + + // Twitter is strict about accepting invalid "Expect" headers + $request->setHeader('Expect', ''); if (isset($params)) { - $options[CURLOPT_POST] = true; - $options[CURLOPT_POSTFIELDS] = $params; + $request->setMethod(HTTP_Request2::METHOD_POST); + $request->setBody($params); } - $ch = curl_init($url); - curl_setopt_array($ch, $options); - $response = curl_exec($ch); - - if ($response === false) { - $msg = curl_error($ch); - $code = curl_errno($ch); - throw new OAuthClientCurlException($msg, $code); + try { + $response = $request->send(); + $code = $response->getStatus(); + if ($code < 200 || $code >= 400) { + throw new OAuthClientException($response->getBody(), $code); + } + return $response->getBody(); + } catch (Exception $e) { + throw new OAuthClientException($e->getMessage(), $e->getCode()); } - - curl_close($ch); - - return $response; } } diff --git a/lib/ping.php b/lib/ping.php index 175bf8440..2797c1b2d 100644 --- a/lib/ping.php +++ b/lib/ping.php @@ -44,20 +44,18 @@ function ping_broadcast_notice($notice) { array('nickname' => $profile->nickname)), $tags)); - $context = stream_context_create(array('http' => array('method' => "POST", - 'header' => - "Content-Type: text/xml\r\n". - "User-Agent: StatusNet/".STATUSNET_VERSION."\r\n", - 'content' => $req))); - $file = file_get_contents($notify_url, false, $context); + $request = new HTTPClient($notify_url, HTTP_Request2::METHOD_POST); + $request->setHeader('Content-Type', 'text/xml'); + $request->setBody($req); + $httpResponse = $request->send(); - if ($file === false || mb_strlen($file) == 0) { + if (!$httpResponse || mb_strlen($httpResponse->getBody()) == 0) { common_log(LOG_WARNING, "XML-RPC empty results for ping ($notify_url, $notice->id) "); continue; } - $response = xmlrpc_decode($file); + $response = xmlrpc_decode($httpResponse->getBody()); if (is_array($response) && xmlrpc_is_fault($response)) { common_log(LOG_WARNING, diff --git a/lib/snapshot.php b/lib/snapshot.php index ede846e5b..6829e8a75 100644 --- a/lib/snapshot.php +++ b/lib/snapshot.php @@ -172,26 +172,11 @@ class Snapshot { // XXX: Use OICU2 and OAuth to make authorized requests - $postdata = http_build_query($this->stats); - - $opts = - array('http' => - array( - 'method' => 'POST', - 'header' => 'Content-type: '. - 'application/x-www-form-urlencoded', - 'content' => $postdata, - 'user_agent' => 'StatusNet/'.STATUSNET_VERSION - ) - ); - - $context = stream_context_create($opts); - $reporturl = common_config('snapshot', 'reporturl'); - $result = @file_get_contents($reporturl, false, $context); - - return $result; + $request = new HTTPClient($reporturl, HTTP_Request2::METHOD_POST); + $request->addPostParameter($this->stats); + $request->send(); } /** diff --git a/plugins/BlogspamNetPlugin.php b/plugins/BlogspamNetPlugin.php index c14569746..3bdc73556 100644 --- a/plugins/BlogspamNetPlugin.php +++ b/plugins/BlogspamNetPlugin.php @@ -22,6 +22,7 @@ * @category Plugin * @package StatusNet * @author Evan Prodromou + * @author Brion Vibber * @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/ @@ -69,14 +70,14 @@ class BlogspamNetPlugin extends Plugin { $args = $this->testArgs($notice); common_debug("Blogspamnet args = " . print_r($args, TRUE)); - $request = xmlrpc_encode_request('testComment', array($args)); - $context = stream_context_create(array('http' => array('method' => "POST", - 'header' => - "Content-Type: text/xml\r\n". - "User-Agent: " . $this->userAgent(), - 'content' => $request))); - $file = file_get_contents($this->baseUrl, false, $context); - $response = xmlrpc_decode($file); + $requestBody = xmlrpc_encode_request('testComment', array($args)); + + $request = new HTTPClient($this->baseUrl, HTTP_Request2::METHOD_POST); + $request->addHeader('Content-Type: text/xml'); + $request->setBody($requestBody); + $httpResponse = $request->send(); + + $response = xmlrpc_decode($httpResponse->getBody()); if (xmlrpc_is_fault($response)) { throw new ServerException("$response[faultString] ($response[faultCode])", 500); } else { diff --git a/plugins/LinkbackPlugin.php b/plugins/LinkbackPlugin.php index 60f7a60c7..0513687e9 100644 --- a/plugins/LinkbackPlugin.php +++ b/plugins/LinkbackPlugin.php @@ -129,27 +129,25 @@ class LinkbackPlugin extends Plugin } } - $request = xmlrpc_encode_request('pingback.ping', $args); - $context = stream_context_create(array('http' => array('method' => "POST", - 'header' => - "Content-Type: text/xml\r\n". - "User-Agent: " . $this->userAgent(), - 'content' => $request))); - $file = file_get_contents($endpoint, false, $context); - if (!$file) { + $request = new HTTPClient($endpoint, 'POST'); + $request->setHeader('User-Agent', $this->userAgent()); + $request->setHeader('Content-Type', 'text/xml'); + $request->setBody(xmlrpc_encode_request('pingback.ping', $args)); + try { + $response = $request->send(); + } catch (HTTP_Request2_Exception $e) { common_log(LOG_WARNING, - "Pingback request failed for '$url' ($endpoint)"); + "Pingback request failed for '$url' ($endpoint)"); + } + $response = xmlrpc_decode($response->getBody()); + if (xmlrpc_is_fault($response)) { + common_log(LOG_WARNING, + "Pingback error for '$url' ($endpoint): ". + "$response[faultString] ($response[faultCode])"); } else { - $response = xmlrpc_decode($file); - if (xmlrpc_is_fault($response)) { - common_log(LOG_WARNING, - "Pingback error for '$url' ($endpoint): ". - "$response[faultString] ($response[faultCode])"); - } else { - common_log(LOG_INFO, - "Pingback success for '$url' ($endpoint): ". - "'$response'"); - } + common_log(LOG_INFO, + "Pingback success for '$url' ($endpoint): ". + "'$response'"); } } diff --git a/plugins/SimpleUrl/SimpleUrlPlugin.php b/plugins/SimpleUrl/SimpleUrlPlugin.php index 82d772048..d59d63e47 100644 --- a/plugins/SimpleUrl/SimpleUrlPlugin.php +++ b/plugins/SimpleUrl/SimpleUrlPlugin.php @@ -65,15 +65,6 @@ class SimpleUrlPlugin extends Plugin class SimpleUrl extends ShortUrlApi { protected function shorten_imp($url) { - $curlh = curl_init(); - curl_setopt($curlh, CURLOPT_CONNECTTIMEOUT, 20); // # seconds to wait - curl_setopt($curlh, CURLOPT_USERAGENT, 'StatusNet'); - curl_setopt($curlh, CURLOPT_RETURNTRANSFER, true); - - curl_setopt($curlh, CURLOPT_URL, $this->service_url.urlencode($url)); - $short_url = curl_exec($curlh); - - curl_close($curlh); - return $short_url; + return $this->http_get($url); } } diff --git a/plugins/TwitterBridge/daemons/synctwitterfriends.php b/plugins/TwitterBridge/daemons/synctwitterfriends.php index ed2bf48a2..671e3c7af 100755 --- a/plugins/TwitterBridge/daemons/synctwitterfriends.php +++ b/plugins/TwitterBridge/daemons/synctwitterfriends.php @@ -152,8 +152,8 @@ class SyncTwitterFriendsDaemon extends ParallelizingDaemon $friends_ids = $client->friendsIds(); } catch (Exception $e) { common_log(LOG_WARNING, $this->name() . - ' - cURL error getting friend ids ' . - $e->getCode() . ' - ' . $e->getMessage()); + ' - error getting friend ids: ' . + $e->getMessage()); return $friends; } diff --git a/plugins/TwitterBridge/daemons/twitterstatusfetcher.php b/plugins/TwitterBridge/daemons/twitterstatusfetcher.php index 81bbbc7c5..6c91b2860 100755 --- a/plugins/TwitterBridge/daemons/twitterstatusfetcher.php +++ b/plugins/TwitterBridge/daemons/twitterstatusfetcher.php @@ -109,12 +109,16 @@ class TwitterStatusFetcher extends ParallelizingDaemon $flink->find(); $flinks = array(); + common_log(LOG_INFO, "hello"); while ($flink->fetch()) { if (($flink->noticesync & FOREIGN_NOTICE_RECV) == FOREIGN_NOTICE_RECV) { $flinks[] = clone($flink); + common_log(LOG_INFO, "sync: foreign id $flink->foreign_id"); + } else { + common_log(LOG_INFO, "nothing to sync"); } } @@ -515,31 +519,34 @@ class TwitterStatusFetcher extends ParallelizingDaemon return $id; } + /** + * Fetch a remote avatar image and save to local storage. + * + * @param string $url avatar source URL + * @param string $filename bare local filename for download + * @return bool true on success, false on failure + */ function fetchAvatar($url, $filename) { - $avatarfile = Avatar::path($filename); + common_debug($this->name() . " - Fetching Twitter avatar: $url"); - $out = fopen($avatarfile, 'wb'); - if (!$out) { - common_log(LOG_WARNING, $this->name() . - " - Couldn't open file $filename"); + $request = new HTTPClient($url, 'GET', array( + 'follow_redirects' => true, + )); + $data = $request->get(); + if ($data) { + $avatarfile = Avatar::path($filename); + $ok = file_put_contents($avatarfile, $data); + if (!$ok) { + common_log(LOG_WARNING, $this->name() . + " - Couldn't open file $filename"); + return false; + } + } else { return false; } - common_debug($this->name() . " - Fetching Twitter avatar: $url"); - - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_FILE, $out); - curl_setopt($ch, CURLOPT_BINARYTRANSFER, true); - curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); - curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0); - $result = curl_exec($ch); - curl_close($ch); - - fclose($out); - - return $result; + return true; } } diff --git a/plugins/TwitterBridge/twitter.php b/plugins/TwitterBridge/twitter.php index 1a5248a9b..3c6803e49 100644 --- a/plugins/TwitterBridge/twitter.php +++ b/plugins/TwitterBridge/twitter.php @@ -215,7 +215,7 @@ function broadcast_basicauth($notice, $flink) try { $status = $client->statusesUpdate($statustxt); - } catch (BasicAuthCurlException $e) { + } catch (HTTP_Request2_Exception $e) { return process_error($e, $flink); } diff --git a/plugins/TwitterBridge/twitterauthorization.php b/plugins/TwitterBridge/twitterauthorization.php index 2a93ff13e..f1daefab1 100644 --- a/plugins/TwitterBridge/twitterauthorization.php +++ b/plugins/TwitterBridge/twitterauthorization.php @@ -125,7 +125,7 @@ class TwitterauthorizationAction extends Action $auth_link = $client->getAuthorizeLink($req_tok); - } catch (TwitterOAuthClientException $e) { + } catch (OAuthClientException $e) { $msg = sprintf('OAuth client cURL error - code: %1s, msg: %2s', $e->getCode(), $e->getMessage()); $this->serverError(_('Couldn\'t link your Twitter account.')); diff --git a/plugins/TwitterBridge/twitterbasicauthclient.php b/plugins/TwitterBridge/twitterbasicauthclient.php index 1040d72fb..e4cae7373 100644 --- a/plugins/TwitterBridge/twitterbasicauthclient.php +++ b/plugins/TwitterBridge/twitterbasicauthclient.php @@ -31,26 +31,6 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } -/** - * Exception wrapper for cURL errors - * - * @category Integration - * @package StatusNet - * @author Adrian Lang - * @author Brenda Wallace - * @author Craig Andrews - * @author Dan Moore - * @author Evan Prodromou - * @author mEDI - * @author Sarven Capadisli - * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://status.net/ - * - */ -class BasicAuthCurlException extends Exception -{ -} - /** * Class for talking to the Twitter API with HTTP Basic Auth. * @@ -198,45 +178,27 @@ class TwitterBasicAuthClient */ function httpRequest($url, $params = null, $auth = true) { - $options = array( - CURLOPT_RETURNTRANSFER => true, - CURLOPT_FAILONERROR => true, - CURLOPT_HEADER => false, - CURLOPT_FOLLOWLOCATION => true, - CURLOPT_USERAGENT => 'StatusNet', - CURLOPT_CONNECTTIMEOUT => 120, - CURLOPT_TIMEOUT => 120, - CURLOPT_HTTPAUTH => CURLAUTH_ANY, - CURLOPT_SSL_VERIFYPEER => false, - - // Twitter is strict about accepting invalid "Expect" headers - - CURLOPT_HTTPHEADER => array('Expect:') - ); + $request = new HTTPClient($url, 'GET', array( + 'follow_redirects' => true, + 'connect_timeout' => 120, + 'timeout' => 120, + 'ssl_verifypeer' => false, + )); + + // Twitter is strict about accepting invalid "Expect" headers + $request->setHeader('Expect', ''); if (isset($params)) { - $options[CURLOPT_POST] = true; - $options[CURLOPT_POSTFIELDS] = $params; + $request->setMethod('POST'); + $request->addPostParameter($params); } if ($auth) { - $options[CURLOPT_USERPWD] = $this->screen_name . - ':' . $this->password; + $request->setAuth($this->screen_name, $this->password); } - $ch = curl_init($url); - curl_setopt_array($ch, $options); - $response = curl_exec($ch); - - if ($response === false) { - $msg = curl_error($ch); - $code = curl_errno($ch); - throw new BasicAuthCurlException($msg, $code); - } - - curl_close($ch); - - return $response; + $response = $request->send(); + return $response->getBody(); } } diff --git a/plugins/WikiHashtagsPlugin.php b/plugins/WikiHashtagsPlugin.php index 0c5649aa4..a9e675f5c 100644 --- a/plugins/WikiHashtagsPlugin.php +++ b/plugins/WikiHashtagsPlugin.php @@ -68,10 +68,8 @@ class WikiHashtagsPlugin extends Plugin $editurl = sprintf('http://hashtags.wikia.com/index.php?title=%s&action=edit', urlencode($tag)); - $context = stream_context_create(array('http' => array('method' => "GET", - 'header' => - "User-Agent: " . $this->userAgent()))); - $html = @file_get_contents($url, false, $context); + $request = new HTTPClient($url); + $html = $request->get(); $action->elementStart('div', array('id' => 'wikihashtags', 'class' => 'section')); @@ -100,10 +98,4 @@ class WikiHashtagsPlugin extends Plugin return true; } - - function userAgent() - { - return 'WikiHashtagsPlugin/'.WIKIHASHTAGSPLUGIN_VERSION . - ' StatusNet/' . STATUSNET_VERSION; - } } diff --git a/scripts/enjitqueuehandler.php b/scripts/enjitqueuehandler.php index 08f733b07..214cc02b4 100755 --- a/scripts/enjitqueuehandler.php +++ b/scripts/enjitqueuehandler.php @@ -46,8 +46,8 @@ class EnjitQueueHandler extends QueueHandler function start() { - $this->log(LOG_INFO, "Starting EnjitQueueHandler"); - $this->log(LOG_INFO, "Broadcasting to ".common_config('enjit', 'apiurl')); + $this->log(LOG_INFO, "Starting EnjitQueueHandler"); + $this->log(LOG_INFO, "Broadcasting to ".common_config('enjit', 'apiurl')); return true; } @@ -56,16 +56,16 @@ class EnjitQueueHandler extends QueueHandler $profile = Profile::staticGet($notice->profile_id); - $this->log(LOG_INFO, "Posting Notice ".$notice->id." from ".$profile->nickname); + $this->log(LOG_INFO, "Posting Notice ".$notice->id." from ".$profile->nickname); - if ( ! $notice->is_local ) { - $this->log(LOG_INFO, "Skipping remote notice"); - return "skipped"; - } + if ( ! $notice->is_local ) { + $this->log(LOG_INFO, "Skipping remote notice"); + return "skipped"; + } - # - # Build an Atom message from the notice - # + # + # Build an Atom message from the notice + # $noticeurl = common_local_url('shownotice', array('notice' => $notice->id)); $msg = $profile->nickname . ': ' . $notice->content; @@ -86,36 +86,20 @@ class EnjitQueueHandler extends QueueHandler $atom .= "".common_date_w3dtf($notice->modified)."\n"; $atom .= "\n"; - $url = common_config('enjit', 'apiurl') . "/submit/". common_config('enjit','apikey'); - $data = "msg=$atom"; - - # - # POST the message to $config['enjit']['apiurl'] - # - $ch = curl_init(); - - curl_setopt($ch, CURLOPT_URL, $url); - - curl_setopt($ch, CURLOPT_HEADER, 1); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch, CURLOPT_POST, 1) ; - curl_setopt($ch, CURLOPT_POSTFIELDS, $data); - - # SSL and Debugging options - # - # curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); - # curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); - # curl_setopt($ch, CURLOPT_VERBOSE, 1); - - $result = curl_exec($ch); - - $code = curl_getinfo($ch, CURLINFO_HTTP_CODE ); - - $this->log(LOG_INFO, "Response Code: $code"); - - curl_close($ch); - - return $code; + $url = common_config('enjit', 'apiurl') . "/submit/". common_config('enjit','apikey'); + $data = array( + 'msg' => $atom, + ); + + # + # POST the message to $config['enjit']['apiurl'] + # + $request = new HTTPClient($url, HTTP_Request2::METHOD_POST); + $request->addPostFields($data); + $response = $request->send(); + + // @fixme handle_notice() is supposed to return true/false. Somethin' funky? + return $response->getStatus(); } } -- cgit v1.2.3-54-g00ecf From b22fc5b74aecd505d4e2df01258171fc65d312cf Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Mon, 2 Nov 2009 06:56:31 -0800 Subject: Revert "Rebuilt HTTPClient class as an extension of PEAR HTTP_Request2 package, adding redirect handling and convenience functions." Going to restructure a little more before finalizing this... This reverts commit fa37967858c3c29000797e510e5f98aca8ab558f. --- classes/File_redirection.php | 68 +- extlib/HTTP/Request2.php | 844 ------------------ extlib/HTTP/Request2/Adapter.php | 152 ---- extlib/HTTP/Request2/Adapter/Curl.php | 383 -------- extlib/HTTP/Request2/Adapter/Mock.php | 171 ---- extlib/HTTP/Request2/Adapter/Socket.php | 971 --------------------- extlib/HTTP/Request2/Exception.php | 62 -- extlib/HTTP/Request2/MultipartBody.php | 274 ------ extlib/HTTP/Request2/Observer/Log.php | 215 ----- extlib/HTTP/Request2/Response.php | 549 ------------ extlib/Net/URL2.php | 471 ++++------ install.php | 7 - lib/Shorturl_api.php | 23 +- lib/curlclient.php | 179 ++++ lib/default.php | 2 + lib/httpclient.php | 180 +--- lib/oauthclient.php | 65 +- lib/ping.php | 14 +- lib/snapshot.php | 21 +- plugins/BlogspamNetPlugin.php | 17 +- plugins/LinkbackPlugin.php | 36 +- plugins/SimpleUrl/SimpleUrlPlugin.php | 11 +- .../TwitterBridge/daemons/synctwitterfriends.php | 4 +- .../TwitterBridge/daemons/twitterstatusfetcher.php | 45 +- plugins/TwitterBridge/twitter.php | 2 +- plugins/TwitterBridge/twitterauthorization.php | 2 +- plugins/TwitterBridge/twitterbasicauthclient.php | 66 +- plugins/WikiHashtagsPlugin.php | 12 +- scripts/enjitqueuehandler.php | 64 +- 29 files changed, 669 insertions(+), 4241 deletions(-) delete mode 100644 extlib/HTTP/Request2.php delete mode 100644 extlib/HTTP/Request2/Adapter.php delete mode 100644 extlib/HTTP/Request2/Adapter/Curl.php delete mode 100644 extlib/HTTP/Request2/Adapter/Mock.php delete mode 100644 extlib/HTTP/Request2/Adapter/Socket.php delete mode 100644 extlib/HTTP/Request2/Exception.php delete mode 100644 extlib/HTTP/Request2/MultipartBody.php delete mode 100644 extlib/HTTP/Request2/Observer/Log.php delete mode 100644 extlib/HTTP/Request2/Response.php create mode 100644 lib/curlclient.php (limited to 'plugins/TwitterBridge/daemons') diff --git a/classes/File_redirection.php b/classes/File_redirection.php index b7945699a..79052bf7d 100644 --- a/classes/File_redirection.php +++ b/classes/File_redirection.php @@ -47,15 +47,18 @@ class File_redirection extends Memcached_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE - static function _commonHttp($url, $redirs) { - $request = new HTTPClient($url); - $request->setConfig(array( - 'connect_timeout' => 10, // # seconds to wait - 'max_redirs' => $redirs, // # max number of http redirections to follow - 'follow_redirects' => true, // Follow redirects - 'store_body' => false, // We won't need body content here. - )); - return $request; + function _commonCurl($url, $redirs) { + $curlh = curl_init(); + curl_setopt($curlh, CURLOPT_URL, $url); + curl_setopt($curlh, CURLOPT_AUTOREFERER, true); // # setup referer header when folowing redirects + curl_setopt($curlh, CURLOPT_CONNECTTIMEOUT, 10); // # seconds to wait + curl_setopt($curlh, CURLOPT_MAXREDIRS, $redirs); // # max number of http redirections to follow + curl_setopt($curlh, CURLOPT_USERAGENT, USER_AGENT); + curl_setopt($curlh, CURLOPT_FOLLOWLOCATION, true); // Follow redirects + curl_setopt($curlh, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curlh, CURLOPT_FILETIME, true); + curl_setopt($curlh, CURLOPT_HEADER, true); // Include header in output + return $curlh; } function _redirectWhere_imp($short_url, $redirs = 10, $protected = false) { @@ -79,39 +82,32 @@ class File_redirection extends Memcached_DataObject if(strpos($short_url,'://') === false){ return $short_url; } - try { - $request = self::_commonHttp($short_url, $redirs); - // Don't include body in output - $request->setMethod(HTTP_Request2::METHOD_HEAD); - $response = $request->send(); - - if (405 == $response->getCode()) { - // Server doesn't support HEAD method? Can this really happen? - // We'll try again as a GET and ignore the response data. - $request = self::_commonHttp($short_url, $redirs); - $response = $request->send(); - } - } catch (Exception $e) { - // Invalid URL or failure to reach server - return $short_url; + $curlh = File_redirection::_commonCurl($short_url, $redirs); + // Don't include body in output + curl_setopt($curlh, CURLOPT_NOBODY, true); + curl_exec($curlh); + $info = curl_getinfo($curlh); + curl_close($curlh); + + if (405 == $info['http_code']) { + $curlh = File_redirection::_commonCurl($short_url, $redirs); + curl_exec($curlh); + $info = curl_getinfo($curlh); + curl_close($curlh); } - if ($response->getRedirectCount() && File::isProtected($response->getUrl())) { - // Bump back up the redirect chain until we find a non-protected URL - return self::_redirectWhere_imp($short_url, $response->getRedirectCount() - 1, true); + if (!empty($info['redirect_count']) && File::isProtected($info['url'])) { + return File_redirection::_redirectWhere_imp($short_url, $info['redirect_count'] - 1, true); } - $ret = array('code' => $response->getCode() - , 'redirects' => $response->getRedirectCount() - , 'url' => $response->getUrl()); + $ret = array('code' => $info['http_code'] + , 'redirects' => $info['redirect_count'] + , 'url' => $info['url']); - $type = $response->getHeader('Content-Type'); - if ($type) $ret['type'] = $type; + if (!empty($info['content_type'])) $ret['type'] = $info['content_type']; if ($protected) $ret['protected'] = true; - $size = $request->getHeader('Content-Length'); // @fixme bytes? - if ($size) $ret['size'] = $size; - $time = $request->getHeader('Last-Modified'); - if ($time) $ret['time'] = strtotime($time); + if (!empty($info['download_content_length'])) $ret['size'] = $info['download_content_length']; + if (isset($info['filetime']) && ($info['filetime'] > 0)) $ret['time'] = $info['filetime']; return $ret; } diff --git a/extlib/HTTP/Request2.php b/extlib/HTTP/Request2.php deleted file mode 100644 index e06bb86bc..000000000 --- a/extlib/HTTP/Request2.php +++ /dev/null @@ -1,844 +0,0 @@ - - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * The names of the authors may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * @category HTTP - * @package HTTP_Request2 - * @author Alexey Borzov - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version CVS: $Id: Request2.php 278226 2009-04-03 21:32:48Z avb $ - * @link http://pear.php.net/package/HTTP_Request2 - */ - -/** - * A class representing an URL as per RFC 3986. - */ -require_once 'Net/URL2.php'; - -/** - * Exception class for HTTP_Request2 package - */ -require_once 'HTTP/Request2/Exception.php'; - -/** - * Class representing a HTTP request - * - * @category HTTP - * @package HTTP_Request2 - * @author Alexey Borzov - * @version Release: 0.4.1 - * @link http://tools.ietf.org/html/rfc2616#section-5 - */ -class HTTP_Request2 implements SplSubject -{ - /**#@+ - * Constants for HTTP request methods - * - * @link http://tools.ietf.org/html/rfc2616#section-5.1.1 - */ - const METHOD_OPTIONS = 'OPTIONS'; - const METHOD_GET = 'GET'; - const METHOD_HEAD = 'HEAD'; - const METHOD_POST = 'POST'; - const METHOD_PUT = 'PUT'; - const METHOD_DELETE = 'DELETE'; - const METHOD_TRACE = 'TRACE'; - const METHOD_CONNECT = 'CONNECT'; - /**#@-*/ - - /**#@+ - * Constants for HTTP authentication schemes - * - * @link http://tools.ietf.org/html/rfc2617 - */ - const AUTH_BASIC = 'basic'; - const AUTH_DIGEST = 'digest'; - /**#@-*/ - - /** - * Regular expression used to check for invalid symbols in RFC 2616 tokens - * @link http://pear.php.net/bugs/bug.php?id=15630 - */ - const REGEXP_INVALID_TOKEN = '![\x00-\x1f\x7f-\xff()<>@,;:\\\\"/\[\]?={}\s]!'; - - /** - * Regular expression used to check for invalid symbols in cookie strings - * @link http://pear.php.net/bugs/bug.php?id=15630 - * @link http://cgi.netscape.com/newsref/std/cookie_spec.html - */ - const REGEXP_INVALID_COOKIE = '/[\s,;]/'; - - /** - * Fileinfo magic database resource - * @var resource - * @see detectMimeType() - */ - private static $_fileinfoDb; - - /** - * Observers attached to the request (instances of SplObserver) - * @var array - */ - protected $observers = array(); - - /** - * Request URL - * @var Net_URL2 - */ - protected $url; - - /** - * Request method - * @var string - */ - protected $method = self::METHOD_GET; - - /** - * Authentication data - * @var array - * @see getAuth() - */ - protected $auth; - - /** - * Request headers - * @var array - */ - protected $headers = array(); - - /** - * Configuration parameters - * @var array - * @see setConfig() - */ - protected $config = array( - 'adapter' => 'HTTP_Request2_Adapter_Socket', - 'connect_timeout' => 10, - 'timeout' => 0, - 'use_brackets' => true, - 'protocol_version' => '1.1', - 'buffer_size' => 16384, - 'store_body' => true, - - 'proxy_host' => '', - 'proxy_port' => '', - 'proxy_user' => '', - 'proxy_password' => '', - 'proxy_auth_scheme' => self::AUTH_BASIC, - - 'ssl_verify_peer' => true, - 'ssl_verify_host' => true, - 'ssl_cafile' => null, - 'ssl_capath' => null, - 'ssl_local_cert' => null, - 'ssl_passphrase' => null, - - 'digest_compat_ie' => false - ); - - /** - * Last event in request / response handling, intended for observers - * @var array - * @see getLastEvent() - */ - protected $lastEvent = array( - 'name' => 'start', - 'data' => null - ); - - /** - * Request body - * @var string|resource - * @see setBody() - */ - protected $body = ''; - - /** - * Array of POST parameters - * @var array - */ - protected $postParams = array(); - - /** - * Array of file uploads (for multipart/form-data POST requests) - * @var array - */ - protected $uploads = array(); - - /** - * Adapter used to perform actual HTTP request - * @var HTTP_Request2_Adapter - */ - protected $adapter; - - - /** - * Constructor. Can set request URL, method and configuration array. - * - * Also sets a default value for User-Agent header. - * - * @param string|Net_Url2 Request URL - * @param string Request method - * @param array Configuration for this Request instance - */ - public function __construct($url = null, $method = self::METHOD_GET, array $config = array()) - { - if (!empty($url)) { - $this->setUrl($url); - } - if (!empty($method)) { - $this->setMethod($method); - } - $this->setConfig($config); - $this->setHeader('user-agent', 'HTTP_Request2/0.4.1 ' . - '(http://pear.php.net/package/http_request2) ' . - 'PHP/' . phpversion()); - } - - /** - * Sets the URL for this request - * - * If the URL has userinfo part (username & password) these will be removed - * and converted to auth data. If the URL does not have a path component, - * that will be set to '/'. - * - * @param string|Net_URL2 Request URL - * @return HTTP_Request2 - * @throws HTTP_Request2_Exception - */ - public function setUrl($url) - { - if (is_string($url)) { - $url = new Net_URL2($url); - } - if (!$url instanceof Net_URL2) { - throw new HTTP_Request2_Exception('Parameter is not a valid HTTP URL'); - } - // URL contains username / password? - if ($url->getUserinfo()) { - $username = $url->getUser(); - $password = $url->getPassword(); - $this->setAuth(rawurldecode($username), $password? rawurldecode($password): ''); - $url->setUserinfo(''); - } - if ('' == $url->getPath()) { - $url->setPath('/'); - } - $this->url = $url; - - return $this; - } - - /** - * Returns the request URL - * - * @return Net_URL2 - */ - public function getUrl() - { - return $this->url; - } - - /** - * Sets the request method - * - * @param string - * @return HTTP_Request2 - * @throws HTTP_Request2_Exception if the method name is invalid - */ - public function setMethod($method) - { - // Method name should be a token: http://tools.ietf.org/html/rfc2616#section-5.1.1 - if (preg_match(self::REGEXP_INVALID_TOKEN, $method)) { - throw new HTTP_Request2_Exception("Invalid request method '{$method}'"); - } - $this->method = $method; - - return $this; - } - - /** - * Returns the request method - * - * @return string - */ - public function getMethod() - { - return $this->method; - } - - /** - * Sets the configuration parameter(s) - * - * The following parameters are available: - *
    - *
  • 'adapter' - adapter to use (string)
  • - *
  • 'connect_timeout' - Connection timeout in seconds (integer)
  • - *
  • 'timeout' - Total number of seconds a request can take. - * Use 0 for no limit, should be greater than - * 'connect_timeout' if set (integer)
  • - *
  • 'use_brackets' - Whether to append [] to array variable names (bool)
  • - *
  • 'protocol_version' - HTTP Version to use, '1.0' or '1.1' (string)
  • - *
  • 'buffer_size' - Buffer size to use for reading and writing (int)
  • - *
  • 'store_body' - Whether to store response body in response object. - * Set to false if receiving a huge response and - * using an Observer to save it (boolean)
  • - *
  • 'proxy_host' - Proxy server host (string)
  • - *
  • 'proxy_port' - Proxy server port (integer)
  • - *
  • 'proxy_user' - Proxy auth username (string)
  • - *
  • 'proxy_password' - Proxy auth password (string)
  • - *
  • 'proxy_auth_scheme' - Proxy auth scheme, one of HTTP_Request2::AUTH_* constants (string)
  • - *
  • 'ssl_verify_peer' - Whether to verify peer's SSL certificate (bool)
  • - *
  • 'ssl_verify_host' - Whether to check that Common Name in SSL - * certificate matches host name (bool)
  • - *
  • 'ssl_cafile' - Cerificate Authority file to verify the peer - * with (use with 'ssl_verify_peer') (string)
  • - *
  • 'ssl_capath' - Directory holding multiple Certificate - * Authority files (string)
  • - *
  • 'ssl_local_cert' - Name of a file containing local cerificate (string)
  • - *
  • 'ssl_passphrase' - Passphrase with which local certificate - * was encoded (string)
  • - *
  • 'digest_compat_ie' - Whether to imitate behaviour of MSIE 5 and 6 - * in using URL without query string in digest - * authentication (boolean)
  • - *
- * - * @param string|array configuration parameter name or array - * ('parameter name' => 'parameter value') - * @param mixed parameter value if $nameOrConfig is not an array - * @return HTTP_Request2 - * @throws HTTP_Request2_Exception If the parameter is unknown - */ - public function setConfig($nameOrConfig, $value = null) - { - if (is_array($nameOrConfig)) { - foreach ($nameOrConfig as $name => $value) { - $this->setConfig($name, $value); - } - - } else { - if (!array_key_exists($nameOrConfig, $this->config)) { - throw new HTTP_Request2_Exception( - "Unknown configuration parameter '{$nameOrConfig}'" - ); - } - $this->config[$nameOrConfig] = $value; - } - - return $this; - } - - /** - * Returns the value(s) of the configuration parameter(s) - * - * @param string parameter name - * @return mixed value of $name parameter, array of all configuration - * parameters if $name is not given - * @throws HTTP_Request2_Exception If the parameter is unknown - */ - public function getConfig($name = null) - { - if (null === $name) { - return $this->config; - } elseif (!array_key_exists($name, $this->config)) { - throw new HTTP_Request2_Exception( - "Unknown configuration parameter '{$name}'" - ); - } - return $this->config[$name]; - } - - /** - * Sets the autentification data - * - * @param string user name - * @param string password - * @param string authentication scheme - * @return HTTP_Request2 - */ - public function setAuth($user, $password = '', $scheme = self::AUTH_BASIC) - { - if (empty($user)) { - $this->auth = null; - } else { - $this->auth = array( - 'user' => (string)$user, - 'password' => (string)$password, - 'scheme' => $scheme - ); - } - - return $this; - } - - /** - * Returns the authentication data - * - * The array has the keys 'user', 'password' and 'scheme', where 'scheme' - * is one of the HTTP_Request2::AUTH_* constants. - * - * @return array - */ - public function getAuth() - { - return $this->auth; - } - - /** - * Sets request header(s) - * - * The first parameter may be either a full header string 'header: value' or - * header name. In the former case $value parameter is ignored, in the latter - * the header's value will either be set to $value or the header will be - * removed if $value is null. The first parameter can also be an array of - * headers, in that case method will be called recursively. - * - * Note that headers are treated case insensitively as per RFC 2616. - * - * - * $req->setHeader('Foo: Bar'); // sets the value of 'Foo' header to 'Bar' - * $req->setHeader('FoO', 'Baz'); // sets the value of 'Foo' header to 'Baz' - * $req->setHeader(array('foo' => 'Quux')); // sets the value of 'Foo' header to 'Quux' - * $req->setHeader('FOO'); // removes 'Foo' header from request - * - * - * @param string|array header name, header string ('Header: value') - * or an array of headers - * @param string|null header value, header will be removed if null - * @return HTTP_Request2 - * @throws HTTP_Request2_Exception - */ - public function setHeader($name, $value = null) - { - if (is_array($name)) { - foreach ($name as $k => $v) { - if (is_string($k)) { - $this->setHeader($k, $v); - } else { - $this->setHeader($v); - } - } - } else { - if (null === $value && strpos($name, ':')) { - list($name, $value) = array_map('trim', explode(':', $name, 2)); - } - // Header name should be a token: http://tools.ietf.org/html/rfc2616#section-4.2 - if (preg_match(self::REGEXP_INVALID_TOKEN, $name)) { - throw new HTTP_Request2_Exception("Invalid header name '{$name}'"); - } - // Header names are case insensitive anyway - $name = strtolower($name); - if (null === $value) { - unset($this->headers[$name]); - } else { - $this->headers[$name] = $value; - } - } - - return $this; - } - - /** - * Returns the request headers - * - * The array is of the form ('header name' => 'header value'), header names - * are lowercased - * - * @return array - */ - public function getHeaders() - { - return $this->headers; - } - - /** - * Appends a cookie to "Cookie:" header - * - * @param string cookie name - * @param string cookie value - * @return HTTP_Request2 - * @throws HTTP_Request2_Exception - */ - public function addCookie($name, $value) - { - $cookie = $name . '=' . $value; - if (preg_match(self::REGEXP_INVALID_COOKIE, $cookie)) { - throw new HTTP_Request2_Exception("Invalid cookie: '{$cookie}'"); - } - $cookies = empty($this->headers['cookie'])? '': $this->headers['cookie'] . '; '; - $this->setHeader('cookie', $cookies . $cookie); - - return $this; - } - - /** - * Sets the request body - * - * @param string Either a string with the body or filename containing body - * @param bool Whether first parameter is a filename - * @return HTTP_Request2 - * @throws HTTP_Request2_Exception - */ - public function setBody($body, $isFilename = false) - { - if (!$isFilename) { - $this->body = (string)$body; - } else { - if (!($fp = @fopen($body, 'rb'))) { - throw new HTTP_Request2_Exception("Cannot open file {$body}"); - } - $this->body = $fp; - if (empty($this->headers['content-type'])) { - $this->setHeader('content-type', self::detectMimeType($body)); - } - } - - return $this; - } - - /** - * Returns the request body - * - * @return string|resource|HTTP_Request2_MultipartBody - */ - public function getBody() - { - if (self::METHOD_POST == $this->method && - (!empty($this->postParams) || !empty($this->uploads)) - ) { - if ('application/x-www-form-urlencoded' == $this->headers['content-type']) { - $body = http_build_query($this->postParams, '', '&'); - if (!$this->getConfig('use_brackets')) { - $body = preg_replace('/%5B\d+%5D=/', '=', $body); - } - // support RFC 3986 by not encoding '~' symbol (request #15368) - return str_replace('%7E', '~', $body); - - } elseif ('multipart/form-data' == $this->headers['content-type']) { - require_once 'HTTP/Request2/MultipartBody.php'; - return new HTTP_Request2_MultipartBody( - $this->postParams, $this->uploads, $this->getConfig('use_brackets') - ); - } - } - return $this->body; - } - - /** - * Adds a file to form-based file upload - * - * Used to emulate file upload via a HTML form. The method also sets - * Content-Type of HTTP request to 'multipart/form-data'. - * - * If you just want to send the contents of a file as the body of HTTP - * request you should use setBody() method. - * - * @param string name of file-upload field - * @param mixed full name of local file - * @param string filename to send in the request - * @param string content-type of file being uploaded - * @return HTTP_Request2 - * @throws HTTP_Request2_Exception - */ - public function addUpload($fieldName, $filename, $sendFilename = null, - $contentType = null) - { - if (!is_array($filename)) { - if (!($fp = @fopen($filename, 'rb'))) { - throw new HTTP_Request2_Exception("Cannot open file {$filename}"); - } - $this->uploads[$fieldName] = array( - 'fp' => $fp, - 'filename' => empty($sendFilename)? basename($filename): $sendFilename, - 'size' => filesize($filename), - 'type' => empty($contentType)? self::detectMimeType($filename): $contentType - ); - } else { - $fps = $names = $sizes = $types = array(); - foreach ($filename as $f) { - if (!is_array($f)) { - $f = array($f); - } - if (!($fp = @fopen($f[0], 'rb'))) { - throw new HTTP_Request2_Exception("Cannot open file {$f[0]}"); - } - $fps[] = $fp; - $names[] = empty($f[1])? basename($f[0]): $f[1]; - $sizes[] = filesize($f[0]); - $types[] = empty($f[2])? self::detectMimeType($f[0]): $f[2]; - } - $this->uploads[$fieldName] = array( - 'fp' => $fps, 'filename' => $names, 'size' => $sizes, 'type' => $types - ); - } - if (empty($this->headers['content-type']) || - 'application/x-www-form-urlencoded' == $this->headers['content-type'] - ) { - $this->setHeader('content-type', 'multipart/form-data'); - } - - return $this; - } - - /** - * Adds POST parameter(s) to the request. - * - * @param string|array parameter name or array ('name' => 'value') - * @param mixed parameter value (can be an array) - * @return HTTP_Request2 - */ - public function addPostParameter($name, $value = null) - { - if (!is_array($name)) { - $this->postParams[$name] = $value; - } else { - foreach ($name as $k => $v) { - $this->addPostParameter($k, $v); - } - } - if (empty($this->headers['content-type'])) { - $this->setHeader('content-type', 'application/x-www-form-urlencoded'); - } - - return $this; - } - - /** - * Attaches a new observer - * - * @param SplObserver - */ - public function attach(SplObserver $observer) - { - foreach ($this->observers as $attached) { - if ($attached === $observer) { - return; - } - } - $this->observers[] = $observer; - } - - /** - * Detaches an existing observer - * - * @param SplObserver - */ - public function detach(SplObserver $observer) - { - foreach ($this->observers as $key => $attached) { - if ($attached === $observer) { - unset($this->observers[$key]); - return; - } - } - } - - /** - * Notifies all observers - */ - public function notify() - { - foreach ($this->observers as $observer) { - $observer->update($this); - } - } - - /** - * Sets the last event - * - * Adapters should use this method to set the current state of the request - * and notify the observers. - * - * @param string event name - * @param mixed event data - */ - public function setLastEvent($name, $data = null) - { - $this->lastEvent = array( - 'name' => $name, - 'data' => $data - ); - $this->notify(); - } - - /** - * Returns the last event - * - * Observers should use this method to access the last change in request. - * The following event names are possible: - *
    - *
  • 'connect' - after connection to remote server, - * data is the destination (string)
  • - *
  • 'disconnect' - after disconnection from server
  • - *
  • 'sentHeaders' - after sending the request headers, - * data is the headers sent (string)
  • - *
  • 'sentBodyPart' - after sending a part of the request body, - * data is the length of that part (int)
  • - *
  • 'receivedHeaders' - after receiving the response headers, - * data is HTTP_Request2_Response object
  • - *
  • 'receivedBodyPart' - after receiving a part of the response - * body, data is that part (string)
  • - *
  • 'receivedEncodedBodyPart' - as 'receivedBodyPart', but data is still - * encoded by Content-Encoding
  • - *
  • 'receivedBody' - after receiving the complete response - * body, data is HTTP_Request2_Response object
  • - *
- * Different adapters may not send all the event types. Mock adapter does - * not send any events to the observers. - * - * @return array The array has two keys: 'name' and 'data' - */ - public function getLastEvent() - { - return $this->lastEvent; - } - - /** - * Sets the adapter used to actually perform the request - * - * You can pass either an instance of a class implementing HTTP_Request2_Adapter - * or a class name. The method will only try to include a file if the class - * name starts with HTTP_Request2_Adapter_, it will also try to prepend this - * prefix to the class name if it doesn't contain any underscores, so that - * - * $request->setAdapter('curl'); - * - * will work. - * - * @param string|HTTP_Request2_Adapter - * @return HTTP_Request2 - * @throws HTTP_Request2_Exception - */ - public function setAdapter($adapter) - { - if (is_string($adapter)) { - if (!class_exists($adapter, false)) { - if (false === strpos($adapter, '_')) { - $adapter = 'HTTP_Request2_Adapter_' . ucfirst($adapter); - } - if (preg_match('/^HTTP_Request2_Adapter_([a-zA-Z0-9]+)$/', $adapter)) { - include_once str_replace('_', DIRECTORY_SEPARATOR, $adapter) . '.php'; - } - if (!class_exists($adapter, false)) { - throw new HTTP_Request2_Exception("Class {$adapter} not found"); - } - } - $adapter = new $adapter; - } - if (!$adapter instanceof HTTP_Request2_Adapter) { - throw new HTTP_Request2_Exception('Parameter is not a HTTP request adapter'); - } - $this->adapter = $adapter; - - return $this; - } - - /** - * Sends the request and returns the response - * - * @throws HTTP_Request2_Exception - * @return HTTP_Request2_Response - */ - public function send() - { - // Sanity check for URL - if (!$this->url instanceof Net_URL2) { - throw new HTTP_Request2_Exception('No URL given'); - } elseif (!$this->url->isAbsolute()) { - throw new HTTP_Request2_Exception('Absolute URL required'); - } elseif (!in_array(strtolower($this->url->getScheme()), array('https', 'http'))) { - throw new HTTP_Request2_Exception('Not a HTTP URL'); - } - if (empty($this->adapter)) { - $this->setAdapter($this->getConfig('adapter')); - } - // magic_quotes_runtime may break file uploads and chunked response - // processing; see bug #4543 - if ($magicQuotes = ini_get('magic_quotes_runtime')) { - ini_set('magic_quotes_runtime', false); - } - // force using single byte encoding if mbstring extension overloads - // strlen() and substr(); see bug #1781, bug #10605 - if (extension_loaded('mbstring') && (2 & ini_get('mbstring.func_overload'))) { - $oldEncoding = mb_internal_encoding(); - mb_internal_encoding('iso-8859-1'); - } - - try { - $response = $this->adapter->sendRequest($this); - } catch (Exception $e) { - } - // cleanup in either case (poor man's "finally" clause) - if ($magicQuotes) { - ini_set('magic_quotes_runtime', true); - } - if (!empty($oldEncoding)) { - mb_internal_encoding($oldEncoding); - } - // rethrow the exception - if (!empty($e)) { - throw $e; - } - return $response; - } - - /** - * Tries to detect MIME type of a file - * - * The method will try to use fileinfo extension if it is available, - * deprecated mime_content_type() function in the other case. If neither - * works, default 'application/octet-stream' MIME type is returned - * - * @param string filename - * @return string file MIME type - */ - protected static function detectMimeType($filename) - { - // finfo extension from PECL available - if (function_exists('finfo_open')) { - if (!isset(self::$_fileinfoDb)) { - self::$_fileinfoDb = @finfo_open(FILEINFO_MIME); - } - if (self::$_fileinfoDb) { - $info = finfo_file(self::$_fileinfoDb, $filename); - } - } - // (deprecated) mime_content_type function available - if (empty($info) && function_exists('mime_content_type')) { - return mime_content_type($filename); - } - return empty($info)? 'application/octet-stream': $info; - } -} -?> \ No newline at end of file diff --git a/extlib/HTTP/Request2/Adapter.php b/extlib/HTTP/Request2/Adapter.php deleted file mode 100644 index 39b092b34..000000000 --- a/extlib/HTTP/Request2/Adapter.php +++ /dev/null @@ -1,152 +0,0 @@ - - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * The names of the authors may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * @category HTTP - * @package HTTP_Request2 - * @author Alexey Borzov - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version CVS: $Id: Adapter.php 274684 2009-01-26 23:07:27Z avb $ - * @link http://pear.php.net/package/HTTP_Request2 - */ - -/** - * Class representing a HTTP response - */ -require_once 'HTTP/Request2/Response.php'; - -/** - * Base class for HTTP_Request2 adapters - * - * HTTP_Request2 class itself only defines methods for aggregating the request - * data, all actual work of sending the request to the remote server and - * receiving its response is performed by adapters. - * - * @category HTTP - * @package HTTP_Request2 - * @author Alexey Borzov - * @version Release: 0.4.1 - */ -abstract class HTTP_Request2_Adapter -{ - /** - * A list of methods that MUST NOT have a request body, per RFC 2616 - * @var array - */ - protected static $bodyDisallowed = array('TRACE'); - - /** - * Methods having defined semantics for request body - * - * Content-Length header (indicating that the body follows, section 4.3 of - * RFC 2616) will be sent for these methods even if no body was added - * - * @var array - * @link http://pear.php.net/bugs/bug.php?id=12900 - * @link http://pear.php.net/bugs/bug.php?id=14740 - */ - protected static $bodyRequired = array('POST', 'PUT'); - - /** - * Request being sent - * @var HTTP_Request2 - */ - protected $request; - - /** - * Request body - * @var string|resource|HTTP_Request2_MultipartBody - * @see HTTP_Request2::getBody() - */ - protected $requestBody; - - /** - * Length of the request body - * @var integer - */ - protected $contentLength; - - /** - * Sends request to the remote server and returns its response - * - * @param HTTP_Request2 - * @return HTTP_Request2_Response - * @throws HTTP_Request2_Exception - */ - abstract public function sendRequest(HTTP_Request2 $request); - - /** - * Calculates length of the request body, adds proper headers - * - * @param array associative array of request headers, this method will - * add proper 'Content-Length' and 'Content-Type' headers - * to this array (or remove them if not needed) - */ - protected function calculateRequestLength(&$headers) - { - $this->requestBody = $this->request->getBody(); - - if (is_string($this->requestBody)) { - $this->contentLength = strlen($this->requestBody); - } elseif (is_resource($this->requestBody)) { - $stat = fstat($this->requestBody); - $this->contentLength = $stat['size']; - rewind($this->requestBody); - } else { - $this->contentLength = $this->requestBody->getLength(); - $headers['content-type'] = 'multipart/form-data; boundary=' . - $this->requestBody->getBoundary(); - $this->requestBody->rewind(); - } - - if (in_array($this->request->getMethod(), self::$bodyDisallowed) || - 0 == $this->contentLength - ) { - unset($headers['content-type']); - // No body: send a Content-Length header nonetheless (request #12900), - // but do that only for methods that require a body (bug #14740) - if (in_array($this->request->getMethod(), self::$bodyRequired)) { - $headers['content-length'] = 0; - } else { - unset($headers['content-length']); - } - } else { - if (empty($headers['content-type'])) { - $headers['content-type'] = 'application/x-www-form-urlencoded'; - } - $headers['content-length'] = $this->contentLength; - } - } -} -?> diff --git a/extlib/HTTP/Request2/Adapter/Curl.php b/extlib/HTTP/Request2/Adapter/Curl.php deleted file mode 100644 index 4d4de0dcc..000000000 --- a/extlib/HTTP/Request2/Adapter/Curl.php +++ /dev/null @@ -1,383 +0,0 @@ - - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * The names of the authors may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * @category HTTP - * @package HTTP_Request2 - * @author Alexey Borzov - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version CVS: $Id: Curl.php 278226 2009-04-03 21:32:48Z avb $ - * @link http://pear.php.net/package/HTTP_Request2 - */ - -/** - * Base class for HTTP_Request2 adapters - */ -require_once 'HTTP/Request2/Adapter.php'; - -/** - * Adapter for HTTP_Request2 wrapping around cURL extension - * - * @category HTTP - * @package HTTP_Request2 - * @author Alexey Borzov - * @version Release: 0.4.1 - */ -class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter -{ - /** - * Mapping of header names to cURL options - * @var array - */ - protected static $headerMap = array( - 'accept-encoding' => CURLOPT_ENCODING, - 'cookie' => CURLOPT_COOKIE, - 'referer' => CURLOPT_REFERER, - 'user-agent' => CURLOPT_USERAGENT - ); - - /** - * Mapping of SSL context options to cURL options - * @var array - */ - protected static $sslContextMap = array( - 'ssl_verify_peer' => CURLOPT_SSL_VERIFYPEER, - 'ssl_cafile' => CURLOPT_CAINFO, - 'ssl_capath' => CURLOPT_CAPATH, - 'ssl_local_cert' => CURLOPT_SSLCERT, - 'ssl_passphrase' => CURLOPT_SSLCERTPASSWD - ); - - /** - * Response being received - * @var HTTP_Request2_Response - */ - protected $response; - - /** - * Whether 'sentHeaders' event was sent to observers - * @var boolean - */ - protected $eventSentHeaders = false; - - /** - * Whether 'receivedHeaders' event was sent to observers - * @var boolean - */ - protected $eventReceivedHeaders = false; - - /** - * Position within request body - * @var integer - * @see callbackReadBody() - */ - protected $position = 0; - - /** - * Information about last transfer, as returned by curl_getinfo() - * @var array - */ - protected $lastInfo; - - /** - * Sends request to the remote server and returns its response - * - * @param HTTP_Request2 - * @return HTTP_Request2_Response - * @throws HTTP_Request2_Exception - */ - public function sendRequest(HTTP_Request2 $request) - { - if (!extension_loaded('curl')) { - throw new HTTP_Request2_Exception('cURL extension not available'); - } - - $this->request = $request; - $this->response = null; - $this->position = 0; - $this->eventSentHeaders = false; - $this->eventReceivedHeaders = false; - - try { - if (false === curl_exec($ch = $this->createCurlHandle())) { - $errorMessage = 'Error sending request: #' . curl_errno($ch) . - ' ' . curl_error($ch); - } - } catch (Exception $e) { - } - $this->lastInfo = curl_getinfo($ch); - curl_close($ch); - - if (!empty($e)) { - throw $e; - } elseif (!empty($errorMessage)) { - throw new HTTP_Request2_Exception($errorMessage); - } - - if (0 < $this->lastInfo['size_download']) { - $this->request->setLastEvent('receivedBody', $this->response); - } - return $this->response; - } - - /** - * Returns information about last transfer - * - * @return array associative array as returned by curl_getinfo() - */ - public function getInfo() - { - return $this->lastInfo; - } - - /** - * Creates a new cURL handle and populates it with data from the request - * - * @return resource a cURL handle, as created by curl_init() - * @throws HTTP_Request2_Exception - */ - protected function createCurlHandle() - { - $ch = curl_init(); - - curl_setopt_array($ch, array( - // setup callbacks - CURLOPT_READFUNCTION => array($this, 'callbackReadBody'), - CURLOPT_HEADERFUNCTION => array($this, 'callbackWriteHeader'), - CURLOPT_WRITEFUNCTION => array($this, 'callbackWriteBody'), - // disallow redirects - CURLOPT_FOLLOWLOCATION => false, - // buffer size - CURLOPT_BUFFERSIZE => $this->request->getConfig('buffer_size'), - // connection timeout - CURLOPT_CONNECTTIMEOUT => $this->request->getConfig('connect_timeout'), - // save full outgoing headers, in case someone is interested - CURLINFO_HEADER_OUT => true, - // request url - CURLOPT_URL => $this->request->getUrl()->getUrl() - )); - - // request timeout - if ($timeout = $this->request->getConfig('timeout')) { - curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); - } - - // set HTTP version - switch ($this->request->getConfig('protocol_version')) { - case '1.0': - curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); - break; - case '1.1': - curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); - } - - // set request method - switch ($this->request->getMethod()) { - case HTTP_Request2::METHOD_GET: - curl_setopt($ch, CURLOPT_HTTPGET, true); - break; - case HTTP_Request2::METHOD_POST: - curl_setopt($ch, CURLOPT_POST, true); - break; - default: - curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $this->request->getMethod()); - } - - // set proxy, if needed - if ($host = $this->request->getConfig('proxy_host')) { - if (!($port = $this->request->getConfig('proxy_port'))) { - throw new HTTP_Request2_Exception('Proxy port not provided'); - } - curl_setopt($ch, CURLOPT_PROXY, $host . ':' . $port); - if ($user = $this->request->getConfig('proxy_user')) { - curl_setopt($ch, CURLOPT_PROXYUSERPWD, $user . ':' . - $this->request->getConfig('proxy_password')); - switch ($this->request->getConfig('proxy_auth_scheme')) { - case HTTP_Request2::AUTH_BASIC: - curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC); - break; - case HTTP_Request2::AUTH_DIGEST: - curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_DIGEST); - } - } - } - - // set authentication data - if ($auth = $this->request->getAuth()) { - curl_setopt($ch, CURLOPT_USERPWD, $auth['user'] . ':' . $auth['password']); - switch ($auth['scheme']) { - case HTTP_Request2::AUTH_BASIC: - curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); - break; - case HTTP_Request2::AUTH_DIGEST: - curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST); - } - } - - // set SSL options - if (0 == strcasecmp($this->request->getUrl()->getScheme(), 'https')) { - foreach ($this->request->getConfig() as $name => $value) { - if ('ssl_verify_host' == $name && null !== $value) { - curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $value? 2: 0); - } elseif (isset(self::$sslContextMap[$name]) && null !== $value) { - curl_setopt($ch, self::$sslContextMap[$name], $value); - } - } - } - - $headers = $this->request->getHeaders(); - // make cURL automagically send proper header - if (!isset($headers['accept-encoding'])) { - $headers['accept-encoding'] = ''; - } - - // set headers having special cURL keys - foreach (self::$headerMap as $name => $option) { - if (isset($headers[$name])) { - curl_setopt($ch, $option, $headers[$name]); - unset($headers[$name]); - } - } - - $this->calculateRequestLength($headers); - - // set headers not having special keys - $headersFmt = array(); - foreach ($headers as $name => $value) { - $canonicalName = implode('-', array_map('ucfirst', explode('-', $name))); - $headersFmt[] = $canonicalName . ': ' . $value; - } - curl_setopt($ch, CURLOPT_HTTPHEADER, $headersFmt); - - return $ch; - } - - /** - * Callback function called by cURL for reading the request body - * - * @param resource cURL handle - * @param resource file descriptor (not used) - * @param integer maximum length of data to return - * @return string part of the request body, up to $length bytes - */ - protected function callbackReadBody($ch, $fd, $length) - { - if (!$this->eventSentHeaders) { - $this->request->setLastEvent( - 'sentHeaders', curl_getinfo($ch, CURLINFO_HEADER_OUT) - ); - $this->eventSentHeaders = true; - } - if (in_array($this->request->getMethod(), self::$bodyDisallowed) || - 0 == $this->contentLength || $this->position >= $this->contentLength - ) { - return ''; - } - if (is_string($this->requestBody)) { - $string = substr($this->requestBody, $this->position, $length); - } elseif (is_resource($this->requestBody)) { - $string = fread($this->requestBody, $length); - } else { - $string = $this->requestBody->read($length); - } - $this->request->setLastEvent('sentBodyPart', strlen($string)); - $this->position += strlen($string); - return $string; - } - - /** - * Callback function called by cURL for saving the response headers - * - * @param resource cURL handle - * @param string response header (with trailing CRLF) - * @return integer number of bytes saved - * @see HTTP_Request2_Response::parseHeaderLine() - */ - protected function callbackWriteHeader($ch, $string) - { - // we may receive a second set of headers if doing e.g. digest auth - if ($this->eventReceivedHeaders || !$this->eventSentHeaders) { - // don't bother with 100-Continue responses (bug #15785) - if (!$this->eventSentHeaders || - $this->response->getStatus() >= 200 - ) { - $this->request->setLastEvent( - 'sentHeaders', curl_getinfo($ch, CURLINFO_HEADER_OUT) - ); - } - $this->eventSentHeaders = true; - // we'll need a new response object - if ($this->eventReceivedHeaders) { - $this->eventReceivedHeaders = false; - $this->response = null; - } - } - if (empty($this->response)) { - $this->response = new HTTP_Request2_Response($string, false); - } else { - $this->response->parseHeaderLine($string); - if ('' == trim($string)) { - // don't bother with 100-Continue responses (bug #15785) - if (200 <= $this->response->getStatus()) { - $this->request->setLastEvent('receivedHeaders', $this->response); - } - $this->eventReceivedHeaders = true; - } - } - return strlen($string); - } - - /** - * Callback function called by cURL for saving the response body - * - * @param resource cURL handle (not used) - * @param string part of the response body - * @return integer number of bytes saved - * @see HTTP_Request2_Response::appendBody() - */ - protected function callbackWriteBody($ch, $string) - { - // cURL calls WRITEFUNCTION callback without calling HEADERFUNCTION if - // response doesn't start with proper HTTP status line (see bug #15716) - if (empty($this->response)) { - throw new HTTP_Request2_Exception("Malformed response: {$string}"); - } - if ($this->request->getConfig('store_body')) { - $this->response->appendBody($string); - } - $this->request->setLastEvent('receivedBodyPart', $string); - return strlen($string); - } -} -?> diff --git a/extlib/HTTP/Request2/Adapter/Mock.php b/extlib/HTTP/Request2/Adapter/Mock.php deleted file mode 100644 index 89688003b..000000000 --- a/extlib/HTTP/Request2/Adapter/Mock.php +++ /dev/null @@ -1,171 +0,0 @@ - - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * The names of the authors may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * @category HTTP - * @package HTTP_Request2 - * @author Alexey Borzov - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version CVS: $Id: Mock.php 274406 2009-01-23 18:01:57Z avb $ - * @link http://pear.php.net/package/HTTP_Request2 - */ - -/** - * Base class for HTTP_Request2 adapters - */ -require_once 'HTTP/Request2/Adapter.php'; - -/** - * Mock adapter intended for testing - * - * Can be used to test applications depending on HTTP_Request2 package without - * actually performing any HTTP requests. This adapter will return responses - * previously added via addResponse() - * - * $mock = new HTTP_Request2_Adapter_Mock(); - * $mock->addResponse("HTTP/1.1 ... "); - * - * $request = new HTTP_Request2(); - * $request->setAdapter($mock); - * - * // This will return the response set above - * $response = $req->send(); - * - * - * @category HTTP - * @package HTTP_Request2 - * @author Alexey Borzov - * @version Release: 0.4.1 - */ -class HTTP_Request2_Adapter_Mock extends HTTP_Request2_Adapter -{ - /** - * A queue of responses to be returned by sendRequest() - * @var array - */ - protected $responses = array(); - - /** - * Returns the next response from the queue built by addResponse() - * - * If the queue is empty will return default empty response with status 400, - * if an Exception object was added to the queue it will be thrown. - * - * @param HTTP_Request2 - * @return HTTP_Request2_Response - * @throws Exception - */ - public function sendRequest(HTTP_Request2 $request) - { - if (count($this->responses) > 0) { - $response = array_shift($this->responses); - if ($response instanceof HTTP_Request2_Response) { - return $response; - } else { - // rethrow the exception, - $class = get_class($response); - $message = $response->getMessage(); - $code = $response->getCode(); - throw new $class($message, $code); - } - } else { - return self::createResponseFromString("HTTP/1.1 400 Bad Request\r\n\r\n"); - } - } - - /** - * Adds response to the queue - * - * @param mixed either a string, a pointer to an open file, - * a HTTP_Request2_Response or Exception object - * @throws HTTP_Request2_Exception - */ - public function addResponse($response) - { - if (is_string($response)) { - $response = self::createResponseFromString($response); - } elseif (is_resource($response)) { - $response = self::createResponseFromFile($response); - } elseif (!$response instanceof HTTP_Request2_Response && - !$response instanceof Exception - ) { - throw new HTTP_Request2_Exception('Parameter is not a valid response'); - } - $this->responses[] = $response; - } - - /** - * Creates a new HTTP_Request2_Response object from a string - * - * @param string - * @return HTTP_Request2_Response - * @throws HTTP_Request2_Exception - */ - public static function createResponseFromString($str) - { - $parts = preg_split('!(\r?\n){2}!m', $str, 2); - $headerLines = explode("\n", $parts[0]); - $response = new HTTP_Request2_Response(array_shift($headerLines)); - foreach ($headerLines as $headerLine) { - $response->parseHeaderLine($headerLine); - } - $response->parseHeaderLine(''); - if (isset($parts[1])) { - $response->appendBody($parts[1]); - } - return $response; - } - - /** - * Creates a new HTTP_Request2_Response object from a file - * - * @param resource file pointer returned by fopen() - * @return HTTP_Request2_Response - * @throws HTTP_Request2_Exception - */ - public static function createResponseFromFile($fp) - { - $response = new HTTP_Request2_Response(fgets($fp)); - do { - $headerLine = fgets($fp); - $response->parseHeaderLine($headerLine); - } while ('' != trim($headerLine)); - - while (!feof($fp)) { - $response->appendBody(fread($fp, 8192)); - } - return $response; - } -} -?> \ No newline at end of file diff --git a/extlib/HTTP/Request2/Adapter/Socket.php b/extlib/HTTP/Request2/Adapter/Socket.php deleted file mode 100644 index ff44d4959..000000000 --- a/extlib/HTTP/Request2/Adapter/Socket.php +++ /dev/null @@ -1,971 +0,0 @@ - - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * The names of the authors may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * @category HTTP - * @package HTTP_Request2 - * @author Alexey Borzov - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version CVS: $Id: Socket.php 279760 2009-05-03 10:46:42Z avb $ - * @link http://pear.php.net/package/HTTP_Request2 - */ - -/** - * Base class for HTTP_Request2 adapters - */ -require_once 'HTTP/Request2/Adapter.php'; - -/** - * Socket-based adapter for HTTP_Request2 - * - * This adapter uses only PHP sockets and will work on almost any PHP - * environment. Code is based on original HTTP_Request PEAR package. - * - * @category HTTP - * @package HTTP_Request2 - * @author Alexey Borzov - * @version Release: 0.4.1 - */ -class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter -{ - /** - * Regular expression for 'token' rule from RFC 2616 - */ - const REGEXP_TOKEN = '[^\x00-\x1f\x7f-\xff()<>@,;:\\\\"/\[\]?={}\s]+'; - - /** - * Regular expression for 'quoted-string' rule from RFC 2616 - */ - const REGEXP_QUOTED_STRING = '"(?:\\\\.|[^\\\\"])*"'; - - /** - * Connected sockets, needed for Keep-Alive support - * @var array - * @see connect() - */ - protected static $sockets = array(); - - /** - * Data for digest authentication scheme - * - * The keys for the array are URL prefixes. - * - * The values are associative arrays with data (realm, nonce, nonce-count, - * opaque...) needed for digest authentication. Stored here to prevent making - * duplicate requests to digest-protected resources after we have already - * received the challenge. - * - * @var array - */ - protected static $challenges = array(); - - /** - * Connected socket - * @var resource - * @see connect() - */ - protected $socket; - - /** - * Challenge used for server digest authentication - * @var array - */ - protected $serverChallenge; - - /** - * Challenge used for proxy digest authentication - * @var array - */ - protected $proxyChallenge; - - /** - * Global timeout, exception will be raised if request continues past this time - * @var integer - */ - protected $timeout = null; - - /** - * Remaining length of the current chunk, when reading chunked response - * @var integer - * @see readChunked() - */ - protected $chunkLength = 0; - - /** - * Sends request to the remote server and returns its response - * - * @param HTTP_Request2 - * @return HTTP_Request2_Response - * @throws HTTP_Request2_Exception - */ - public function sendRequest(HTTP_Request2 $request) - { - $this->request = $request; - $keepAlive = $this->connect(); - $headers = $this->prepareHeaders(); - - // Use global request timeout if given, see feature requests #5735, #8964 - if ($timeout = $request->getConfig('timeout')) { - $this->timeout = time() + $timeout; - } else { - $this->timeout = null; - } - - try { - if (false === @fwrite($this->socket, $headers, strlen($headers))) { - throw new HTTP_Request2_Exception('Error writing request'); - } - // provide request headers to the observer, see request #7633 - $this->request->setLastEvent('sentHeaders', $headers); - $this->writeBody(); - - if ($this->timeout && time() > $this->timeout) { - throw new HTTP_Request2_Exception( - 'Request timed out after ' . - $request->getConfig('timeout') . ' second(s)' - ); - } - - $response = $this->readResponse(); - - if (!$this->canKeepAlive($keepAlive, $response)) { - $this->disconnect(); - } - - if ($this->shouldUseProxyDigestAuth($response)) { - return $this->sendRequest($request); - } - if ($this->shouldUseServerDigestAuth($response)) { - return $this->sendRequest($request); - } - if ($authInfo = $response->getHeader('authentication-info')) { - $this->updateChallenge($this->serverChallenge, $authInfo); - } - if ($proxyInfo = $response->getHeader('proxy-authentication-info')) { - $this->updateChallenge($this->proxyChallenge, $proxyInfo); - } - - } catch (Exception $e) { - $this->disconnect(); - throw $e; - } - - return $response; - } - - /** - * Connects to the remote server - * - * @return bool whether the connection can be persistent - * @throws HTTP_Request2_Exception - */ - protected function connect() - { - $secure = 0 == strcasecmp($this->request->getUrl()->getScheme(), 'https'); - $tunnel = HTTP_Request2::METHOD_CONNECT == $this->request->getMethod(); - $headers = $this->request->getHeaders(); - $reqHost = $this->request->getUrl()->getHost(); - if (!($reqPort = $this->request->getUrl()->getPort())) { - $reqPort = $secure? 443: 80; - } - - if ($host = $this->request->getConfig('proxy_host')) { - if (!($port = $this->request->getConfig('proxy_port'))) { - throw new HTTP_Request2_Exception('Proxy port not provided'); - } - $proxy = true; - } else { - $host = $reqHost; - $port = $reqPort; - $proxy = false; - } - - if ($tunnel && !$proxy) { - throw new HTTP_Request2_Exception( - "Trying to perform CONNECT request without proxy" - ); - } - if ($secure && !in_array('ssl', stream_get_transports())) { - throw new HTTP_Request2_Exception( - 'Need OpenSSL support for https:// requests' - ); - } - - // RFC 2068, section 19.7.1: A client MUST NOT send the Keep-Alive - // connection token to a proxy server... - if ($proxy && !$secure && - !empty($headers['connection']) && 'Keep-Alive' == $headers['connection'] - ) { - $this->request->setHeader('connection'); - } - - $keepAlive = ('1.1' == $this->request->getConfig('protocol_version') && - empty($headers['connection'])) || - (!empty($headers['connection']) && - 'Keep-Alive' == $headers['connection']); - $host = ((!$secure || $proxy)? 'tcp://': 'ssl://') . $host; - - $options = array(); - if ($secure || $tunnel) { - foreach ($this->request->getConfig() as $name => $value) { - if ('ssl_' == substr($name, 0, 4) && null !== $value) { - if ('ssl_verify_host' == $name) { - if ($value) { - $options['CN_match'] = $reqHost; - } - } else { - $options[substr($name, 4)] = $value; - } - } - } - ksort($options); - } - - // Changing SSL context options after connection is established does *not* - // work, we need a new connection if options change - $remote = $host . ':' . $port; - $socketKey = $remote . (($secure && $proxy)? "->{$reqHost}:{$reqPort}": '') . - (empty($options)? '': ':' . serialize($options)); - unset($this->socket); - - // We use persistent connections and have a connected socket? - // Ensure that the socket is still connected, see bug #16149 - if ($keepAlive && !empty(self::$sockets[$socketKey]) && - !feof(self::$sockets[$socketKey]) - ) { - $this->socket =& self::$sockets[$socketKey]; - - } elseif ($secure && $proxy && !$tunnel) { - $this->establishTunnel(); - $this->request->setLastEvent( - 'connect', "ssl://{$reqHost}:{$reqPort} via {$host}:{$port}" - ); - self::$sockets[$socketKey] =& $this->socket; - - } else { - // Set SSL context options if doing HTTPS request or creating a tunnel - $context = stream_context_create(); - foreach ($options as $name => $value) { - if (!stream_context_set_option($context, 'ssl', $name, $value)) { - throw new HTTP_Request2_Exception( - "Error setting SSL context option '{$name}'" - ); - } - } - $this->socket = @stream_socket_client( - $remote, $errno, $errstr, - $this->request->getConfig('connect_timeout'), - STREAM_CLIENT_CONNECT, $context - ); - if (!$this->socket) { - throw new HTTP_Request2_Exception( - "Unable to connect to {$remote}. Error #{$errno}: {$errstr}" - ); - } - $this->request->setLastEvent('connect', $remote); - self::$sockets[$socketKey] =& $this->socket; - } - return $keepAlive; - } - - /** - * Establishes a tunnel to a secure remote server via HTTP CONNECT request - * - * This method will fail if 'ssl_verify_peer' is enabled. Probably because PHP - * sees that we are connected to a proxy server (duh!) rather than the server - * that presents its certificate. - * - * @link http://tools.ietf.org/html/rfc2817#section-5.2 - * @throws HTTP_Request2_Exception - */ - protected function establishTunnel() - { - $donor = new self; - $connect = new HTTP_Request2( - $this->request->getUrl(), HTTP_Request2::METHOD_CONNECT, - array_merge($this->request->getConfig(), - array('adapter' => $donor)) - ); - $response = $connect->send(); - // Need any successful (2XX) response - if (200 > $response->getStatus() || 300 <= $response->getStatus()) { - throw new HTTP_Request2_Exception( - 'Failed to connect via HTTPS proxy. Proxy response: ' . - $response->getStatus() . ' ' . $response->getReasonPhrase() - ); - } - $this->socket = $donor->socket; - - $modes = array( - STREAM_CRYPTO_METHOD_TLS_CLIENT, - STREAM_CRYPTO_METHOD_SSLv3_CLIENT, - STREAM_CRYPTO_METHOD_SSLv23_CLIENT, - STREAM_CRYPTO_METHOD_SSLv2_CLIENT - ); - - foreach ($modes as $mode) { - if (stream_socket_enable_crypto($this->socket, true, $mode)) { - return; - } - } - throw new HTTP_Request2_Exception( - 'Failed to enable secure connection when connecting through proxy' - ); - } - - /** - * Checks whether current connection may be reused or should be closed - * - * @param boolean whether connection could be persistent - * in the first place - * @param HTTP_Request2_Response response object to check - * @return boolean - */ - protected function canKeepAlive($requestKeepAlive, HTTP_Request2_Response $response) - { - // Do not close socket on successful CONNECT request - if (HTTP_Request2::METHOD_CONNECT == $this->request->getMethod() && - 200 <= $response->getStatus() && 300 > $response->getStatus() - ) { - return true; - } - - $lengthKnown = 'chunked' == strtolower($response->getHeader('transfer-encoding')) || - null !== $response->getHeader('content-length'); - $persistent = 'keep-alive' == strtolower($response->getHeader('connection')) || - (null === $response->getHeader('connection') && - '1.1' == $response->getVersion()); - return $requestKeepAlive && $lengthKnown && $persistent; - } - - /** - * Disconnects from the remote server - */ - protected function disconnect() - { - if (is_resource($this->socket)) { - fclose($this->socket); - $this->socket = null; - $this->request->setLastEvent('disconnect'); - } - } - - /** - * Checks whether another request should be performed with server digest auth - * - * Several conditions should be satisfied for it to return true: - * - response status should be 401 - * - auth credentials should be set in the request object - * - response should contain WWW-Authenticate header with digest challenge - * - there is either no challenge stored for this URL or new challenge - * contains stale=true parameter (in other case we probably just failed - * due to invalid username / password) - * - * The method stores challenge values in $challenges static property - * - * @param HTTP_Request2_Response response to check - * @return boolean whether another request should be performed - * @throws HTTP_Request2_Exception in case of unsupported challenge parameters - */ - protected function shouldUseServerDigestAuth(HTTP_Request2_Response $response) - { - // no sense repeating a request if we don't have credentials - if (401 != $response->getStatus() || !$this->request->getAuth()) { - return false; - } - if (!$challenge = $this->parseDigestChallenge($response->getHeader('www-authenticate'))) { - return false; - } - - $url = $this->request->getUrl(); - $scheme = $url->getScheme(); - $host = $scheme . '://' . $url->getHost(); - if ($port = $url->getPort()) { - if ((0 == strcasecmp($scheme, 'http') && 80 != $port) || - (0 == strcasecmp($scheme, 'https') && 443 != $port) - ) { - $host .= ':' . $port; - } - } - - if (!empty($challenge['domain'])) { - $prefixes = array(); - foreach (preg_split('/\\s+/', $challenge['domain']) as $prefix) { - // don't bother with different servers - if ('/' == substr($prefix, 0, 1)) { - $prefixes[] = $host . $prefix; - } - } - } - if (empty($prefixes)) { - $prefixes = array($host . '/'); - } - - $ret = true; - foreach ($prefixes as $prefix) { - if (!empty(self::$challenges[$prefix]) && - (empty($challenge['stale']) || strcasecmp('true', $challenge['stale'])) - ) { - // probably credentials are invalid - $ret = false; - } - self::$challenges[$prefix] =& $challenge; - } - return $ret; - } - - /** - * Checks whether another request should be performed with proxy digest auth - * - * Several conditions should be satisfied for it to return true: - * - response status should be 407 - * - proxy auth credentials should be set in the request object - * - response should contain Proxy-Authenticate header with digest challenge - * - there is either no challenge stored for this proxy or new challenge - * contains stale=true parameter (in other case we probably just failed - * due to invalid username / password) - * - * The method stores challenge values in $challenges static property - * - * @param HTTP_Request2_Response response to check - * @return boolean whether another request should be performed - * @throws HTTP_Request2_Exception in case of unsupported challenge parameters - */ - protected function shouldUseProxyDigestAuth(HTTP_Request2_Response $response) - { - if (407 != $response->getStatus() || !$this->request->getConfig('proxy_user')) { - return false; - } - if (!($challenge = $this->parseDigestChallenge($response->getHeader('proxy-authenticate')))) { - return false; - } - - $key = 'proxy://' . $this->request->getConfig('proxy_host') . - ':' . $this->request->getConfig('proxy_port'); - - if (!empty(self::$challenges[$key]) && - (empty($challenge['stale']) || strcasecmp('true', $challenge['stale'])) - ) { - $ret = false; - } else { - $ret = true; - } - self::$challenges[$key] = $challenge; - return $ret; - } - - /** - * Extracts digest method challenge from (WWW|Proxy)-Authenticate header value - * - * There is a problem with implementation of RFC 2617: several of the parameters - * here are defined as quoted-string and thus may contain backslash escaped - * double quotes (RFC 2616, section 2.2). However, RFC 2617 defines unq(X) as - * just value of quoted-string X without surrounding quotes, it doesn't speak - * about removing backslash escaping. - * - * Now realm parameter is user-defined and human-readable, strange things - * happen when it contains quotes: - * - Apache allows quotes in realm, but apparently uses realm value without - * backslashes for digest computation - * - Squid allows (manually escaped) quotes there, but it is impossible to - * authorize with either escaped or unescaped quotes used in digest, - * probably it can't parse the response (?) - * - Both IE and Firefox display realm value with backslashes in - * the password popup and apparently use the same value for digest - * - * HTTP_Request2 follows IE and Firefox (and hopefully RFC 2617) in - * quoted-string handling, unfortunately that means failure to authorize - * sometimes - * - * @param string value of WWW-Authenticate or Proxy-Authenticate header - * @return mixed associative array with challenge parameters, false if - * no challenge is present in header value - * @throws HTTP_Request2_Exception in case of unsupported challenge parameters - */ - protected function parseDigestChallenge($headerValue) - { - $authParam = '(' . self::REGEXP_TOKEN . ')\\s*=\\s*(' . - self::REGEXP_TOKEN . '|' . self::REGEXP_QUOTED_STRING . ')'; - $challenge = "!(?<=^|\\s|,)Digest ({$authParam}\\s*(,\\s*|$))+!"; - if (!preg_match($challenge, $headerValue, $matches)) { - return false; - } - - preg_match_all('!' . $authParam . '!', $matches[0], $params); - $paramsAry = array(); - $knownParams = array('realm', 'domain', 'nonce', 'opaque', 'stale', - 'algorithm', 'qop'); - for ($i = 0; $i < count($params[0]); $i++) { - // section 3.2.1: Any unrecognized directive MUST be ignored. - if (in_array($params[1][$i], $knownParams)) { - if ('"' == substr($params[2][$i], 0, 1)) { - $paramsAry[$params[1][$i]] = substr($params[2][$i], 1, -1); - } else { - $paramsAry[$params[1][$i]] = $params[2][$i]; - } - } - } - // we only support qop=auth - if (!empty($paramsAry['qop']) && - !in_array('auth', array_map('trim', explode(',', $paramsAry['qop']))) - ) { - throw new HTTP_Request2_Exception( - "Only 'auth' qop is currently supported in digest authentication, " . - "server requested '{$paramsAry['qop']}'" - ); - } - // we only support algorithm=MD5 - if (!empty($paramsAry['algorithm']) && 'MD5' != $paramsAry['algorithm']) { - throw new HTTP_Request2_Exception( - "Only 'MD5' algorithm is currently supported in digest authentication, " . - "server requested '{$paramsAry['algorithm']}'" - ); - } - - return $paramsAry; - } - - /** - * Parses [Proxy-]Authentication-Info header value and updates challenge - * - * @param array challenge to update - * @param string value of [Proxy-]Authentication-Info header - * @todo validate server rspauth response - */ - protected function updateChallenge(&$challenge, $headerValue) - { - $authParam = '!(' . self::REGEXP_TOKEN . ')\\s*=\\s*(' . - self::REGEXP_TOKEN . '|' . self::REGEXP_QUOTED_STRING . ')!'; - $paramsAry = array(); - - preg_match_all($authParam, $headerValue, $params); - for ($i = 0; $i < count($params[0]); $i++) { - if ('"' == substr($params[2][$i], 0, 1)) { - $paramsAry[$params[1][$i]] = substr($params[2][$i], 1, -1); - } else { - $paramsAry[$params[1][$i]] = $params[2][$i]; - } - } - // for now, just update the nonce value - if (!empty($paramsAry['nextnonce'])) { - $challenge['nonce'] = $paramsAry['nextnonce']; - $challenge['nc'] = 1; - } - } - - /** - * Creates a value for [Proxy-]Authorization header when using digest authentication - * - * @param string user name - * @param string password - * @param string request URL - * @param array digest challenge parameters - * @return string value of [Proxy-]Authorization request header - * @link http://tools.ietf.org/html/rfc2617#section-3.2.2 - */ - protected function createDigestResponse($user, $password, $url, &$challenge) - { - if (false !== ($q = strpos($url, '?')) && - $this->request->getConfig('digest_compat_ie') - ) { - $url = substr($url, 0, $q); - } - - $a1 = md5($user . ':' . $challenge['realm'] . ':' . $password); - $a2 = md5($this->request->getMethod() . ':' . $url); - - if (empty($challenge['qop'])) { - $digest = md5($a1 . ':' . $challenge['nonce'] . ':' . $a2); - } else { - $challenge['cnonce'] = 'Req2.' . rand(); - if (empty($challenge['nc'])) { - $challenge['nc'] = 1; - } - $nc = sprintf('%08x', $challenge['nc']++); - $digest = md5($a1 . ':' . $challenge['nonce'] . ':' . $nc . ':' . - $challenge['cnonce'] . ':auth:' . $a2); - } - return 'Digest username="' . str_replace(array('\\', '"'), array('\\\\', '\\"'), $user) . '", ' . - 'realm="' . $challenge['realm'] . '", ' . - 'nonce="' . $challenge['nonce'] . '", ' . - 'uri="' . $url . '", ' . - 'response="' . $digest . '"' . - (!empty($challenge['opaque'])? - ', opaque="' . $challenge['opaque'] . '"': - '') . - (!empty($challenge['qop'])? - ', qop="auth", nc=' . $nc . ', cnonce="' . $challenge['cnonce'] . '"': - ''); - } - - /** - * Adds 'Authorization' header (if needed) to request headers array - * - * @param array request headers - * @param string request host (needed for digest authentication) - * @param string request URL (needed for digest authentication) - * @throws HTTP_Request2_Exception - */ - protected function addAuthorizationHeader(&$headers, $requestHost, $requestUrl) - { - if (!($auth = $this->request->getAuth())) { - return; - } - switch ($auth['scheme']) { - case HTTP_Request2::AUTH_BASIC: - $headers['authorization'] = - 'Basic ' . base64_encode($auth['user'] . ':' . $auth['password']); - break; - - case HTTP_Request2::AUTH_DIGEST: - unset($this->serverChallenge); - $fullUrl = ('/' == $requestUrl[0])? - $this->request->getUrl()->getScheme() . '://' . - $requestHost . $requestUrl: - $requestUrl; - foreach (array_keys(self::$challenges) as $key) { - if ($key == substr($fullUrl, 0, strlen($key))) { - $headers['authorization'] = $this->createDigestResponse( - $auth['user'], $auth['password'], - $requestUrl, self::$challenges[$key] - ); - $this->serverChallenge =& self::$challenges[$key]; - break; - } - } - break; - - default: - throw new HTTP_Request2_Exception( - "Unknown HTTP authentication scheme '{$auth['scheme']}'" - ); - } - } - - /** - * Adds 'Proxy-Authorization' header (if needed) to request headers array - * - * @param array request headers - * @param string request URL (needed for digest authentication) - * @throws HTTP_Request2_Exception - */ - protected function addProxyAuthorizationHeader(&$headers, $requestUrl) - { - if (!$this->request->getConfig('proxy_host') || - !($user = $this->request->getConfig('proxy_user')) || - (0 == strcasecmp('https', $this->request->getUrl()->getScheme()) && - HTTP_Request2::METHOD_CONNECT != $this->request->getMethod()) - ) { - return; - } - - $password = $this->request->getConfig('proxy_password'); - switch ($this->request->getConfig('proxy_auth_scheme')) { - case HTTP_Request2::AUTH_BASIC: - $headers['proxy-authorization'] = - 'Basic ' . base64_encode($user . ':' . $password); - break; - - case HTTP_Request2::AUTH_DIGEST: - unset($this->proxyChallenge); - $proxyUrl = 'proxy://' . $this->request->getConfig('proxy_host') . - ':' . $this->request->getConfig('proxy_port'); - if (!empty(self::$challenges[$proxyUrl])) { - $headers['proxy-authorization'] = $this->createDigestResponse( - $user, $password, - $requestUrl, self::$challenges[$proxyUrl] - ); - $this->proxyChallenge =& self::$challenges[$proxyUrl]; - } - break; - - default: - throw new HTTP_Request2_Exception( - "Unknown HTTP authentication scheme '" . - $this->request->getConfig('proxy_auth_scheme') . "'" - ); - } - } - - - /** - * Creates the string with the Request-Line and request headers - * - * @return string - * @throws HTTP_Request2_Exception - */ - protected function prepareHeaders() - { - $headers = $this->request->getHeaders(); - $url = $this->request->getUrl(); - $connect = HTTP_Request2::METHOD_CONNECT == $this->request->getMethod(); - $host = $url->getHost(); - - $defaultPort = 0 == strcasecmp($url->getScheme(), 'https')? 443: 80; - if (($port = $url->getPort()) && $port != $defaultPort || $connect) { - $host .= ':' . (empty($port)? $defaultPort: $port); - } - // Do not overwrite explicitly set 'Host' header, see bug #16146 - if (!isset($headers['host'])) { - $headers['host'] = $host; - } - - if ($connect) { - $requestUrl = $host; - - } else { - if (!$this->request->getConfig('proxy_host') || - 0 == strcasecmp($url->getScheme(), 'https') - ) { - $requestUrl = ''; - } else { - $requestUrl = $url->getScheme() . '://' . $host; - } - $path = $url->getPath(); - $query = $url->getQuery(); - $requestUrl .= (empty($path)? '/': $path) . (empty($query)? '': '?' . $query); - } - - if ('1.1' == $this->request->getConfig('protocol_version') && - extension_loaded('zlib') && !isset($headers['accept-encoding']) - ) { - $headers['accept-encoding'] = 'gzip, deflate'; - } - - $this->addAuthorizationHeader($headers, $host, $requestUrl); - $this->addProxyAuthorizationHeader($headers, $requestUrl); - $this->calculateRequestLength($headers); - - $headersStr = $this->request->getMethod() . ' ' . $requestUrl . ' HTTP/' . - $this->request->getConfig('protocol_version') . "\r\n"; - foreach ($headers as $name => $value) { - $canonicalName = implode('-', array_map('ucfirst', explode('-', $name))); - $headersStr .= $canonicalName . ': ' . $value . "\r\n"; - } - return $headersStr . "\r\n"; - } - - /** - * Sends the request body - * - * @throws HTTP_Request2_Exception - */ - protected function writeBody() - { - if (in_array($this->request->getMethod(), self::$bodyDisallowed) || - 0 == $this->contentLength - ) { - return; - } - - $position = 0; - $bufferSize = $this->request->getConfig('buffer_size'); - while ($position < $this->contentLength) { - if (is_string($this->requestBody)) { - $str = substr($this->requestBody, $position, $bufferSize); - } elseif (is_resource($this->requestBody)) { - $str = fread($this->requestBody, $bufferSize); - } else { - $str = $this->requestBody->read($bufferSize); - } - if (false === @fwrite($this->socket, $str, strlen($str))) { - throw new HTTP_Request2_Exception('Error writing request'); - } - // Provide the length of written string to the observer, request #7630 - $this->request->setLastEvent('sentBodyPart', strlen($str)); - $position += strlen($str); - } - } - - /** - * Reads the remote server's response - * - * @return HTTP_Request2_Response - * @throws HTTP_Request2_Exception - */ - protected function readResponse() - { - $bufferSize = $this->request->getConfig('buffer_size'); - - do { - $response = new HTTP_Request2_Response($this->readLine($bufferSize), true); - do { - $headerLine = $this->readLine($bufferSize); - $response->parseHeaderLine($headerLine); - } while ('' != $headerLine); - } while (in_array($response->getStatus(), array(100, 101))); - - $this->request->setLastEvent('receivedHeaders', $response); - - // No body possible in such responses - if (HTTP_Request2::METHOD_HEAD == $this->request->getMethod() || - (HTTP_Request2::METHOD_CONNECT == $this->request->getMethod() && - 200 <= $response->getStatus() && 300 > $response->getStatus()) || - in_array($response->getStatus(), array(204, 304)) - ) { - return $response; - } - - $chunked = 'chunked' == $response->getHeader('transfer-encoding'); - $length = $response->getHeader('content-length'); - $hasBody = false; - if ($chunked || null === $length || 0 < intval($length)) { - // RFC 2616, section 4.4: - // 3. ... If a message is received with both a - // Transfer-Encoding header field and a Content-Length header field, - // the latter MUST be ignored. - $toRead = ($chunked || null === $length)? null: $length; - $this->chunkLength = 0; - - while (!feof($this->socket) && (is_null($toRead) || 0 < $toRead)) { - if ($chunked) { - $data = $this->readChunked($bufferSize); - } elseif (is_null($toRead)) { - $data = $this->fread($bufferSize); - } else { - $data = $this->fread(min($toRead, $bufferSize)); - $toRead -= strlen($data); - } - if ('' == $data && (!$this->chunkLength || feof($this->socket))) { - break; - } - - $hasBody = true; - if ($this->request->getConfig('store_body')) { - $response->appendBody($data); - } - if (!in_array($response->getHeader('content-encoding'), array('identity', null))) { - $this->request->setLastEvent('receivedEncodedBodyPart', $data); - } else { - $this->request->setLastEvent('receivedBodyPart', $data); - } - } - } - - if ($hasBody) { - $this->request->setLastEvent('receivedBody', $response); - } - return $response; - } - - /** - * Reads until either the end of the socket or a newline, whichever comes first - * - * Strips the trailing newline from the returned data, handles global - * request timeout. Method idea borrowed from Net_Socket PEAR package. - * - * @param int buffer size to use for reading - * @return Available data up to the newline (not including newline) - * @throws HTTP_Request2_Exception In case of timeout - */ - protected function readLine($bufferSize) - { - $line = ''; - while (!feof($this->socket)) { - if ($this->timeout) { - stream_set_timeout($this->socket, max($this->timeout - time(), 1)); - } - $line .= @fgets($this->socket, $bufferSize); - $info = stream_get_meta_data($this->socket); - if ($info['timed_out'] || $this->timeout && time() > $this->timeout) { - throw new HTTP_Request2_Exception( - 'Request timed out after ' . - $this->request->getConfig('timeout') . ' second(s)' - ); - } - if (substr($line, -1) == "\n") { - return rtrim($line, "\r\n"); - } - } - return $line; - } - - /** - * Wrapper around fread(), handles global request timeout - * - * @param int Reads up to this number of bytes - * @return Data read from socket - * @throws HTTP_Request2_Exception In case of timeout - */ - protected function fread($length) - { - if ($this->timeout) { - stream_set_timeout($this->socket, max($this->timeout - time(), 1)); - } - $data = fread($this->socket, $length); - $info = stream_get_meta_data($this->socket); - if ($info['timed_out'] || $this->timeout && time() > $this->timeout) { - throw new HTTP_Request2_Exception( - 'Request timed out after ' . - $this->request->getConfig('timeout') . ' second(s)' - ); - } - return $data; - } - - /** - * Reads a part of response body encoded with chunked Transfer-Encoding - * - * @param int buffer size to use for reading - * @return string - * @throws HTTP_Request2_Exception - */ - protected function readChunked($bufferSize) - { - // at start of the next chunk? - if (0 == $this->chunkLength) { - $line = $this->readLine($bufferSize); - if (!preg_match('/^([0-9a-f]+)/i', $line, $matches)) { - throw new HTTP_Request2_Exception( - "Cannot decode chunked response, invalid chunk length '{$line}'" - ); - } else { - $this->chunkLength = hexdec($matches[1]); - // Chunk with zero length indicates the end - if (0 == $this->chunkLength) { - $this->readLine($bufferSize); - return ''; - } - } - } - $data = $this->fread(min($this->chunkLength, $bufferSize)); - $this->chunkLength -= strlen($data); - if (0 == $this->chunkLength) { - $this->readLine($bufferSize); // Trailing CRLF - } - return $data; - } -} - -?> \ No newline at end of file diff --git a/extlib/HTTP/Request2/Exception.php b/extlib/HTTP/Request2/Exception.php deleted file mode 100644 index bfef7d6c2..000000000 --- a/extlib/HTTP/Request2/Exception.php +++ /dev/null @@ -1,62 +0,0 @@ - - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * The names of the authors may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * @category HTTP - * @package HTTP_Request2 - * @author Alexey Borzov - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version CVS: $Id: Exception.php 273003 2009-01-07 19:28:22Z avb $ - * @link http://pear.php.net/package/HTTP_Request2 - */ - -/** - * Base class for exceptions in PEAR - */ -require_once 'PEAR/Exception.php'; - -/** - * Exception class for HTTP_Request2 package - * - * Such a class is required by the Exception RFC: - * http://pear.php.net/pepr/pepr-proposal-show.php?id=132 - * - * @category HTTP - * @package HTTP_Request2 - * @version Release: 0.4.1 - */ -class HTTP_Request2_Exception extends PEAR_Exception -{ -} -?> \ No newline at end of file diff --git a/extlib/HTTP/Request2/MultipartBody.php b/extlib/HTTP/Request2/MultipartBody.php deleted file mode 100644 index d8afd8344..000000000 --- a/extlib/HTTP/Request2/MultipartBody.php +++ /dev/null @@ -1,274 +0,0 @@ - - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * The names of the authors may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * @category HTTP - * @package HTTP_Request2 - * @author Alexey Borzov - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version CVS: $Id: MultipartBody.php 287306 2009-08-14 15:22:52Z avb $ - * @link http://pear.php.net/package/HTTP_Request2 - */ - -/** - * Class for building multipart/form-data request body - * - * The class helps to reduce memory consumption by streaming large file uploads - * from disk, it also allows monitoring of upload progress (see request #7630) - * - * @category HTTP - * @package HTTP_Request2 - * @author Alexey Borzov - * @version Release: 0.4.1 - * @link http://tools.ietf.org/html/rfc1867 - */ -class HTTP_Request2_MultipartBody -{ - /** - * MIME boundary - * @var string - */ - private $_boundary; - - /** - * Form parameters added via {@link HTTP_Request2::addPostParameter()} - * @var array - */ - private $_params = array(); - - /** - * File uploads added via {@link HTTP_Request2::addUpload()} - * @var array - */ - private $_uploads = array(); - - /** - * Header for parts with parameters - * @var string - */ - private $_headerParam = "--%s\r\nContent-Disposition: form-data; name=\"%s\"\r\n\r\n"; - - /** - * Header for parts with uploads - * @var string - */ - private $_headerUpload = "--%s\r\nContent-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\nContent-Type: %s\r\n\r\n"; - - /** - * Current position in parameter and upload arrays - * - * First number is index of "current" part, second number is position within - * "current" part - * - * @var array - */ - private $_pos = array(0, 0); - - - /** - * Constructor. Sets the arrays with POST data. - * - * @param array values of form fields set via {@link HTTP_Request2::addPostParameter()} - * @param array file uploads set via {@link HTTP_Request2::addUpload()} - * @param bool whether to append brackets to array variable names - */ - public function __construct(array $params, array $uploads, $useBrackets = true) - { - $this->_params = self::_flattenArray('', $params, $useBrackets); - foreach ($uploads as $fieldName => $f) { - if (!is_array($f['fp'])) { - $this->_uploads[] = $f + array('name' => $fieldName); - } else { - for ($i = 0; $i < count($f['fp']); $i++) { - $upload = array( - 'name' => ($useBrackets? $fieldName . '[' . $i . ']': $fieldName) - ); - foreach (array('fp', 'filename', 'size', 'type') as $key) { - $upload[$key] = $f[$key][$i]; - } - $this->_uploads[] = $upload; - } - } - } - } - - /** - * Returns the length of the body to use in Content-Length header - * - * @return integer - */ - public function getLength() - { - $boundaryLength = strlen($this->getBoundary()); - $headerParamLength = strlen($this->_headerParam) - 4 + $boundaryLength; - $headerUploadLength = strlen($this->_headerUpload) - 8 + $boundaryLength; - $length = $boundaryLength + 6; - foreach ($this->_params as $p) { - $length += $headerParamLength + strlen($p[0]) + strlen($p[1]) + 2; - } - foreach ($this->_uploads as $u) { - $length += $headerUploadLength + strlen($u['name']) + strlen($u['type']) + - strlen($u['filename']) + $u['size'] + 2; - } - return $length; - } - - /** - * Returns the boundary to use in Content-Type header - * - * @return string - */ - public function getBoundary() - { - if (empty($this->_boundary)) { - $this->_boundary = '--' . md5('PEAR-HTTP_Request2-' . microtime()); - } - return $this->_boundary; - } - - /** - * Returns next chunk of request body - * - * @param integer Amount of bytes to read - * @return string Up to $length bytes of data, empty string if at end - */ - public function read($length) - { - $ret = ''; - $boundary = $this->getBoundary(); - $paramCount = count($this->_params); - $uploadCount = count($this->_uploads); - while ($length > 0 && $this->_pos[0] <= $paramCount + $uploadCount) { - $oldLength = $length; - if ($this->_pos[0] < $paramCount) { - $param = sprintf($this->_headerParam, $boundary, - $this->_params[$this->_pos[0]][0]) . - $this->_params[$this->_pos[0]][1] . "\r\n"; - $ret .= substr($param, $this->_pos[1], $length); - $length -= min(strlen($param) - $this->_pos[1], $length); - - } elseif ($this->_pos[0] < $paramCount + $uploadCount) { - $pos = $this->_pos[0] - $paramCount; - $header = sprintf($this->_headerUpload, $boundary, - $this->_uploads[$pos]['name'], - $this->_uploads[$pos]['filename'], - $this->_uploads[$pos]['type']); - if ($this->_pos[1] < strlen($header)) { - $ret .= substr($header, $this->_pos[1], $length); - $length -= min(strlen($header) - $this->_pos[1], $length); - } - $filePos = max(0, $this->_pos[1] - strlen($header)); - if ($length > 0 && $filePos < $this->_uploads[$pos]['size']) { - $ret .= fread($this->_uploads[$pos]['fp'], $length); - $length -= min($length, $this->_uploads[$pos]['size'] - $filePos); - } - if ($length > 0) { - $start = $this->_pos[1] + ($oldLength - $length) - - strlen($header) - $this->_uploads[$pos]['size']; - $ret .= substr("\r\n", $start, $length); - $length -= min(2 - $start, $length); - } - - } else { - $closing = '--' . $boundary . "--\r\n"; - $ret .= substr($closing, $this->_pos[1], $length); - $length -= min(strlen($closing) - $this->_pos[1], $length); - } - if ($length > 0) { - $this->_pos = array($this->_pos[0] + 1, 0); - } else { - $this->_pos[1] += $oldLength; - } - } - return $ret; - } - - /** - * Sets the current position to the start of the body - * - * This allows reusing the same body in another request - */ - public function rewind() - { - $this->_pos = array(0, 0); - foreach ($this->_uploads as $u) { - rewind($u['fp']); - } - } - - /** - * Returns the body as string - * - * Note that it reads all file uploads into memory so it is a good idea not - * to use this method with large file uploads and rely on read() instead. - * - * @return string - */ - public function __toString() - { - $this->rewind(); - return $this->read($this->getLength()); - } - - - /** - * Helper function to change the (probably multidimensional) associative array - * into the simple one. - * - * @param string name for item - * @param mixed item's values - * @param bool whether to append [] to array variables' names - * @return array array with the following items: array('item name', 'item value'); - */ - private static function _flattenArray($name, $values, $useBrackets) - { - if (!is_array($values)) { - return array(array($name, $values)); - } else { - $ret = array(); - foreach ($values as $k => $v) { - if (empty($name)) { - $newName = $k; - } elseif ($useBrackets) { - $newName = $name . '[' . $k . ']'; - } else { - $newName = $name; - } - $ret = array_merge($ret, self::_flattenArray($newName, $v, $useBrackets)); - } - return $ret; - } - } -} -?> diff --git a/extlib/HTTP/Request2/Observer/Log.php b/extlib/HTTP/Request2/Observer/Log.php deleted file mode 100644 index b1a055278..000000000 --- a/extlib/HTTP/Request2/Observer/Log.php +++ /dev/null @@ -1,215 +0,0 @@ - - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * The names of the authors may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * @category HTTP - * @package HTTP_Request2 - * @author David Jean Louis - * @author Alexey Borzov - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version CVS: $Id: Log.php 272593 2009-01-02 16:27:14Z avb $ - * @link http://pear.php.net/package/HTTP_Request2 - */ - -/** - * Exception class for HTTP_Request2 package - */ -require_once 'HTTP/Request2/Exception.php'; - -/** - * A debug observer useful for debugging / testing. - * - * This observer logs to a log target data corresponding to the various request - * and response events, it logs by default to php://output but can be configured - * to log to a file or via the PEAR Log package. - * - * A simple example: - * - * require_once 'HTTP/Request2.php'; - * require_once 'HTTP/Request2/Observer/Log.php'; - * - * $request = new HTTP_Request2('http://www.example.com'); - * $observer = new HTTP_Request2_Observer_Log(); - * $request->attach($observer); - * $request->send(); - * - * - * A more complex example with PEAR Log: - * - * require_once 'HTTP/Request2.php'; - * require_once 'HTTP/Request2/Observer/Log.php'; - * require_once 'Log.php'; - * - * $request = new HTTP_Request2('http://www.example.com'); - * // we want to log with PEAR log - * $observer = new HTTP_Request2_Observer_Log(Log::factory('console')); - * - * // we only want to log received headers - * $observer->events = array('receivedHeaders'); - * - * $request->attach($observer); - * $request->send(); - * - * - * @category HTTP - * @package HTTP_Request2 - * @author David Jean Louis - * @author Alexey Borzov - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 0.4.1 - * @link http://pear.php.net/package/HTTP_Request2 - */ -class HTTP_Request2_Observer_Log implements SplObserver -{ - // properties {{{ - - /** - * The log target, it can be a a resource or a PEAR Log instance. - * - * @var resource|Log $target - */ - protected $target = null; - - /** - * The events to log. - * - * @var array $events - */ - public $events = array( - 'connect', - 'sentHeaders', - 'sentBodyPart', - 'receivedHeaders', - 'receivedBody', - 'disconnect', - ); - - // }}} - // __construct() {{{ - - /** - * Constructor. - * - * @param mixed $target Can be a file path (default: php://output), a resource, - * or an instance of the PEAR Log class. - * @param array $events Array of events to listen to (default: all events) - * - * @return void - */ - public function __construct($target = 'php://output', array $events = array()) - { - if (!empty($events)) { - $this->events = $events; - } - if (is_resource($target) || $target instanceof Log) { - $this->target = $target; - } elseif (false === ($this->target = @fopen($target, 'w'))) { - throw new HTTP_Request2_Exception("Unable to open '{$target}'"); - } - } - - // }}} - // update() {{{ - - /** - * Called when the request notify us of an event. - * - * @param HTTP_Request2 $subject The HTTP_Request2 instance - * - * @return void - */ - public function update(SplSubject $subject) - { - $event = $subject->getLastEvent(); - if (!in_array($event['name'], $this->events)) { - return; - } - - switch ($event['name']) { - case 'connect': - $this->log('* Connected to ' . $event['data']); - break; - case 'sentHeaders': - $headers = explode("\r\n", $event['data']); - array_pop($headers); - foreach ($headers as $header) { - $this->log('> ' . $header); - } - break; - case 'sentBodyPart': - $this->log('> ' . $event['data']); - break; - case 'receivedHeaders': - $this->log(sprintf('< HTTP/%s %s %s', - $event['data']->getVersion(), - $event['data']->getStatus(), - $event['data']->getReasonPhrase())); - $headers = $event['data']->getHeader(); - foreach ($headers as $key => $val) { - $this->log('< ' . $key . ': ' . $val); - } - $this->log('< '); - break; - case 'receivedBody': - $this->log($event['data']->getBody()); - break; - case 'disconnect': - $this->log('* Disconnected'); - break; - } - } - - // }}} - // log() {{{ - - /** - * Log the given message to the configured target. - * - * @param string $message Message to display - * - * @return void - */ - protected function log($message) - { - if ($this->target instanceof Log) { - $this->target->debug($message); - } elseif (is_resource($this->target)) { - fwrite($this->target, $message . "\r\n"); - } - } - - // }}} -} - -?> \ No newline at end of file diff --git a/extlib/HTTP/Request2/Response.php b/extlib/HTTP/Request2/Response.php deleted file mode 100644 index c7c1021fb..000000000 --- a/extlib/HTTP/Request2/Response.php +++ /dev/null @@ -1,549 +0,0 @@ - - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * The names of the authors may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * @category HTTP - * @package HTTP_Request2 - * @author Alexey Borzov - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version CVS: $Id: Response.php 287948 2009-09-01 17:12:18Z avb $ - * @link http://pear.php.net/package/HTTP_Request2 - */ - -/** - * Exception class for HTTP_Request2 package - */ -require_once 'HTTP/Request2/Exception.php'; - -/** - * Class representing a HTTP response - * - * The class is designed to be used in "streaming" scenario, building the - * response as it is being received: - * - * $statusLine = read_status_line(); - * $response = new HTTP_Request2_Response($statusLine); - * do { - * $headerLine = read_header_line(); - * $response->parseHeaderLine($headerLine); - * } while ($headerLine != ''); - * - * while ($chunk = read_body()) { - * $response->appendBody($chunk); - * } - * - * var_dump($response->getHeader(), $response->getCookies(), $response->getBody()); - * - * - * - * @category HTTP - * @package HTTP_Request2 - * @author Alexey Borzov - * @version Release: 0.4.1 - * @link http://tools.ietf.org/html/rfc2616#section-6 - */ -class HTTP_Request2_Response -{ - /** - * HTTP protocol version (e.g. 1.0, 1.1) - * @var string - */ - protected $version; - - /** - * Status code - * @var integer - * @link http://tools.ietf.org/html/rfc2616#section-6.1.1 - */ - protected $code; - - /** - * Reason phrase - * @var string - * @link http://tools.ietf.org/html/rfc2616#section-6.1.1 - */ - protected $reasonPhrase; - - /** - * Associative array of response headers - * @var array - */ - protected $headers = array(); - - /** - * Cookies set in the response - * @var array - */ - protected $cookies = array(); - - /** - * Name of last header processed by parseHederLine() - * - * Used to handle the headers that span multiple lines - * - * @var string - */ - protected $lastHeader = null; - - /** - * Response body - * @var string - */ - protected $body = ''; - - /** - * Whether the body is still encoded by Content-Encoding - * - * cURL provides the decoded body to the callback; if we are reading from - * socket the body is still gzipped / deflated - * - * @var bool - */ - protected $bodyEncoded; - - /** - * Associative array of HTTP status code / reason phrase. - * - * @var array - * @link http://tools.ietf.org/html/rfc2616#section-10 - */ - protected static $phrases = array( - - // 1xx: Informational - Request received, continuing process - 100 => 'Continue', - 101 => 'Switching Protocols', - - // 2xx: Success - The action was successfully received, understood and - // accepted - 200 => 'OK', - 201 => 'Created', - 202 => 'Accepted', - 203 => 'Non-Authoritative Information', - 204 => 'No Content', - 205 => 'Reset Content', - 206 => 'Partial Content', - - // 3xx: Redirection - Further action must be taken in order to complete - // the request - 300 => 'Multiple Choices', - 301 => 'Moved Permanently', - 302 => 'Found', // 1.1 - 303 => 'See Other', - 304 => 'Not Modified', - 305 => 'Use Proxy', - 307 => 'Temporary Redirect', - - // 4xx: Client Error - The request contains bad syntax or cannot be - // fulfilled - 400 => 'Bad Request', - 401 => 'Unauthorized', - 402 => 'Payment Required', - 403 => 'Forbidden', - 404 => 'Not Found', - 405 => 'Method Not Allowed', - 406 => 'Not Acceptable', - 407 => 'Proxy Authentication Required', - 408 => 'Request Timeout', - 409 => 'Conflict', - 410 => 'Gone', - 411 => 'Length Required', - 412 => 'Precondition Failed', - 413 => 'Request Entity Too Large', - 414 => 'Request-URI Too Long', - 415 => 'Unsupported Media Type', - 416 => 'Requested Range Not Satisfiable', - 417 => 'Expectation Failed', - - // 5xx: Server Error - The server failed to fulfill an apparently - // valid request - 500 => 'Internal Server Error', - 501 => 'Not Implemented', - 502 => 'Bad Gateway', - 503 => 'Service Unavailable', - 504 => 'Gateway Timeout', - 505 => 'HTTP Version Not Supported', - 509 => 'Bandwidth Limit Exceeded', - - ); - - /** - * Constructor, parses the response status line - * - * @param string Response status line (e.g. "HTTP/1.1 200 OK") - * @param bool Whether body is still encoded by Content-Encoding - * @throws HTTP_Request2_Exception if status line is invalid according to spec - */ - public function __construct($statusLine, $bodyEncoded = true) - { - if (!preg_match('!^HTTP/(\d\.\d) (\d{3})(?: (.+))?!', $statusLine, $m)) { - throw new HTTP_Request2_Exception("Malformed response: {$statusLine}"); - } - $this->version = $m[1]; - $this->code = intval($m[2]); - if (!empty($m[3])) { - $this->reasonPhrase = trim($m[3]); - } elseif (!empty(self::$phrases[$this->code])) { - $this->reasonPhrase = self::$phrases[$this->code]; - } - $this->bodyEncoded = (bool)$bodyEncoded; - } - - /** - * Parses the line from HTTP response filling $headers array - * - * The method should be called after reading the line from socket or receiving - * it into cURL callback. Passing an empty string here indicates the end of - * response headers and triggers additional processing, so be sure to pass an - * empty string in the end. - * - * @param string Line from HTTP response - */ - public function parseHeaderLine($headerLine) - { - $headerLine = trim($headerLine, "\r\n"); - - // empty string signals the end of headers, process the received ones - if ('' == $headerLine) { - if (!empty($this->headers['set-cookie'])) { - $cookies = is_array($this->headers['set-cookie'])? - $this->headers['set-cookie']: - array($this->headers['set-cookie']); - foreach ($cookies as $cookieString) { - $this->parseCookie($cookieString); - } - unset($this->headers['set-cookie']); - } - foreach (array_keys($this->headers) as $k) { - if (is_array($this->headers[$k])) { - $this->headers[$k] = implode(', ', $this->headers[$k]); - } - } - - // string of the form header-name: header value - } elseif (preg_match('!^([^\x00-\x1f\x7f-\xff()<>@,;:\\\\"/\[\]?={}\s]+):(.+)$!', $headerLine, $m)) { - $name = strtolower($m[1]); - $value = trim($m[2]); - if (empty($this->headers[$name])) { - $this->headers[$name] = $value; - } else { - if (!is_array($this->headers[$name])) { - $this->headers[$name] = array($this->headers[$name]); - } - $this->headers[$name][] = $value; - } - $this->lastHeader = $name; - - // string - } elseif (preg_match('!^\s+(.+)$!', $headerLine, $m) && $this->lastHeader) { - if (!is_array($this->headers[$this->lastHeader])) { - $this->headers[$this->lastHeader] .= ' ' . trim($m[1]); - } else { - $key = count($this->headers[$this->lastHeader]) - 1; - $this->headers[$this->lastHeader][$key] .= ' ' . trim($m[1]); - } - } - } - - /** - * Parses a Set-Cookie header to fill $cookies array - * - * @param string value of Set-Cookie header - * @link http://cgi.netscape.com/newsref/std/cookie_spec.html - */ - protected function parseCookie($cookieString) - { - $cookie = array( - 'expires' => null, - 'domain' => null, - 'path' => null, - 'secure' => false - ); - - // Only a name=value pair - if (!strpos($cookieString, ';')) { - $pos = strpos($cookieString, '='); - $cookie['name'] = trim(substr($cookieString, 0, $pos)); - $cookie['value'] = trim(substr($cookieString, $pos + 1)); - - // Some optional parameters are supplied - } else { - $elements = explode(';', $cookieString); - $pos = strpos($elements[0], '='); - $cookie['name'] = trim(substr($elements[0], 0, $pos)); - $cookie['value'] = trim(substr($elements[0], $pos + 1)); - - for ($i = 1; $i < count($elements); $i++) { - if (false === strpos($elements[$i], '=')) { - $elName = trim($elements[$i]); - $elValue = null; - } else { - list ($elName, $elValue) = array_map('trim', explode('=', $elements[$i])); - } - $elName = strtolower($elName); - if ('secure' == $elName) { - $cookie['secure'] = true; - } elseif ('expires' == $elName) { - $cookie['expires'] = str_replace('"', '', $elValue); - } elseif ('path' == $elName || 'domain' == $elName) { - $cookie[$elName] = urldecode($elValue); - } else { - $cookie[$elName] = $elValue; - } - } - } - $this->cookies[] = $cookie; - } - - /** - * Appends a string to the response body - * @param string - */ - public function appendBody($bodyChunk) - { - $this->body .= $bodyChunk; - } - - /** - * Returns the status code - * @return integer - */ - public function getStatus() - { - return $this->code; - } - - /** - * Returns the reason phrase - * @return string - */ - public function getReasonPhrase() - { - return $this->reasonPhrase; - } - - /** - * Returns either the named header or all response headers - * - * @param string Name of header to return - * @return string|array Value of $headerName header (null if header is - * not present), array of all response headers if - * $headerName is null - */ - public function getHeader($headerName = null) - { - if (null === $headerName) { - return $this->headers; - } else { - $headerName = strtolower($headerName); - return isset($this->headers[$headerName])? $this->headers[$headerName]: null; - } - } - - /** - * Returns cookies set in response - * - * @return array - */ - public function getCookies() - { - return $this->cookies; - } - - /** - * Returns the body of the response - * - * @return string - * @throws HTTP_Request2_Exception if body cannot be decoded - */ - public function getBody() - { - if (!$this->bodyEncoded || - !in_array(strtolower($this->getHeader('content-encoding')), array('gzip', 'deflate')) - ) { - return $this->body; - - } else { - if (extension_loaded('mbstring') && (2 & ini_get('mbstring.func_overload'))) { - $oldEncoding = mb_internal_encoding(); - mb_internal_encoding('iso-8859-1'); - } - - try { - switch (strtolower($this->getHeader('content-encoding'))) { - case 'gzip': - $decoded = self::decodeGzip($this->body); - break; - case 'deflate': - $decoded = self::decodeDeflate($this->body); - } - } catch (Exception $e) { - } - - if (!empty($oldEncoding)) { - mb_internal_encoding($oldEncoding); - } - if (!empty($e)) { - throw $e; - } - return $decoded; - } - } - - /** - * Get the HTTP version of the response - * - * @return string - */ - public function getVersion() - { - return $this->version; - } - - /** - * Decodes the message-body encoded by gzip - * - * The real decoding work is done by gzinflate() built-in function, this - * method only parses the header and checks data for compliance with - * RFC 1952 - * - * @param string gzip-encoded data - * @return string decoded data - * @throws HTTP_Request2_Exception - * @link http://tools.ietf.org/html/rfc1952 - */ - public static function decodeGzip($data) - { - $length = strlen($data); - // If it doesn't look like gzip-encoded data, don't bother - if (18 > $length || strcmp(substr($data, 0, 2), "\x1f\x8b")) { - return $data; - } - if (!function_exists('gzinflate')) { - throw new HTTP_Request2_Exception('Unable to decode body: gzip extension not available'); - } - $method = ord(substr($data, 2, 1)); - if (8 != $method) { - throw new HTTP_Request2_Exception('Error parsing gzip header: unknown compression method'); - } - $flags = ord(substr($data, 3, 1)); - if ($flags & 224) { - throw new HTTP_Request2_Exception('Error parsing gzip header: reserved bits are set'); - } - - // header is 10 bytes minimum. may be longer, though. - $headerLength = 10; - // extra fields, need to skip 'em - if ($flags & 4) { - if ($length - $headerLength - 2 < 8) { - throw new HTTP_Request2_Exception('Error parsing gzip header: data too short'); - } - $extraLength = unpack('v', substr($data, 10, 2)); - if ($length - $headerLength - 2 - $extraLength[1] < 8) { - throw new HTTP_Request2_Exception('Error parsing gzip header: data too short'); - } - $headerLength += $extraLength[1] + 2; - } - // file name, need to skip that - if ($flags & 8) { - if ($length - $headerLength - 1 < 8) { - throw new HTTP_Request2_Exception('Error parsing gzip header: data too short'); - } - $filenameLength = strpos(substr($data, $headerLength), chr(0)); - if (false === $filenameLength || $length - $headerLength - $filenameLength - 1 < 8) { - throw new HTTP_Request2_Exception('Error parsing gzip header: data too short'); - } - $headerLength += $filenameLength + 1; - } - // comment, need to skip that also - if ($flags & 16) { - if ($length - $headerLength - 1 < 8) { - throw new HTTP_Request2_Exception('Error parsing gzip header: data too short'); - } - $commentLength = strpos(substr($data, $headerLength), chr(0)); - if (false === $commentLength || $length - $headerLength - $commentLength - 1 < 8) { - throw new HTTP_Request2_Exception('Error parsing gzip header: data too short'); - } - $headerLength += $commentLength + 1; - } - // have a CRC for header. let's check - if ($flags & 2) { - if ($length - $headerLength - 2 < 8) { - throw new HTTP_Request2_Exception('Error parsing gzip header: data too short'); - } - $crcReal = 0xffff & crc32(substr($data, 0, $headerLength)); - $crcStored = unpack('v', substr($data, $headerLength, 2)); - if ($crcReal != $crcStored[1]) { - throw new HTTP_Request2_Exception('Header CRC check failed'); - } - $headerLength += 2; - } - // unpacked data CRC and size at the end of encoded data - $tmp = unpack('V2', substr($data, -8)); - $dataCrc = $tmp[1]; - $dataSize = $tmp[2]; - - // finally, call the gzinflate() function - // don't pass $dataSize to gzinflate, see bugs #13135, #14370 - $unpacked = gzinflate(substr($data, $headerLength, -8)); - if (false === $unpacked) { - throw new HTTP_Request2_Exception('gzinflate() call failed'); - } elseif ($dataSize != strlen($unpacked)) { - throw new HTTP_Request2_Exception('Data size check failed'); - } elseif ((0xffffffff & $dataCrc) != (0xffffffff & crc32($unpacked))) { - throw new HTTP_Request2_Exception('Data CRC check failed'); - } - return $unpacked; - } - - /** - * Decodes the message-body encoded by deflate - * - * @param string deflate-encoded data - * @return string decoded data - * @throws HTTP_Request2_Exception - */ - public static function decodeDeflate($data) - { - if (!function_exists('gzuncompress')) { - throw new HTTP_Request2_Exception('Unable to decode body: gzip extension not available'); - } - // RFC 2616 defines 'deflate' encoding as zlib format from RFC 1950, - // while many applications send raw deflate stream from RFC 1951. - // We should check for presence of zlib header and use gzuncompress() or - // gzinflate() as needed. See bug #15305 - $header = unpack('n', substr($data, 0, 2)); - return (0 == $header[1] % 31)? gzuncompress($data): gzinflate($data); - } -} -?> \ No newline at end of file diff --git a/extlib/Net/URL2.php b/extlib/Net/URL2.php index f7fbcd9ce..7a654aed8 100644 --- a/extlib/Net/URL2.php +++ b/extlib/Net/URL2.php @@ -1,58 +1,44 @@ | +// +-----------------------------------------------------------------------+ +// +// $Id: URL2.php,v 1.10 2008/04/26 21:57:08 schmidt Exp $ +// +// Net_URL2 Class (PHP5 Only) + +// This code is released under the BSD License - http://www.opensource.org/licenses/bsd-license.php /** - * Net_URL2, a class representing a URL as per RFC 3986. - * - * PHP version 5 - * - * LICENSE: - * - * Copyright (c) 2007-2009, Peytz & Co. A/S - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the distribution. - * * Neither the name of the PHP_LexerGenerator nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * @category Networking - * @package Net_URL2 - * @author Christian Schmidt - * @copyright 2007-2008 Peytz & Co. A/S - * @license http://www.opensource.org/licenses/bsd-license.php New BSD License - * @version CVS: $Id: URL2.php 286661 2009-08-02 12:50:54Z schmidt $ - * @link http://www.rfc-editor.org/rfc/rfc3986.txt - */ - -/** - * Represents a URL as per RFC 3986. - * - * @category Networking - * @package Net_URL2 - * @author Christian Schmidt - * @copyright 2007-2008 Peytz & Co. ApS - * @license http://www.opensource.org/licenses/bsd-license.php New BSD License - * @version Release: @package_version@ - * @link http://pear.php.net/package/Net_URL2 + * @license BSD License */ class Net_URL2 { @@ -60,24 +46,24 @@ class Net_URL2 * Do strict parsing in resolve() (see RFC 3986, section 5.2.2). Default * is true. */ - const OPTION_STRICT = 'strict'; + const OPTION_STRICT = 'strict'; /** * Represent arrays in query using PHP's [] notation. Default is true. */ - const OPTION_USE_BRACKETS = 'use_brackets'; + const OPTION_USE_BRACKETS = 'use_brackets'; /** * URL-encode query variable keys. Default is true. */ - const OPTION_ENCODE_KEYS = 'encode_keys'; + const OPTION_ENCODE_KEYS = 'encode_keys'; /** * Query variable separators when parsing the query string. Every character * is considered a separator. Default is specified by the * arg_separator.input php.ini setting (this defaults to "&"). */ - const OPTION_SEPARATOR_INPUT = 'input_separator'; + const OPTION_SEPARATOR_INPUT = 'input_separator'; /** * Query variable separator used when generating the query string. Default @@ -89,7 +75,7 @@ class Net_URL2 /** * Default options corresponds to how PHP handles $_GET. */ - private $_options = array( + private $options = array( self::OPTION_STRICT => true, self::OPTION_USE_BRACKETS => true, self::OPTION_ENCODE_KEYS => true, @@ -100,43 +86,41 @@ class Net_URL2 /** * @var string|bool */ - private $_scheme = false; + private $scheme = false; /** * @var string|bool */ - private $_userinfo = false; + private $userinfo = false; /** * @var string|bool */ - private $_host = false; + private $host = false; /** * @var int|bool */ - private $_port = false; + private $port = false; /** * @var string */ - private $_path = ''; + private $path = ''; /** * @var string|bool */ - private $_query = false; + private $query = false; /** * @var string|bool */ - private $_fragment = false; + private $fragment = false; /** - * Constructor. - * * @param string $url an absolute or relative URL - * @param array $options an array of OPTION_xxx constants + * @param array $options */ public function __construct($url, $options = null) { @@ -146,12 +130,12 @@ class Net_URL2 ini_get('arg_separator.output')); if (is_array($options)) { foreach ($options as $optionName => $value) { - $this->setOption($optionName, $value); + $this->setOption($optionName); } } if (preg_match('@^([a-z][a-z0-9.+-]*):@i', $url, $reg)) { - $this->_scheme = $reg[1]; + $this->scheme = $reg[1]; $url = substr($url, strlen($reg[0])); } @@ -161,58 +145,19 @@ class Net_URL2 } $i = strcspn($url, '?#'); - $this->_path = substr($url, 0, $i); + $this->path = substr($url, 0, $i); $url = substr($url, $i); if (preg_match('@^\?([^#]*)@', $url, $reg)) { - $this->_query = $reg[1]; + $this->query = $reg[1]; $url = substr($url, strlen($reg[0])); } if ($url) { - $this->_fragment = substr($url, 1); + $this->fragment = substr($url, 1); } } - /** - * Magic Setter. - * - * This method will magically set the value of a private variable ($var) - * with the value passed as the args - * - * @param string $var The private variable to set. - * @param mixed $arg An argument of any type. - * @return void - */ - public function __set($var, $arg) - { - $method = 'set' . $var; - if (method_exists($this, $method)) { - $this->$method($arg); - } - } - - /** - * Magic Getter. - * - * This is the magic get method to retrieve the private variable - * that was set by either __set() or it's setter... - * - * @param string $var The property name to retrieve. - * @return mixed $this->$var Either a boolean false if the - * property is not set or the value - * of the private property. - */ - public function __get($var) - { - $method = 'get' . $var; - if (method_exists($this, $method)) { - return $this->$method(); - } - - return false; - } - /** * Returns the scheme, e.g. "http" or "urn", or false if there is no * scheme specified, i.e. if this is a relative URL. @@ -221,23 +166,18 @@ class Net_URL2 */ public function getScheme() { - return $this->_scheme; + return $this->scheme; } /** - * Sets the scheme, e.g. "http" or "urn". Specify false if there is no - * scheme specified, i.e. if this is a relative URL. - * - * @param string|bool $scheme e.g. "http" or "urn", or false if there is no - * scheme specified, i.e. if this is a relative - * URL + * @param string|bool $scheme * * @return void * @see getScheme() */ public function setScheme($scheme) { - $this->_scheme = $scheme; + $this->scheme = $scheme; } /** @@ -248,9 +188,7 @@ class Net_URL2 */ public function getUser() { - return $this->_userinfo !== false - ? preg_replace('@:.*$@', '', $this->_userinfo) - : false; + return $this->userinfo !== false ? preg_replace('@:.*$@', '', $this->userinfo) : false; } /** @@ -263,9 +201,7 @@ class Net_URL2 */ public function getPassword() { - return $this->_userinfo !== false - ? substr(strstr($this->_userinfo, ':'), 1) - : false; + return $this->userinfo !== false ? substr(strstr($this->userinfo, ':'), 1) : false; } /** @@ -276,7 +212,7 @@ class Net_URL2 */ public function getUserinfo() { - return $this->_userinfo; + return $this->userinfo; } /** @@ -284,15 +220,15 @@ class Net_URL2 * in the userinfo part as username ":" password. * * @param string|bool $userinfo userinfo or username - * @param string|bool $password optional password, or false + * @param string|bool $password * * @return void */ public function setUserinfo($userinfo, $password = false) { - $this->_userinfo = $userinfo; + $this->userinfo = $userinfo; if ($password !== false) { - $this->_userinfo .= ':' . $password; + $this->userinfo .= ':' . $password; } } @@ -300,24 +236,21 @@ class Net_URL2 * Returns the host part, or false if there is no authority part, e.g. * relative URLs. * - * @return string|bool a hostname, an IP address, or false + * @return string|bool */ public function getHost() { - return $this->_host; + return $this->host; } /** - * Sets the host part. Specify false if there is no authority part, e.g. - * relative URLs. - * - * @param string|bool $host a hostname, an IP address, or false + * @param string|bool $host * * @return void */ public function setHost($host) { - $this->_host = $host; + $this->host = $host; } /** @@ -328,72 +261,65 @@ class Net_URL2 */ public function getPort() { - return $this->_port; + return $this->port; } /** - * Sets the port number. Specify false if there is no port number specified, - * i.e. if the default port is to be used. - * - * @param int|bool $port a port number, or false + * @param int|bool $port * * @return void */ public function setPort($port) { - $this->_port = intval($port); + $this->port = intval($port); } /** * Returns the authority part, i.e. [ userinfo "@" ] host [ ":" port ], or - * false if there is no authority. + * false if there is no authority none. * * @return string|bool */ public function getAuthority() { - if (!$this->_host) { + if (!$this->host) { return false; } $authority = ''; - if ($this->_userinfo !== false) { - $authority .= $this->_userinfo . '@'; + if ($this->userinfo !== false) { + $authority .= $this->userinfo . '@'; } - $authority .= $this->_host; + $authority .= $this->host; - if ($this->_port !== false) { - $authority .= ':' . $this->_port; + if ($this->port !== false) { + $authority .= ':' . $this->port; } return $authority; } /** - * Sets the authority part, i.e. [ userinfo "@" ] host [ ":" port ]. Specify - * false if there is no authority. - * - * @param string|false $authority a hostname or an IP addresse, possibly - * with userinfo prefixed and port number - * appended, e.g. "foo:bar@example.org:81". + * @param string|false $authority * * @return void */ public function setAuthority($authority) { - $this->_userinfo = false; - $this->_host = false; - $this->_port = false; - if (preg_match('@^(([^\@]*)\@)?([^:]+)(:(\d*))?$@', $authority, $reg)) { + $this->user = false; + $this->pass = false; + $this->host = false; + $this->port = false; + if (preg_match('@^(([^\@]+)\@)?([^:]+)(:(\d*))?$@', $authority, $reg)) { if ($reg[1]) { - $this->_userinfo = $reg[2]; + $this->userinfo = $reg[2]; } - $this->_host = $reg[3]; + $this->host = $reg[3]; if (isset($reg[5])) { - $this->_port = intval($reg[5]); + $this->port = intval($reg[5]); } } } @@ -405,74 +331,65 @@ class Net_URL2 */ public function getPath() { - return $this->_path; + return $this->path; } /** - * Sets the path part (possibly an empty string). - * - * @param string $path a path + * @param string $path * * @return void */ public function setPath($path) { - $this->_path = $path; + $this->path = $path; } /** * Returns the query string (excluding the leading "?"), or false if "?" - * is not present in the URL. + * isn't present in the URL. * * @return string|bool * @see self::getQueryVariables() */ public function getQuery() { - return $this->_query; + return $this->query; } /** - * Sets the query string (excluding the leading "?"). Specify false if "?" - * is not present in the URL. - * - * @param string|bool $query a query string, e.g. "foo=1&bar=2" + * @param string|bool $query * * @return void * @see self::setQueryVariables() */ public function setQuery($query) { - $this->_query = $query; + $this->query = $query; } /** - * Returns the fragment name, or false if "#" is not present in the URL. + * Returns the fragment name, or false if "#" isn't present in the URL. * * @return string|bool */ public function getFragment() { - return $this->_fragment; + return $this->fragment; } /** - * Sets the fragment name. Specify false if "#" is not present in the URL. - * - * @param string|bool $fragment a fragment excluding the leading "#", or - * false + * @param string|bool $fragment * * @return void */ public function setFragment($fragment) { - $this->_fragment = $fragment; + $this->fragment = $fragment; } /** * Returns the query string like an array as the variables would appear in - * $_GET in a PHP script. If the URL does not contain a "?", an empty array - * is returned. + * $_GET in a PHP script. * * @return array */ @@ -481,7 +398,7 @@ class Net_URL2 $pattern = '/[' . preg_quote($this->getOption(self::OPTION_SEPARATOR_INPUT), '/') . ']/'; - $parts = preg_split($pattern, $this->_query, -1, PREG_SPLIT_NO_EMPTY); + $parts = preg_split($pattern, $this->query, -1, PREG_SPLIT_NO_EMPTY); $return = array(); foreach ($parts as $part) { @@ -528,8 +445,6 @@ class Net_URL2 } /** - * Sets the query string to the specified variable in the query string. - * * @param array $array (name => value) array * * @return void @@ -537,11 +452,11 @@ class Net_URL2 public function setQueryVariables(array $array) { if (!$array) { - $this->_query = false; + $this->query = false; } else { foreach ($array as $name => $value) { if ($this->getOption(self::OPTION_ENCODE_KEYS)) { - $name = self::urlencode($name); + $name = rawurlencode($name); } if (is_array($value)) { @@ -551,21 +466,19 @@ class Net_URL2 : ($name . '=' . $v); } } elseif (!is_null($value)) { - $parts[] = $name . '=' . self::urlencode($value); + $parts[] = $name . '=' . $value; } else { $parts[] = $name; } } - $this->_query = implode($this->getOption(self::OPTION_SEPARATOR_OUTPUT), - $parts); + $this->query = implode($this->getOption(self::OPTION_SEPARATOR_OUTPUT), + $parts); } } /** - * Sets the specified variable in the query string. - * - * @param string $name variable name - * @param mixed $value variable value + * @param string $name + * @param mixed $value * * @return array */ @@ -577,9 +490,7 @@ class Net_URL2 } /** - * Removes the specifed variable from the query string. - * - * @param string $name a query string variable, e.g. "foo" in "?foo=1" + * @param string $name * * @return void */ @@ -600,38 +511,27 @@ class Net_URL2 // See RFC 3986, section 5.3 $url = ""; - if ($this->_scheme !== false) { - $url .= $this->_scheme . ':'; + if ($this->scheme !== false) { + $url .= $this->scheme . ':'; } $authority = $this->getAuthority(); if ($authority !== false) { $url .= '//' . $authority; } - $url .= $this->_path; + $url .= $this->path; - if ($this->_query !== false) { - $url .= '?' . $this->_query; + if ($this->query !== false) { + $url .= '?' . $this->query; } - if ($this->_fragment !== false) { - $url .= '#' . $this->_fragment; + if ($this->fragment !== false) { + $url .= '#' . $this->fragment; } return $url; } - /** - * Returns a string representation of this URL. - * - * @return string - * @see toString() - */ - public function __toString() - { - return $this->getURL(); - } - /** * Returns a normalized string representation of this URL. This is useful * for comparison of URLs. @@ -655,38 +555,36 @@ class Net_URL2 // See RFC 3886, section 6 // Schemes are case-insensitive - if ($this->_scheme) { - $this->_scheme = strtolower($this->_scheme); + if ($this->scheme) { + $this->scheme = strtolower($this->scheme); } // Hostnames are case-insensitive - if ($this->_host) { - $this->_host = strtolower($this->_host); + if ($this->host) { + $this->host = strtolower($this->host); } // Remove default port number for known schemes (RFC 3986, section 6.2.3) - if ($this->_port && - $this->_scheme && - $this->_port == getservbyname($this->_scheme, 'tcp')) { + if ($this->port && + $this->scheme && + $this->port == getservbyname($this->scheme, 'tcp')) { - $this->_port = false; + $this->port = false; } // Normalize case of %XX percentage-encodings (RFC 3986, section 6.2.2.1) - foreach (array('_userinfo', '_host', '_path') as $part) { + foreach (array('userinfo', 'host', 'path') as $part) { if ($this->$part) { - $this->$part = preg_replace('/%[0-9a-f]{2}/ie', - 'strtoupper("\0")', - $this->$part); + $this->$part = preg_replace('/%[0-9a-f]{2}/ie', 'strtoupper("\0")', $this->$part); } } // Path segment normalization (RFC 3986, section 6.2.2.3) - $this->_path = self::removeDotSegments($this->_path); + $this->path = self::removeDotSegments($this->path); // Scheme based normalization (RFC 3986, section 6.2.3) - if ($this->_host && !$this->_path) { - $this->_path = '/'; + if ($this->host && !$this->path) { + $this->path = '/'; } } @@ -697,7 +595,7 @@ class Net_URL2 */ public function isAbsolute() { - return (bool) $this->_scheme; + return (bool) $this->scheme; } /** @@ -710,7 +608,7 @@ class Net_URL2 */ public function resolve($reference) { - if (!$reference instanceof Net_URL2) { + if (is_string($reference)) { $reference = new self($reference); } if (!$this->isAbsolute()) { @@ -719,54 +617,54 @@ class Net_URL2 // A non-strict parser may ignore a scheme in the reference if it is // identical to the base URI's scheme. - if (!$this->getOption(self::OPTION_STRICT) && $reference->_scheme == $this->_scheme) { - $reference->_scheme = false; + if (!$this->getOption(self::OPTION_STRICT) && $reference->scheme == $this->scheme) { + $reference->scheme = false; } $target = new self(''); - if ($reference->_scheme !== false) { - $target->_scheme = $reference->_scheme; + if ($reference->scheme !== false) { + $target->scheme = $reference->scheme; $target->setAuthority($reference->getAuthority()); - $target->_path = self::removeDotSegments($reference->_path); - $target->_query = $reference->_query; + $target->path = self::removeDotSegments($reference->path); + $target->query = $reference->query; } else { $authority = $reference->getAuthority(); if ($authority !== false) { $target->setAuthority($authority); - $target->_path = self::removeDotSegments($reference->_path); - $target->_query = $reference->_query; + $target->path = self::removeDotSegments($reference->path); + $target->query = $reference->query; } else { - if ($reference->_path == '') { - $target->_path = $this->_path; - if ($reference->_query !== false) { - $target->_query = $reference->_query; + if ($reference->path == '') { + $target->path = $this->path; + if ($reference->query !== false) { + $target->query = $reference->query; } else { - $target->_query = $this->_query; + $target->query = $this->query; } } else { - if (substr($reference->_path, 0, 1) == '/') { - $target->_path = self::removeDotSegments($reference->_path); + if (substr($reference->path, 0, 1) == '/') { + $target->path = self::removeDotSegments($reference->path); } else { // Merge paths (RFC 3986, section 5.2.3) - if ($this->_host !== false && $this->_path == '') { - $target->_path = '/' . $this->_path; + if ($this->host !== false && $this->path == '') { + $target->path = '/' . $this->path; } else { - $i = strrpos($this->_path, '/'); + $i = strrpos($this->path, '/'); if ($i !== false) { - $target->_path = substr($this->_path, 0, $i + 1); + $target->path = substr($this->path, 0, $i + 1); } - $target->_path .= $reference->_path; + $target->path .= $reference->path; } - $target->_path = self::removeDotSegments($target->_path); + $target->path = self::removeDotSegments($target->path); } - $target->_query = $reference->_query; + $target->query = $reference->query; } $target->setAuthority($this->getAuthority()); } - $target->_scheme = $this->_scheme; + $target->scheme = $this->scheme; } - $target->_fragment = $reference->_fragment; + $target->fragment = $reference->fragment; return $target; } @@ -779,7 +677,7 @@ class Net_URL2 * * @return string a path */ - public static function removeDotSegments($path) + private static function removeDotSegments($path) { $output = ''; @@ -787,25 +685,28 @@ class Net_URL2 // method $j = 0; while ($path && $j++ < 100) { + // Step A if (substr($path, 0, 2) == './') { - // Step 2.A $path = substr($path, 2); } elseif (substr($path, 0, 3) == '../') { - // Step 2.A $path = substr($path, 3); + + // Step B } elseif (substr($path, 0, 3) == '/./' || $path == '/.') { - // Step 2.B $path = '/' . substr($path, 3); + + // Step C } elseif (substr($path, 0, 4) == '/../' || $path == '/..') { - // Step 2.C - $path = '/' . substr($path, 4); - $i = strrpos($output, '/'); + $path = '/' . substr($path, 4); + $i = strrpos($output, '/'); $output = $i === false ? '' : substr($output, 0, $i); + + // Step D } elseif ($path == '.' || $path == '..') { - // Step 2.D $path = ''; + + // Step E } else { - // Step 2.E $i = strpos($path, '/'); if ($i === 0) { $i = strpos($path, '/', 1); @@ -821,22 +722,6 @@ class Net_URL2 return $output; } - /** - * Percent-encodes all non-alphanumeric characters except these: _ . - ~ - * Similar to PHP's rawurlencode(), except that it also encodes ~ in PHP - * 5.2.x and earlier. - * - * @param $raw the string to encode - * @return string - */ - public static function urlencode($string) - { - $encoded = rawurlencode($string); - // This is only necessary in PHP < 5.3. - $encoded = str_replace('%7E', '~', $encoded); - return $encoded; - } - /** * Returns a Net_URL2 instance representing the canonical URL of the * currently executing PHP script. @@ -852,13 +737,13 @@ class Net_URL2 // Begin with a relative URL $url = new self($_SERVER['PHP_SELF']); - $url->_scheme = isset($_SERVER['HTTPS']) ? 'https' : 'http'; - $url->_host = $_SERVER['SERVER_NAME']; + $url->scheme = isset($_SERVER['HTTPS']) ? 'https' : 'http'; + $url->host = $_SERVER['SERVER_NAME']; $port = intval($_SERVER['SERVER_PORT']); - if ($url->_scheme == 'http' && $port != 80 || - $url->_scheme == 'https' && $port != 443) { + if ($url->scheme == 'http' && $port != 80 || + $url->scheme == 'https' && $port != 443) { - $url->_port = $port; + $url->port = $port; } return $url; } @@ -888,7 +773,7 @@ class Net_URL2 // Begin with a relative URL $url = new self($_SERVER['REQUEST_URI']); - $url->_scheme = isset($_SERVER['HTTPS']) ? 'https' : 'http'; + $url->scheme = isset($_SERVER['HTTPS']) ? 'https' : 'http'; // Set host and possibly port $url->setAuthority($_SERVER['HTTP_HOST']); return $url; @@ -907,10 +792,10 @@ class Net_URL2 */ function setOption($optionName, $value) { - if (!array_key_exists($optionName, $this->_options)) { + if (!array_key_exists($optionName, $this->options)) { return false; } - $this->_options[$optionName] = $value; + $this->options[$optionName] = $value; } /** @@ -922,7 +807,7 @@ class Net_URL2 */ function getOption($optionName) { - return isset($this->_options[$optionName]) - ? $this->_options[$optionName] : false; + return isset($this->options[$optionName]) + ? $this->options[$optionName] : false; } } diff --git a/install.php b/install.php index d34e92dab..6bfc4c2e2 100644 --- a/install.php +++ b/install.php @@ -93,13 +93,6 @@ $external_libraries=array( 'include'=>'HTTP/Request.php', 'check_class'=>'HTTP_Request' ), - array( - 'name'=>'HTTP_Request2', - 'pear'=>'HTTP_Request2', - 'url'=>'http://pear.php.net/package/HTTP_Request2', - 'include'=>'HTTP/Request2.php', - 'check_class'=>'HTTP_Request2' - ), array( 'name'=>'Mail', 'pear'=>'Mail', diff --git a/lib/Shorturl_api.php b/lib/Shorturl_api.php index ef0d8dda4..18ae7719b 100644 --- a/lib/Shorturl_api.php +++ b/lib/Shorturl_api.php @@ -41,17 +41,22 @@ abstract class ShortUrlApi return strlen($url) >= common_config('site', 'shorturllength'); } - protected function http_post($data) - { - $request = new HTTPClient($this->service_url); - return $request->post($data); + protected function http_post($data) { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $this->service_url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, $data); + $response = curl_exec($ch); + $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + if (($code < 200) || ($code >= 400)) return false; + return $response; } - protected function http_get($url) - { - $service = $this->service_url . urlencode($url); - $request = new HTTPClient($service); - return $request->get(); + protected function http_get($url) { + $encoded_url = urlencode($url); + return file_get_contents("{$this->service_url}$encoded_url"); } protected function tidy($response) { diff --git a/lib/curlclient.php b/lib/curlclient.php new file mode 100644 index 000000000..c307c2984 --- /dev/null +++ b/lib/curlclient.php @@ -0,0 +1,179 @@ +. + * + * @category HTTP + * @package StatusNet + * @author Evan Prodromou + * @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')) { + exit(1); +} + +define(CURLCLIENT_VERSION, "0.1"); + +/** + * Wrapper for Curl + * + * Makes Curl HTTP client calls within our HTTPClient framework + * + * @category HTTP + * @package StatusNet + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +class CurlClient extends HTTPClient +{ + function __construct() + { + } + + function head($url, $headers=null) + { + $ch = curl_init($url); + + $this->setup($ch); + + curl_setopt_array($ch, + array(CURLOPT_NOBODY => true)); + + if (!is_null($headers)) { + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + } + + $result = curl_exec($ch); + + curl_close($ch); + + return $this->parseResults($result); + } + + function get($url, $headers=null) + { + $ch = curl_init($url); + + $this->setup($ch); + + if (!is_null($headers)) { + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + } + + $result = curl_exec($ch); + + curl_close($ch); + + return $this->parseResults($result); + } + + function post($url, $headers=null, $body=null) + { + $ch = curl_init($url); + + $this->setup($ch); + + curl_setopt($ch, CURLOPT_POST, true); + + if (!is_null($body)) { + curl_setopt($ch, CURLOPT_POSTFIELDS, $body); + } + + if (!is_null($headers)) { + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + } + + $result = curl_exec($ch); + + curl_close($ch); + + return $this->parseResults($result); + } + + function setup($ch) + { + curl_setopt_array($ch, + array(CURLOPT_USERAGENT => $this->userAgent(), + CURLOPT_HEADER => true, + CURLOPT_RETURNTRANSFER => true)); + } + + function userAgent() + { + $version = curl_version(); + return parent::userAgent() . " CurlClient/".CURLCLIENT_VERSION . " cURL/" . $version['version']; + } + + function parseResults($results) + { + $resp = new HTTPResponse(); + + $lines = explode("\r\n", $results); + + if (preg_match("#^HTTP/1.[01] (\d\d\d) .+$#", $lines[0], $match)) { + $resp->code = $match[1]; + } else { + throw Exception("Bad format: initial line is not HTTP status line"); + } + + $lastk = null; + + for ($i = 1; $i < count($lines); $i++) { + $l =& $lines[$i]; + if (mb_strlen($l) == 0) { + $resp->body = implode("\r\n", array_slice($lines, $i + 1)); + break; + } + if (preg_match("#^(\S+):\s+(.*)$#", $l, $match)) { + $k = $match[1]; + $v = $match[2]; + + if (array_key_exists($k, $resp->headers)) { + if (is_array($resp->headers[$k])) { + $resp->headers[$k][] = $v; + } else { + $resp->headers[$k] = array($resp->headers[$k], $v); + } + } else { + $resp->headers[$k] = $v; + } + $lastk = $k; + } else if (preg_match("#^\s+(.*)$#", $l, $match)) { + // continuation line + if (is_null($lastk)) { + throw Exception("Bad format: initial whitespace in headers"); + } + $h =& $resp->headers[$lastk]; + if (is_array($h)) { + $n = count($h); + $h[$n-1] .= $match[1]; + } else { + $h .= $match[1]; + } + } + } + + return $resp; + } +} diff --git a/lib/default.php b/lib/default.php index f6cc4b725..7ec8558b0 100644 --- a/lib/default.php +++ b/lib/default.php @@ -228,6 +228,8 @@ $default = array('contentlimit' => null), 'message' => array('contentlimit' => null), + 'http' => + array('client' => 'curl'), // XXX: should this be the default? 'location' => array('namespace' => 1), // 1 = geonames, 2 = Yahoo Where on Earth ); diff --git a/lib/httpclient.php b/lib/httpclient.php index ee894e983..f16e31e10 100644 --- a/lib/httpclient.php +++ b/lib/httpclient.php @@ -31,9 +31,6 @@ if (!defined('STATUSNET')) { exit(1); } -require_once 'HTTP/Request2.php'; -require_once 'HTTP/Request2/Response.php'; - /** * Useful structure for HTTP responses * @@ -41,42 +38,18 @@ require_once 'HTTP/Request2/Response.php'; * ways of doing them. This class hides the specifics of what underlying * library (curl or PHP-HTTP or whatever) that's used. * - * This extends the HTTP_Request2_Response class with methods to get info - * about any followed redirects. - * * @category HTTP - * @package StatusNet - * @author Evan Prodromou - * @author Brion Vibber - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://status.net/ + * @package StatusNet + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ */ -class HTTPResponse extends HTTP_Request2_Response -{ - function __construct(HTTP_Request2_Response $response, $url, $redirects=0) - { - foreach (get_object_vars($response) as $key => $val) { - $this->$key = $val; - } - $this->url = strval($url); - $this->redirectCount = intval($redirects); - } - - /** - * Get the count of redirects that have been followed, if any. - * @return int - */ - function getRedirectCount() { - return $this->redirectCount; - } - /** - * Gets the final target URL, after any redirects have been followed. - * @return string URL - */ - function getUrl() { - return $this->url; - } +class HTTPResponse +{ + public $code = null; + public $headers = array(); + public $body = null; } /** @@ -86,133 +59,64 @@ class HTTPResponse extends HTTP_Request2_Response * ways of doing them. This class hides the specifics of what underlying * library (curl or PHP-HTTP or whatever) that's used. * - * This extends the PEAR HTTP_Request2 package: - * - sends StatusNet-specific User-Agent header - * - 'follow_redirects' config option, defaulting off - * - 'max_redirs' config option, defaulting to 10 - * - extended response class adds getRedirectCount() and getUrl() methods - * - get() and post() convenience functions return body content directly - * * @category HTTP * @package StatusNet * @author Evan Prodromou - * @author Brion Vibber * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ */ -class HTTPClient extends HTTP_Request2 +class HTTPClient { + static $_client = null; - function __construct($url=null, $method=self::METHOD_GET, $config=array()) + static function start() { - $this->config['max_redirs'] = 10; - $this->config['follow_redirects'] = false; - parent::__construct($url, $method, $config); - $this->setHeader('User-Agent', $this->userAgent()); + if (!is_null(self::$_client)) { + return self::$_client; + } + + $type = common_config('http', 'client'); + + switch ($type) { + case 'curl': + self::$_client = new CurlClient(); + break; + default: + throw new Exception("Unknown HTTP client type '$type'"); + break; + } + + return self::$_client; } - /** - * Convenience function to run a get request and return the response body. - * Use when you don't need to get into details of the response. - * - * @return mixed string on success, false on failure - */ - function get() + function head($url, $headers) { - $this->setMethod(self::METHOD_GET); - return $this->doRequest(); + throw new Exception("HEAD method unimplemented"); } - /** - * Convenience function to post form data and return the response body. - * Use when you don't need to get into details of the response. - * - * @param array associative array of form data to submit - * @return mixed string on success, false on failure - */ - public function post($data=array()) + function get($url, $headers) { - $this->setMethod(self::METHOD_POST); - if ($data) { - $this->addPostParameter($data); - } - return $this->doRequest(); + throw new Exception("GET method unimplemented"); } - /** - * @return mixed string on success, false on failure - */ - protected function doRequest() + function post($url, $headers, $body) { - try { - $response = $this->send(); - $code = $response->getStatus(); - if (($code < 200) || ($code >= 400)) { - return false; - } - return $response->getBody(); - } catch (HTTP_Request2_Exception $e) { - $this->log(LOG_ERR, $e->getMessage()); - return false; - } + throw new Exception("POST method unimplemented"); } - - protected function log($level, $detail) { - $method = $this->getMethod(); - $url = $this->getUrl(); - common_log($level, __CLASS__ . ": HTTP $method $url - $detail"); + + function put($url, $headers, $body) + { + throw new Exception("PUT method unimplemented"); } - /** - * Pulls up StatusNet's customized user-agent string, so services - * we hit can track down the responsible software. - */ - function userAgent() + function delete($url, $headers) { - return "StatusNet/".STATUSNET_VERSION." (".STATUSNET_CODENAME.")"; + throw new Exception("DELETE method unimplemented"); } - function send() + function userAgent() { - $maxRedirs = intval($this->config['max_redirs']); - if (empty($this->config['follow_redirects'])) { - $maxRedirs = 0; - } - $redirs = 0; - do { - try { - $response = parent::send(); - } catch (HTTP_Request2_Exception $e) { - $this->log(LOG_ERR, $e->getMessage()); - throw $e; - } - $code = $response->getStatus(); - if ($code >= 200 && $code < 300) { - $reason = $response->getReasonPhrase(); - $this->log(LOG_INFO, "$code $reason"); - } elseif ($code >= 300 && $code < 400) { - $url = $this->getUrl(); - $target = $response->getHeader('Location'); - - if (++$redirs >= $maxRedirs) { - common_log(LOG_ERR, __CLASS__ . ": Too many redirects: skipping $code redirect from $url to $target"); - break; - } - try { - $this->setUrl($target); - $this->setHeader('Referer', $url); - common_log(LOG_INFO, __CLASS__ . ": Following $code redirect from $url to $target"); - continue; - } catch (HTTP_Request2_Exception $e) { - common_log(LOG_ERR, __CLASS__ . ": Invalid $code redirect from $url to $target"); - } - } else { - $reason = $response->getReasonPhrase(); - $this->log(LOG_ERR, "$code $reason"); - } - break; - } while ($maxRedirs); - return new HTTPResponse($response, $this->getUrl(), $redirs); + return "StatusNet/".STATUSNET_VERSION." (".STATUSNET_CODENAME.")"; } } diff --git a/lib/oauthclient.php b/lib/oauthclient.php index 1a86e2460..f1827726e 100644 --- a/lib/oauthclient.php +++ b/lib/oauthclient.php @@ -43,7 +43,7 @@ require_once 'OAuth.php'; * @link http://status.net/ * */ -class OAuthClientException extends Exception +class OAuthClientCurlException extends Exception { } @@ -97,14 +97,9 @@ class OAuthClient function getRequestToken($url) { $response = $this->oAuthGet($url); - $arr = array(); - parse_str($response, $arr); - if (isset($arr['oauth_token']) && isset($arr['oauth_token_secret'])) { - $token = new OAuthToken($arr['oauth_token'], @$arr['oauth_token_secret']); - return $token; - } else { - throw new OAuthClientException(); - } + parse_str($response); + $token = new OAuthToken($oauth_token, $oauth_token_secret); + return $token; } /** @@ -182,7 +177,7 @@ class OAuthClient } /** - * Make a HTTP request. + * Make a HTTP request using cURL. * * @param string $url Where to make the * @param array $params post parameters @@ -191,32 +186,40 @@ class OAuthClient */ function httpRequest($url, $params = null) { - $request = new HTTPClient($url); - $request->setConfig(array( - 'connect_timeout' => 120, - 'timeout' => 120, - 'follow_redirects' => true, - 'ssl_verify_peer' => false, - )); - - // Twitter is strict about accepting invalid "Expect" headers - $request->setHeader('Expect', ''); + $options = array( + CURLOPT_RETURNTRANSFER => true, + CURLOPT_FAILONERROR => true, + CURLOPT_HEADER => false, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_USERAGENT => 'StatusNet', + CURLOPT_CONNECTTIMEOUT => 120, + CURLOPT_TIMEOUT => 120, + CURLOPT_HTTPAUTH => CURLAUTH_ANY, + CURLOPT_SSL_VERIFYPEER => false, + + // Twitter is strict about accepting invalid "Expect" headers + + CURLOPT_HTTPHEADER => array('Expect:') + ); if (isset($params)) { - $request->setMethod(HTTP_Request2::METHOD_POST); - $request->setBody($params); + $options[CURLOPT_POST] = true; + $options[CURLOPT_POSTFIELDS] = $params; } - try { - $response = $request->send(); - $code = $response->getStatus(); - if ($code < 200 || $code >= 400) { - throw new OAuthClientException($response->getBody(), $code); - } - return $response->getBody(); - } catch (Exception $e) { - throw new OAuthClientException($e->getMessage(), $e->getCode()); + $ch = curl_init($url); + curl_setopt_array($ch, $options); + $response = curl_exec($ch); + + if ($response === false) { + $msg = curl_error($ch); + $code = curl_errno($ch); + throw new OAuthClientCurlException($msg, $code); } + + curl_close($ch); + + return $response; } } diff --git a/lib/ping.php b/lib/ping.php index 2797c1b2d..175bf8440 100644 --- a/lib/ping.php +++ b/lib/ping.php @@ -44,18 +44,20 @@ function ping_broadcast_notice($notice) { array('nickname' => $profile->nickname)), $tags)); - $request = new HTTPClient($notify_url, HTTP_Request2::METHOD_POST); - $request->setHeader('Content-Type', 'text/xml'); - $request->setBody($req); - $httpResponse = $request->send(); + $context = stream_context_create(array('http' => array('method' => "POST", + 'header' => + "Content-Type: text/xml\r\n". + "User-Agent: StatusNet/".STATUSNET_VERSION."\r\n", + 'content' => $req))); + $file = file_get_contents($notify_url, false, $context); - if (!$httpResponse || mb_strlen($httpResponse->getBody()) == 0) { + if ($file === false || mb_strlen($file) == 0) { common_log(LOG_WARNING, "XML-RPC empty results for ping ($notify_url, $notice->id) "); continue; } - $response = xmlrpc_decode($httpResponse->getBody()); + $response = xmlrpc_decode($file); if (is_array($response) && xmlrpc_is_fault($response)) { common_log(LOG_WARNING, diff --git a/lib/snapshot.php b/lib/snapshot.php index 6829e8a75..ede846e5b 100644 --- a/lib/snapshot.php +++ b/lib/snapshot.php @@ -172,11 +172,26 @@ class Snapshot { // XXX: Use OICU2 and OAuth to make authorized requests + $postdata = http_build_query($this->stats); + + $opts = + array('http' => + array( + 'method' => 'POST', + 'header' => 'Content-type: '. + 'application/x-www-form-urlencoded', + 'content' => $postdata, + 'user_agent' => 'StatusNet/'.STATUSNET_VERSION + ) + ); + + $context = stream_context_create($opts); + $reporturl = common_config('snapshot', 'reporturl'); - $request = new HTTPClient($reporturl, HTTP_Request2::METHOD_POST); - $request->addPostParameter($this->stats); - $request->send(); + $result = @file_get_contents($reporturl, false, $context); + + return $result; } /** diff --git a/plugins/BlogspamNetPlugin.php b/plugins/BlogspamNetPlugin.php index 3bdc73556..c14569746 100644 --- a/plugins/BlogspamNetPlugin.php +++ b/plugins/BlogspamNetPlugin.php @@ -22,7 +22,6 @@ * @category Plugin * @package StatusNet * @author Evan Prodromou - * @author Brion Vibber * @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/ @@ -70,14 +69,14 @@ class BlogspamNetPlugin extends Plugin { $args = $this->testArgs($notice); common_debug("Blogspamnet args = " . print_r($args, TRUE)); - $requestBody = xmlrpc_encode_request('testComment', array($args)); - - $request = new HTTPClient($this->baseUrl, HTTP_Request2::METHOD_POST); - $request->addHeader('Content-Type: text/xml'); - $request->setBody($requestBody); - $httpResponse = $request->send(); - - $response = xmlrpc_decode($httpResponse->getBody()); + $request = xmlrpc_encode_request('testComment', array($args)); + $context = stream_context_create(array('http' => array('method' => "POST", + 'header' => + "Content-Type: text/xml\r\n". + "User-Agent: " . $this->userAgent(), + 'content' => $request))); + $file = file_get_contents($this->baseUrl, false, $context); + $response = xmlrpc_decode($file); if (xmlrpc_is_fault($response)) { throw new ServerException("$response[faultString] ($response[faultCode])", 500); } else { diff --git a/plugins/LinkbackPlugin.php b/plugins/LinkbackPlugin.php index 0513687e9..60f7a60c7 100644 --- a/plugins/LinkbackPlugin.php +++ b/plugins/LinkbackPlugin.php @@ -129,25 +129,27 @@ class LinkbackPlugin extends Plugin } } - $request = new HTTPClient($endpoint, 'POST'); - $request->setHeader('User-Agent', $this->userAgent()); - $request->setHeader('Content-Type', 'text/xml'); - $request->setBody(xmlrpc_encode_request('pingback.ping', $args)); - try { - $response = $request->send(); - } catch (HTTP_Request2_Exception $e) { + $request = xmlrpc_encode_request('pingback.ping', $args); + $context = stream_context_create(array('http' => array('method' => "POST", + 'header' => + "Content-Type: text/xml\r\n". + "User-Agent: " . $this->userAgent(), + 'content' => $request))); + $file = file_get_contents($endpoint, false, $context); + if (!$file) { common_log(LOG_WARNING, - "Pingback request failed for '$url' ($endpoint)"); - } - $response = xmlrpc_decode($response->getBody()); - if (xmlrpc_is_fault($response)) { - common_log(LOG_WARNING, - "Pingback error for '$url' ($endpoint): ". - "$response[faultString] ($response[faultCode])"); + "Pingback request failed for '$url' ($endpoint)"); } else { - common_log(LOG_INFO, - "Pingback success for '$url' ($endpoint): ". - "'$response'"); + $response = xmlrpc_decode($file); + if (xmlrpc_is_fault($response)) { + common_log(LOG_WARNING, + "Pingback error for '$url' ($endpoint): ". + "$response[faultString] ($response[faultCode])"); + } else { + common_log(LOG_INFO, + "Pingback success for '$url' ($endpoint): ". + "'$response'"); + } } } diff --git a/plugins/SimpleUrl/SimpleUrlPlugin.php b/plugins/SimpleUrl/SimpleUrlPlugin.php index d59d63e47..82d772048 100644 --- a/plugins/SimpleUrl/SimpleUrlPlugin.php +++ b/plugins/SimpleUrl/SimpleUrlPlugin.php @@ -65,6 +65,15 @@ class SimpleUrlPlugin extends Plugin class SimpleUrl extends ShortUrlApi { protected function shorten_imp($url) { - return $this->http_get($url); + $curlh = curl_init(); + curl_setopt($curlh, CURLOPT_CONNECTTIMEOUT, 20); // # seconds to wait + curl_setopt($curlh, CURLOPT_USERAGENT, 'StatusNet'); + curl_setopt($curlh, CURLOPT_RETURNTRANSFER, true); + + curl_setopt($curlh, CURLOPT_URL, $this->service_url.urlencode($url)); + $short_url = curl_exec($curlh); + + curl_close($curlh); + return $short_url; } } diff --git a/plugins/TwitterBridge/daemons/synctwitterfriends.php b/plugins/TwitterBridge/daemons/synctwitterfriends.php index 671e3c7af..ed2bf48a2 100755 --- a/plugins/TwitterBridge/daemons/synctwitterfriends.php +++ b/plugins/TwitterBridge/daemons/synctwitterfriends.php @@ -152,8 +152,8 @@ class SyncTwitterFriendsDaemon extends ParallelizingDaemon $friends_ids = $client->friendsIds(); } catch (Exception $e) { common_log(LOG_WARNING, $this->name() . - ' - error getting friend ids: ' . - $e->getMessage()); + ' - cURL error getting friend ids ' . + $e->getCode() . ' - ' . $e->getMessage()); return $friends; } diff --git a/plugins/TwitterBridge/daemons/twitterstatusfetcher.php b/plugins/TwitterBridge/daemons/twitterstatusfetcher.php index 6c91b2860..81bbbc7c5 100755 --- a/plugins/TwitterBridge/daemons/twitterstatusfetcher.php +++ b/plugins/TwitterBridge/daemons/twitterstatusfetcher.php @@ -109,16 +109,12 @@ class TwitterStatusFetcher extends ParallelizingDaemon $flink->find(); $flinks = array(); - common_log(LOG_INFO, "hello"); while ($flink->fetch()) { if (($flink->noticesync & FOREIGN_NOTICE_RECV) == FOREIGN_NOTICE_RECV) { $flinks[] = clone($flink); - common_log(LOG_INFO, "sync: foreign id $flink->foreign_id"); - } else { - common_log(LOG_INFO, "nothing to sync"); } } @@ -519,34 +515,31 @@ class TwitterStatusFetcher extends ParallelizingDaemon return $id; } - /** - * Fetch a remote avatar image and save to local storage. - * - * @param string $url avatar source URL - * @param string $filename bare local filename for download - * @return bool true on success, false on failure - */ function fetchAvatar($url, $filename) { - common_debug($this->name() . " - Fetching Twitter avatar: $url"); + $avatarfile = Avatar::path($filename); - $request = new HTTPClient($url, 'GET', array( - 'follow_redirects' => true, - )); - $data = $request->get(); - if ($data) { - $avatarfile = Avatar::path($filename); - $ok = file_put_contents($avatarfile, $data); - if (!$ok) { - common_log(LOG_WARNING, $this->name() . - " - Couldn't open file $filename"); - return false; - } - } else { + $out = fopen($avatarfile, 'wb'); + if (!$out) { + common_log(LOG_WARNING, $this->name() . + " - Couldn't open file $filename"); return false; } - return true; + common_debug($this->name() . " - Fetching Twitter avatar: $url"); + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_FILE, $out); + curl_setopt($ch, CURLOPT_BINARYTRANSFER, true); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0); + $result = curl_exec($ch); + curl_close($ch); + + fclose($out); + + return $result; } } diff --git a/plugins/TwitterBridge/twitter.php b/plugins/TwitterBridge/twitter.php index 3c6803e49..1a5248a9b 100644 --- a/plugins/TwitterBridge/twitter.php +++ b/plugins/TwitterBridge/twitter.php @@ -215,7 +215,7 @@ function broadcast_basicauth($notice, $flink) try { $status = $client->statusesUpdate($statustxt); - } catch (HTTP_Request2_Exception $e) { + } catch (BasicAuthCurlException $e) { return process_error($e, $flink); } diff --git a/plugins/TwitterBridge/twitterauthorization.php b/plugins/TwitterBridge/twitterauthorization.php index f1daefab1..2a93ff13e 100644 --- a/plugins/TwitterBridge/twitterauthorization.php +++ b/plugins/TwitterBridge/twitterauthorization.php @@ -125,7 +125,7 @@ class TwitterauthorizationAction extends Action $auth_link = $client->getAuthorizeLink($req_tok); - } catch (OAuthClientException $e) { + } 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.')); diff --git a/plugins/TwitterBridge/twitterbasicauthclient.php b/plugins/TwitterBridge/twitterbasicauthclient.php index e4cae7373..1040d72fb 100644 --- a/plugins/TwitterBridge/twitterbasicauthclient.php +++ b/plugins/TwitterBridge/twitterbasicauthclient.php @@ -31,6 +31,26 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } +/** + * Exception wrapper for cURL errors + * + * @category Integration + * @package StatusNet + * @author Adrian Lang + * @author Brenda Wallace + * @author Craig Andrews + * @author Dan Moore + * @author Evan Prodromou + * @author mEDI + * @author Sarven Capadisli + * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + * + */ +class BasicAuthCurlException extends Exception +{ +} + /** * Class for talking to the Twitter API with HTTP Basic Auth. * @@ -178,27 +198,45 @@ class TwitterBasicAuthClient */ function httpRequest($url, $params = null, $auth = true) { - $request = new HTTPClient($url, 'GET', array( - 'follow_redirects' => true, - 'connect_timeout' => 120, - 'timeout' => 120, - 'ssl_verifypeer' => false, - )); - - // Twitter is strict about accepting invalid "Expect" headers - $request->setHeader('Expect', ''); + $options = array( + CURLOPT_RETURNTRANSFER => true, + CURLOPT_FAILONERROR => true, + CURLOPT_HEADER => false, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_USERAGENT => 'StatusNet', + CURLOPT_CONNECTTIMEOUT => 120, + CURLOPT_TIMEOUT => 120, + CURLOPT_HTTPAUTH => CURLAUTH_ANY, + CURLOPT_SSL_VERIFYPEER => false, + + // Twitter is strict about accepting invalid "Expect" headers + + CURLOPT_HTTPHEADER => array('Expect:') + ); if (isset($params)) { - $request->setMethod('POST'); - $request->addPostParameter($params); + $options[CURLOPT_POST] = true; + $options[CURLOPT_POSTFIELDS] = $params; } if ($auth) { - $request->setAuth($this->screen_name, $this->password); + $options[CURLOPT_USERPWD] = $this->screen_name . + ':' . $this->password; } - $response = $request->send(); - return $response->getBody(); + $ch = curl_init($url); + curl_setopt_array($ch, $options); + $response = curl_exec($ch); + + if ($response === false) { + $msg = curl_error($ch); + $code = curl_errno($ch); + throw new BasicAuthCurlException($msg, $code); + } + + curl_close($ch); + + return $response; } } diff --git a/plugins/WikiHashtagsPlugin.php b/plugins/WikiHashtagsPlugin.php index a9e675f5c..0c5649aa4 100644 --- a/plugins/WikiHashtagsPlugin.php +++ b/plugins/WikiHashtagsPlugin.php @@ -68,8 +68,10 @@ class WikiHashtagsPlugin extends Plugin $editurl = sprintf('http://hashtags.wikia.com/index.php?title=%s&action=edit', urlencode($tag)); - $request = new HTTPClient($url); - $html = $request->get(); + $context = stream_context_create(array('http' => array('method' => "GET", + 'header' => + "User-Agent: " . $this->userAgent()))); + $html = @file_get_contents($url, false, $context); $action->elementStart('div', array('id' => 'wikihashtags', 'class' => 'section')); @@ -98,4 +100,10 @@ class WikiHashtagsPlugin extends Plugin return true; } + + function userAgent() + { + return 'WikiHashtagsPlugin/'.WIKIHASHTAGSPLUGIN_VERSION . + ' StatusNet/' . STATUSNET_VERSION; + } } diff --git a/scripts/enjitqueuehandler.php b/scripts/enjitqueuehandler.php index 214cc02b4..08f733b07 100755 --- a/scripts/enjitqueuehandler.php +++ b/scripts/enjitqueuehandler.php @@ -46,8 +46,8 @@ class EnjitQueueHandler extends QueueHandler function start() { - $this->log(LOG_INFO, "Starting EnjitQueueHandler"); - $this->log(LOG_INFO, "Broadcasting to ".common_config('enjit', 'apiurl')); + $this->log(LOG_INFO, "Starting EnjitQueueHandler"); + $this->log(LOG_INFO, "Broadcasting to ".common_config('enjit', 'apiurl')); return true; } @@ -56,16 +56,16 @@ class EnjitQueueHandler extends QueueHandler $profile = Profile::staticGet($notice->profile_id); - $this->log(LOG_INFO, "Posting Notice ".$notice->id." from ".$profile->nickname); + $this->log(LOG_INFO, "Posting Notice ".$notice->id." from ".$profile->nickname); - if ( ! $notice->is_local ) { - $this->log(LOG_INFO, "Skipping remote notice"); - return "skipped"; - } + if ( ! $notice->is_local ) { + $this->log(LOG_INFO, "Skipping remote notice"); + return "skipped"; + } - # - # Build an Atom message from the notice - # + # + # Build an Atom message from the notice + # $noticeurl = common_local_url('shownotice', array('notice' => $notice->id)); $msg = $profile->nickname . ': ' . $notice->content; @@ -86,20 +86,36 @@ class EnjitQueueHandler extends QueueHandler $atom .= "".common_date_w3dtf($notice->modified)."\n"; $atom .= "\n"; - $url = common_config('enjit', 'apiurl') . "/submit/". common_config('enjit','apikey'); - $data = array( - 'msg' => $atom, - ); - - # - # POST the message to $config['enjit']['apiurl'] - # - $request = new HTTPClient($url, HTTP_Request2::METHOD_POST); - $request->addPostFields($data); - $response = $request->send(); - - // @fixme handle_notice() is supposed to return true/false. Somethin' funky? - return $response->getStatus(); + $url = common_config('enjit', 'apiurl') . "/submit/". common_config('enjit','apikey'); + $data = "msg=$atom"; + + # + # POST the message to $config['enjit']['apiurl'] + # + $ch = curl_init(); + + curl_setopt($ch, CURLOPT_URL, $url); + + curl_setopt($ch, CURLOPT_HEADER, 1); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_POST, 1) ; + curl_setopt($ch, CURLOPT_POSTFIELDS, $data); + + # SSL and Debugging options + # + # curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + # curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + # curl_setopt($ch, CURLOPT_VERBOSE, 1); + + $result = curl_exec($ch); + + $code = curl_getinfo($ch, CURLINFO_HTTP_CODE ); + + $this->log(LOG_INFO, "Response Code: $code"); + + curl_close($ch); + + return $code; } } -- cgit v1.2.3-54-g00ecf From 5581143bee602dbd5417f532f2b483e58d0a4269 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 28 Oct 2009 15:29:20 -0400 Subject: Rebuilt HTTPClient class as an extension of PEAR HTTP_Request2 package, adding redirect handling and convenience functions. Caching support will be added in future work after unit tests have been added. * extlib: add PEAR HTTP_Request2 0.4.1 alpha * extlib: update PEAR Net_URL2 to 0.3.0 beta for HTTP_Request2 compatibility * moved direct usage of CURL and file_get_contents to HTTPClient class, excluding external-sourced libraries * adapted GeonamesPlugin for new HTTPResponse interface Note some plugins haven't been fully tested yet. --- classes/File_redirection.php | 68 +- extlib/HTTP/Request2.php | 844 ++++++++++++++++++ extlib/HTTP/Request2/Adapter.php | 152 ++++ extlib/HTTP/Request2/Adapter/Curl.php | 383 ++++++++ extlib/HTTP/Request2/Adapter/Mock.php | 171 ++++ extlib/HTTP/Request2/Adapter/Socket.php | 971 +++++++++++++++++++++ extlib/HTTP/Request2/Exception.php | 62 ++ extlib/HTTP/Request2/MultipartBody.php | 274 ++++++ extlib/HTTP/Request2/Observer/Log.php | 215 +++++ extlib/HTTP/Request2/Response.php | 549 ++++++++++++ extlib/Net/URL2.php | 471 ++++++---- install.php | 7 + lib/Shorturl_api.php | 24 +- lib/curlclient.php | 179 ---- lib/default.php | 2 - lib/httpclient.php | 213 ++++- lib/oauthclient.php | 65 +- lib/ping.php | 12 +- lib/snapshot.php | 21 +- plugins/BlogspamNetPlugin.php | 15 +- plugins/GeonamesPlugin.php | 16 +- plugins/LilUrl/LilUrlPlugin.php | 5 +- plugins/LinkbackPlugin.php | 21 +- plugins/SimpleUrl/SimpleUrlPlugin.php | 11 +- .../TwitterBridge/daemons/synctwitterfriends.php | 4 +- .../TwitterBridge/daemons/twitterstatusfetcher.php | 43 +- plugins/TwitterBridge/twitter.php | 2 +- plugins/TwitterBridge/twitterauthorization.php | 2 +- plugins/TwitterBridge/twitterbasicauthclient.php | 68 +- plugins/WikiHashtagsPlugin.php | 15 +- scripts/enjitqueuehandler.php | 58 +- 31 files changed, 4275 insertions(+), 668 deletions(-) create mode 100644 extlib/HTTP/Request2.php create mode 100644 extlib/HTTP/Request2/Adapter.php create mode 100644 extlib/HTTP/Request2/Adapter/Curl.php create mode 100644 extlib/HTTP/Request2/Adapter/Mock.php create mode 100644 extlib/HTTP/Request2/Adapter/Socket.php create mode 100644 extlib/HTTP/Request2/Exception.php create mode 100644 extlib/HTTP/Request2/MultipartBody.php create mode 100644 extlib/HTTP/Request2/Observer/Log.php create mode 100644 extlib/HTTP/Request2/Response.php delete mode 100644 lib/curlclient.php (limited to 'plugins/TwitterBridge/daemons') diff --git a/classes/File_redirection.php b/classes/File_redirection.php index 79052bf7d..08a6e8d8b 100644 --- a/classes/File_redirection.php +++ b/classes/File_redirection.php @@ -47,18 +47,15 @@ class File_redirection extends Memcached_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE - function _commonCurl($url, $redirs) { - $curlh = curl_init(); - curl_setopt($curlh, CURLOPT_URL, $url); - curl_setopt($curlh, CURLOPT_AUTOREFERER, true); // # setup referer header when folowing redirects - curl_setopt($curlh, CURLOPT_CONNECTTIMEOUT, 10); // # seconds to wait - curl_setopt($curlh, CURLOPT_MAXREDIRS, $redirs); // # max number of http redirections to follow - curl_setopt($curlh, CURLOPT_USERAGENT, USER_AGENT); - curl_setopt($curlh, CURLOPT_FOLLOWLOCATION, true); // Follow redirects - curl_setopt($curlh, CURLOPT_RETURNTRANSFER, true); - curl_setopt($curlh, CURLOPT_FILETIME, true); - curl_setopt($curlh, CURLOPT_HEADER, true); // Include header in output - return $curlh; + static function _commonHttp($url, $redirs) { + $request = new HTTPClient($url); + $request->setConfig(array( + 'connect_timeout' => 10, // # seconds to wait + 'max_redirs' => $redirs, // # max number of http redirections to follow + 'follow_redirects' => true, // Follow redirects + 'store_body' => false, // We won't need body content here. + )); + return $request; } function _redirectWhere_imp($short_url, $redirs = 10, $protected = false) { @@ -82,32 +79,39 @@ class File_redirection extends Memcached_DataObject if(strpos($short_url,'://') === false){ return $short_url; } - $curlh = File_redirection::_commonCurl($short_url, $redirs); - // Don't include body in output - curl_setopt($curlh, CURLOPT_NOBODY, true); - curl_exec($curlh); - $info = curl_getinfo($curlh); - curl_close($curlh); - - if (405 == $info['http_code']) { - $curlh = File_redirection::_commonCurl($short_url, $redirs); - curl_exec($curlh); - $info = curl_getinfo($curlh); - curl_close($curlh); + try { + $request = self::_commonHttp($short_url, $redirs); + // Don't include body in output + $request->setMethod(HTTP_Request2::METHOD_HEAD); + $response = $request->send(); + + if (405 == $response->getStatus()) { + // Server doesn't support HEAD method? Can this really happen? + // We'll try again as a GET and ignore the response data. + $request = self::_commonHttp($short_url, $redirs); + $response = $request->send(); + } + } catch (Exception $e) { + // Invalid URL or failure to reach server + return $short_url; } - if (!empty($info['redirect_count']) && File::isProtected($info['url'])) { - return File_redirection::_redirectWhere_imp($short_url, $info['redirect_count'] - 1, true); + if ($response->getRedirectCount() && File::isProtected($response->getUrl())) { + // Bump back up the redirect chain until we find a non-protected URL + return self::_redirectWhere_imp($short_url, $response->getRedirectCount() - 1, true); } - $ret = array('code' => $info['http_code'] - , 'redirects' => $info['redirect_count'] - , 'url' => $info['url']); + $ret = array('code' => $response->getStatus() + , 'redirects' => $response->getRedirectCount() + , 'url' => $response->getUrl()); - if (!empty($info['content_type'])) $ret['type'] = $info['content_type']; + $type = $response->getHeader('Content-Type'); + if ($type) $ret['type'] = $type; if ($protected) $ret['protected'] = true; - if (!empty($info['download_content_length'])) $ret['size'] = $info['download_content_length']; - if (isset($info['filetime']) && ($info['filetime'] > 0)) $ret['time'] = $info['filetime']; + $size = $response->getHeader('Content-Length'); // @fixme bytes? + if ($size) $ret['size'] = $size; + $time = $response->getHeader('Last-Modified'); + if ($time) $ret['time'] = strtotime($time); return $ret; } diff --git a/extlib/HTTP/Request2.php b/extlib/HTTP/Request2.php new file mode 100644 index 000000000..e06bb86bc --- /dev/null +++ b/extlib/HTTP/Request2.php @@ -0,0 +1,844 @@ + + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Request2.php 278226 2009-04-03 21:32:48Z avb $ + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** + * A class representing an URL as per RFC 3986. + */ +require_once 'Net/URL2.php'; + +/** + * Exception class for HTTP_Request2 package + */ +require_once 'HTTP/Request2/Exception.php'; + +/** + * Class representing a HTTP request + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @version Release: 0.4.1 + * @link http://tools.ietf.org/html/rfc2616#section-5 + */ +class HTTP_Request2 implements SplSubject +{ + /**#@+ + * Constants for HTTP request methods + * + * @link http://tools.ietf.org/html/rfc2616#section-5.1.1 + */ + const METHOD_OPTIONS = 'OPTIONS'; + const METHOD_GET = 'GET'; + const METHOD_HEAD = 'HEAD'; + const METHOD_POST = 'POST'; + const METHOD_PUT = 'PUT'; + const METHOD_DELETE = 'DELETE'; + const METHOD_TRACE = 'TRACE'; + const METHOD_CONNECT = 'CONNECT'; + /**#@-*/ + + /**#@+ + * Constants for HTTP authentication schemes + * + * @link http://tools.ietf.org/html/rfc2617 + */ + const AUTH_BASIC = 'basic'; + const AUTH_DIGEST = 'digest'; + /**#@-*/ + + /** + * Regular expression used to check for invalid symbols in RFC 2616 tokens + * @link http://pear.php.net/bugs/bug.php?id=15630 + */ + const REGEXP_INVALID_TOKEN = '![\x00-\x1f\x7f-\xff()<>@,;:\\\\"/\[\]?={}\s]!'; + + /** + * Regular expression used to check for invalid symbols in cookie strings + * @link http://pear.php.net/bugs/bug.php?id=15630 + * @link http://cgi.netscape.com/newsref/std/cookie_spec.html + */ + const REGEXP_INVALID_COOKIE = '/[\s,;]/'; + + /** + * Fileinfo magic database resource + * @var resource + * @see detectMimeType() + */ + private static $_fileinfoDb; + + /** + * Observers attached to the request (instances of SplObserver) + * @var array + */ + protected $observers = array(); + + /** + * Request URL + * @var Net_URL2 + */ + protected $url; + + /** + * Request method + * @var string + */ + protected $method = self::METHOD_GET; + + /** + * Authentication data + * @var array + * @see getAuth() + */ + protected $auth; + + /** + * Request headers + * @var array + */ + protected $headers = array(); + + /** + * Configuration parameters + * @var array + * @see setConfig() + */ + protected $config = array( + 'adapter' => 'HTTP_Request2_Adapter_Socket', + 'connect_timeout' => 10, + 'timeout' => 0, + 'use_brackets' => true, + 'protocol_version' => '1.1', + 'buffer_size' => 16384, + 'store_body' => true, + + 'proxy_host' => '', + 'proxy_port' => '', + 'proxy_user' => '', + 'proxy_password' => '', + 'proxy_auth_scheme' => self::AUTH_BASIC, + + 'ssl_verify_peer' => true, + 'ssl_verify_host' => true, + 'ssl_cafile' => null, + 'ssl_capath' => null, + 'ssl_local_cert' => null, + 'ssl_passphrase' => null, + + 'digest_compat_ie' => false + ); + + /** + * Last event in request / response handling, intended for observers + * @var array + * @see getLastEvent() + */ + protected $lastEvent = array( + 'name' => 'start', + 'data' => null + ); + + /** + * Request body + * @var string|resource + * @see setBody() + */ + protected $body = ''; + + /** + * Array of POST parameters + * @var array + */ + protected $postParams = array(); + + /** + * Array of file uploads (for multipart/form-data POST requests) + * @var array + */ + protected $uploads = array(); + + /** + * Adapter used to perform actual HTTP request + * @var HTTP_Request2_Adapter + */ + protected $adapter; + + + /** + * Constructor. Can set request URL, method and configuration array. + * + * Also sets a default value for User-Agent header. + * + * @param string|Net_Url2 Request URL + * @param string Request method + * @param array Configuration for this Request instance + */ + public function __construct($url = null, $method = self::METHOD_GET, array $config = array()) + { + if (!empty($url)) { + $this->setUrl($url); + } + if (!empty($method)) { + $this->setMethod($method); + } + $this->setConfig($config); + $this->setHeader('user-agent', 'HTTP_Request2/0.4.1 ' . + '(http://pear.php.net/package/http_request2) ' . + 'PHP/' . phpversion()); + } + + /** + * Sets the URL for this request + * + * If the URL has userinfo part (username & password) these will be removed + * and converted to auth data. If the URL does not have a path component, + * that will be set to '/'. + * + * @param string|Net_URL2 Request URL + * @return HTTP_Request2 + * @throws HTTP_Request2_Exception + */ + public function setUrl($url) + { + if (is_string($url)) { + $url = new Net_URL2($url); + } + if (!$url instanceof Net_URL2) { + throw new HTTP_Request2_Exception('Parameter is not a valid HTTP URL'); + } + // URL contains username / password? + if ($url->getUserinfo()) { + $username = $url->getUser(); + $password = $url->getPassword(); + $this->setAuth(rawurldecode($username), $password? rawurldecode($password): ''); + $url->setUserinfo(''); + } + if ('' == $url->getPath()) { + $url->setPath('/'); + } + $this->url = $url; + + return $this; + } + + /** + * Returns the request URL + * + * @return Net_URL2 + */ + public function getUrl() + { + return $this->url; + } + + /** + * Sets the request method + * + * @param string + * @return HTTP_Request2 + * @throws HTTP_Request2_Exception if the method name is invalid + */ + public function setMethod($method) + { + // Method name should be a token: http://tools.ietf.org/html/rfc2616#section-5.1.1 + if (preg_match(self::REGEXP_INVALID_TOKEN, $method)) { + throw new HTTP_Request2_Exception("Invalid request method '{$method}'"); + } + $this->method = $method; + + return $this; + } + + /** + * Returns the request method + * + * @return string + */ + public function getMethod() + { + return $this->method; + } + + /** + * Sets the configuration parameter(s) + * + * The following parameters are available: + *
    + *
  • 'adapter' - adapter to use (string)
  • + *
  • 'connect_timeout' - Connection timeout in seconds (integer)
  • + *
  • 'timeout' - Total number of seconds a request can take. + * Use 0 for no limit, should be greater than + * 'connect_timeout' if set (integer)
  • + *
  • 'use_brackets' - Whether to append [] to array variable names (bool)
  • + *
  • 'protocol_version' - HTTP Version to use, '1.0' or '1.1' (string)
  • + *
  • 'buffer_size' - Buffer size to use for reading and writing (int)
  • + *
  • 'store_body' - Whether to store response body in response object. + * Set to false if receiving a huge response and + * using an Observer to save it (boolean)
  • + *
  • 'proxy_host' - Proxy server host (string)
  • + *
  • 'proxy_port' - Proxy server port (integer)
  • + *
  • 'proxy_user' - Proxy auth username (string)
  • + *
  • 'proxy_password' - Proxy auth password (string)
  • + *
  • 'proxy_auth_scheme' - Proxy auth scheme, one of HTTP_Request2::AUTH_* constants (string)
  • + *
  • 'ssl_verify_peer' - Whether to verify peer's SSL certificate (bool)
  • + *
  • 'ssl_verify_host' - Whether to check that Common Name in SSL + * certificate matches host name (bool)
  • + *
  • 'ssl_cafile' - Cerificate Authority file to verify the peer + * with (use with 'ssl_verify_peer') (string)
  • + *
  • 'ssl_capath' - Directory holding multiple Certificate + * Authority files (string)
  • + *
  • 'ssl_local_cert' - Name of a file containing local cerificate (string)
  • + *
  • 'ssl_passphrase' - Passphrase with which local certificate + * was encoded (string)
  • + *
  • 'digest_compat_ie' - Whether to imitate behaviour of MSIE 5 and 6 + * in using URL without query string in digest + * authentication (boolean)
  • + *
+ * + * @param string|array configuration parameter name or array + * ('parameter name' => 'parameter value') + * @param mixed parameter value if $nameOrConfig is not an array + * @return HTTP_Request2 + * @throws HTTP_Request2_Exception If the parameter is unknown + */ + public function setConfig($nameOrConfig, $value = null) + { + if (is_array($nameOrConfig)) { + foreach ($nameOrConfig as $name => $value) { + $this->setConfig($name, $value); + } + + } else { + if (!array_key_exists($nameOrConfig, $this->config)) { + throw new HTTP_Request2_Exception( + "Unknown configuration parameter '{$nameOrConfig}'" + ); + } + $this->config[$nameOrConfig] = $value; + } + + return $this; + } + + /** + * Returns the value(s) of the configuration parameter(s) + * + * @param string parameter name + * @return mixed value of $name parameter, array of all configuration + * parameters if $name is not given + * @throws HTTP_Request2_Exception If the parameter is unknown + */ + public function getConfig($name = null) + { + if (null === $name) { + return $this->config; + } elseif (!array_key_exists($name, $this->config)) { + throw new HTTP_Request2_Exception( + "Unknown configuration parameter '{$name}'" + ); + } + return $this->config[$name]; + } + + /** + * Sets the autentification data + * + * @param string user name + * @param string password + * @param string authentication scheme + * @return HTTP_Request2 + */ + public function setAuth($user, $password = '', $scheme = self::AUTH_BASIC) + { + if (empty($user)) { + $this->auth = null; + } else { + $this->auth = array( + 'user' => (string)$user, + 'password' => (string)$password, + 'scheme' => $scheme + ); + } + + return $this; + } + + /** + * Returns the authentication data + * + * The array has the keys 'user', 'password' and 'scheme', where 'scheme' + * is one of the HTTP_Request2::AUTH_* constants. + * + * @return array + */ + public function getAuth() + { + return $this->auth; + } + + /** + * Sets request header(s) + * + * The first parameter may be either a full header string 'header: value' or + * header name. In the former case $value parameter is ignored, in the latter + * the header's value will either be set to $value or the header will be + * removed if $value is null. The first parameter can also be an array of + * headers, in that case method will be called recursively. + * + * Note that headers are treated case insensitively as per RFC 2616. + * + * + * $req->setHeader('Foo: Bar'); // sets the value of 'Foo' header to 'Bar' + * $req->setHeader('FoO', 'Baz'); // sets the value of 'Foo' header to 'Baz' + * $req->setHeader(array('foo' => 'Quux')); // sets the value of 'Foo' header to 'Quux' + * $req->setHeader('FOO'); // removes 'Foo' header from request + * + * + * @param string|array header name, header string ('Header: value') + * or an array of headers + * @param string|null header value, header will be removed if null + * @return HTTP_Request2 + * @throws HTTP_Request2_Exception + */ + public function setHeader($name, $value = null) + { + if (is_array($name)) { + foreach ($name as $k => $v) { + if (is_string($k)) { + $this->setHeader($k, $v); + } else { + $this->setHeader($v); + } + } + } else { + if (null === $value && strpos($name, ':')) { + list($name, $value) = array_map('trim', explode(':', $name, 2)); + } + // Header name should be a token: http://tools.ietf.org/html/rfc2616#section-4.2 + if (preg_match(self::REGEXP_INVALID_TOKEN, $name)) { + throw new HTTP_Request2_Exception("Invalid header name '{$name}'"); + } + // Header names are case insensitive anyway + $name = strtolower($name); + if (null === $value) { + unset($this->headers[$name]); + } else { + $this->headers[$name] = $value; + } + } + + return $this; + } + + /** + * Returns the request headers + * + * The array is of the form ('header name' => 'header value'), header names + * are lowercased + * + * @return array + */ + public function getHeaders() + { + return $this->headers; + } + + /** + * Appends a cookie to "Cookie:" header + * + * @param string cookie name + * @param string cookie value + * @return HTTP_Request2 + * @throws HTTP_Request2_Exception + */ + public function addCookie($name, $value) + { + $cookie = $name . '=' . $value; + if (preg_match(self::REGEXP_INVALID_COOKIE, $cookie)) { + throw new HTTP_Request2_Exception("Invalid cookie: '{$cookie}'"); + } + $cookies = empty($this->headers['cookie'])? '': $this->headers['cookie'] . '; '; + $this->setHeader('cookie', $cookies . $cookie); + + return $this; + } + + /** + * Sets the request body + * + * @param string Either a string with the body or filename containing body + * @param bool Whether first parameter is a filename + * @return HTTP_Request2 + * @throws HTTP_Request2_Exception + */ + public function setBody($body, $isFilename = false) + { + if (!$isFilename) { + $this->body = (string)$body; + } else { + if (!($fp = @fopen($body, 'rb'))) { + throw new HTTP_Request2_Exception("Cannot open file {$body}"); + } + $this->body = $fp; + if (empty($this->headers['content-type'])) { + $this->setHeader('content-type', self::detectMimeType($body)); + } + } + + return $this; + } + + /** + * Returns the request body + * + * @return string|resource|HTTP_Request2_MultipartBody + */ + public function getBody() + { + if (self::METHOD_POST == $this->method && + (!empty($this->postParams) || !empty($this->uploads)) + ) { + if ('application/x-www-form-urlencoded' == $this->headers['content-type']) { + $body = http_build_query($this->postParams, '', '&'); + if (!$this->getConfig('use_brackets')) { + $body = preg_replace('/%5B\d+%5D=/', '=', $body); + } + // support RFC 3986 by not encoding '~' symbol (request #15368) + return str_replace('%7E', '~', $body); + + } elseif ('multipart/form-data' == $this->headers['content-type']) { + require_once 'HTTP/Request2/MultipartBody.php'; + return new HTTP_Request2_MultipartBody( + $this->postParams, $this->uploads, $this->getConfig('use_brackets') + ); + } + } + return $this->body; + } + + /** + * Adds a file to form-based file upload + * + * Used to emulate file upload via a HTML form. The method also sets + * Content-Type of HTTP request to 'multipart/form-data'. + * + * If you just want to send the contents of a file as the body of HTTP + * request you should use setBody() method. + * + * @param string name of file-upload field + * @param mixed full name of local file + * @param string filename to send in the request + * @param string content-type of file being uploaded + * @return HTTP_Request2 + * @throws HTTP_Request2_Exception + */ + public function addUpload($fieldName, $filename, $sendFilename = null, + $contentType = null) + { + if (!is_array($filename)) { + if (!($fp = @fopen($filename, 'rb'))) { + throw new HTTP_Request2_Exception("Cannot open file {$filename}"); + } + $this->uploads[$fieldName] = array( + 'fp' => $fp, + 'filename' => empty($sendFilename)? basename($filename): $sendFilename, + 'size' => filesize($filename), + 'type' => empty($contentType)? self::detectMimeType($filename): $contentType + ); + } else { + $fps = $names = $sizes = $types = array(); + foreach ($filename as $f) { + if (!is_array($f)) { + $f = array($f); + } + if (!($fp = @fopen($f[0], 'rb'))) { + throw new HTTP_Request2_Exception("Cannot open file {$f[0]}"); + } + $fps[] = $fp; + $names[] = empty($f[1])? basename($f[0]): $f[1]; + $sizes[] = filesize($f[0]); + $types[] = empty($f[2])? self::detectMimeType($f[0]): $f[2]; + } + $this->uploads[$fieldName] = array( + 'fp' => $fps, 'filename' => $names, 'size' => $sizes, 'type' => $types + ); + } + if (empty($this->headers['content-type']) || + 'application/x-www-form-urlencoded' == $this->headers['content-type'] + ) { + $this->setHeader('content-type', 'multipart/form-data'); + } + + return $this; + } + + /** + * Adds POST parameter(s) to the request. + * + * @param string|array parameter name or array ('name' => 'value') + * @param mixed parameter value (can be an array) + * @return HTTP_Request2 + */ + public function addPostParameter($name, $value = null) + { + if (!is_array($name)) { + $this->postParams[$name] = $value; + } else { + foreach ($name as $k => $v) { + $this->addPostParameter($k, $v); + } + } + if (empty($this->headers['content-type'])) { + $this->setHeader('content-type', 'application/x-www-form-urlencoded'); + } + + return $this; + } + + /** + * Attaches a new observer + * + * @param SplObserver + */ + public function attach(SplObserver $observer) + { + foreach ($this->observers as $attached) { + if ($attached === $observer) { + return; + } + } + $this->observers[] = $observer; + } + + /** + * Detaches an existing observer + * + * @param SplObserver + */ + public function detach(SplObserver $observer) + { + foreach ($this->observers as $key => $attached) { + if ($attached === $observer) { + unset($this->observers[$key]); + return; + } + } + } + + /** + * Notifies all observers + */ + public function notify() + { + foreach ($this->observers as $observer) { + $observer->update($this); + } + } + + /** + * Sets the last event + * + * Adapters should use this method to set the current state of the request + * and notify the observers. + * + * @param string event name + * @param mixed event data + */ + public function setLastEvent($name, $data = null) + { + $this->lastEvent = array( + 'name' => $name, + 'data' => $data + ); + $this->notify(); + } + + /** + * Returns the last event + * + * Observers should use this method to access the last change in request. + * The following event names are possible: + *
    + *
  • 'connect' - after connection to remote server, + * data is the destination (string)
  • + *
  • 'disconnect' - after disconnection from server
  • + *
  • 'sentHeaders' - after sending the request headers, + * data is the headers sent (string)
  • + *
  • 'sentBodyPart' - after sending a part of the request body, + * data is the length of that part (int)
  • + *
  • 'receivedHeaders' - after receiving the response headers, + * data is HTTP_Request2_Response object
  • + *
  • 'receivedBodyPart' - after receiving a part of the response + * body, data is that part (string)
  • + *
  • 'receivedEncodedBodyPart' - as 'receivedBodyPart', but data is still + * encoded by Content-Encoding
  • + *
  • 'receivedBody' - after receiving the complete response + * body, data is HTTP_Request2_Response object
  • + *
+ * Different adapters may not send all the event types. Mock adapter does + * not send any events to the observers. + * + * @return array The array has two keys: 'name' and 'data' + */ + public function getLastEvent() + { + return $this->lastEvent; + } + + /** + * Sets the adapter used to actually perform the request + * + * You can pass either an instance of a class implementing HTTP_Request2_Adapter + * or a class name. The method will only try to include a file if the class + * name starts with HTTP_Request2_Adapter_, it will also try to prepend this + * prefix to the class name if it doesn't contain any underscores, so that + * + * $request->setAdapter('curl'); + * + * will work. + * + * @param string|HTTP_Request2_Adapter + * @return HTTP_Request2 + * @throws HTTP_Request2_Exception + */ + public function setAdapter($adapter) + { + if (is_string($adapter)) { + if (!class_exists($adapter, false)) { + if (false === strpos($adapter, '_')) { + $adapter = 'HTTP_Request2_Adapter_' . ucfirst($adapter); + } + if (preg_match('/^HTTP_Request2_Adapter_([a-zA-Z0-9]+)$/', $adapter)) { + include_once str_replace('_', DIRECTORY_SEPARATOR, $adapter) . '.php'; + } + if (!class_exists($adapter, false)) { + throw new HTTP_Request2_Exception("Class {$adapter} not found"); + } + } + $adapter = new $adapter; + } + if (!$adapter instanceof HTTP_Request2_Adapter) { + throw new HTTP_Request2_Exception('Parameter is not a HTTP request adapter'); + } + $this->adapter = $adapter; + + return $this; + } + + /** + * Sends the request and returns the response + * + * @throws HTTP_Request2_Exception + * @return HTTP_Request2_Response + */ + public function send() + { + // Sanity check for URL + if (!$this->url instanceof Net_URL2) { + throw new HTTP_Request2_Exception('No URL given'); + } elseif (!$this->url->isAbsolute()) { + throw new HTTP_Request2_Exception('Absolute URL required'); + } elseif (!in_array(strtolower($this->url->getScheme()), array('https', 'http'))) { + throw new HTTP_Request2_Exception('Not a HTTP URL'); + } + if (empty($this->adapter)) { + $this->setAdapter($this->getConfig('adapter')); + } + // magic_quotes_runtime may break file uploads and chunked response + // processing; see bug #4543 + if ($magicQuotes = ini_get('magic_quotes_runtime')) { + ini_set('magic_quotes_runtime', false); + } + // force using single byte encoding if mbstring extension overloads + // strlen() and substr(); see bug #1781, bug #10605 + if (extension_loaded('mbstring') && (2 & ini_get('mbstring.func_overload'))) { + $oldEncoding = mb_internal_encoding(); + mb_internal_encoding('iso-8859-1'); + } + + try { + $response = $this->adapter->sendRequest($this); + } catch (Exception $e) { + } + // cleanup in either case (poor man's "finally" clause) + if ($magicQuotes) { + ini_set('magic_quotes_runtime', true); + } + if (!empty($oldEncoding)) { + mb_internal_encoding($oldEncoding); + } + // rethrow the exception + if (!empty($e)) { + throw $e; + } + return $response; + } + + /** + * Tries to detect MIME type of a file + * + * The method will try to use fileinfo extension if it is available, + * deprecated mime_content_type() function in the other case. If neither + * works, default 'application/octet-stream' MIME type is returned + * + * @param string filename + * @return string file MIME type + */ + protected static function detectMimeType($filename) + { + // finfo extension from PECL available + if (function_exists('finfo_open')) { + if (!isset(self::$_fileinfoDb)) { + self::$_fileinfoDb = @finfo_open(FILEINFO_MIME); + } + if (self::$_fileinfoDb) { + $info = finfo_file(self::$_fileinfoDb, $filename); + } + } + // (deprecated) mime_content_type function available + if (empty($info) && function_exists('mime_content_type')) { + return mime_content_type($filename); + } + return empty($info)? 'application/octet-stream': $info; + } +} +?> \ No newline at end of file diff --git a/extlib/HTTP/Request2/Adapter.php b/extlib/HTTP/Request2/Adapter.php new file mode 100644 index 000000000..39b092b34 --- /dev/null +++ b/extlib/HTTP/Request2/Adapter.php @@ -0,0 +1,152 @@ + + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Adapter.php 274684 2009-01-26 23:07:27Z avb $ + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** + * Class representing a HTTP response + */ +require_once 'HTTP/Request2/Response.php'; + +/** + * Base class for HTTP_Request2 adapters + * + * HTTP_Request2 class itself only defines methods for aggregating the request + * data, all actual work of sending the request to the remote server and + * receiving its response is performed by adapters. + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @version Release: 0.4.1 + */ +abstract class HTTP_Request2_Adapter +{ + /** + * A list of methods that MUST NOT have a request body, per RFC 2616 + * @var array + */ + protected static $bodyDisallowed = array('TRACE'); + + /** + * Methods having defined semantics for request body + * + * Content-Length header (indicating that the body follows, section 4.3 of + * RFC 2616) will be sent for these methods even if no body was added + * + * @var array + * @link http://pear.php.net/bugs/bug.php?id=12900 + * @link http://pear.php.net/bugs/bug.php?id=14740 + */ + protected static $bodyRequired = array('POST', 'PUT'); + + /** + * Request being sent + * @var HTTP_Request2 + */ + protected $request; + + /** + * Request body + * @var string|resource|HTTP_Request2_MultipartBody + * @see HTTP_Request2::getBody() + */ + protected $requestBody; + + /** + * Length of the request body + * @var integer + */ + protected $contentLength; + + /** + * Sends request to the remote server and returns its response + * + * @param HTTP_Request2 + * @return HTTP_Request2_Response + * @throws HTTP_Request2_Exception + */ + abstract public function sendRequest(HTTP_Request2 $request); + + /** + * Calculates length of the request body, adds proper headers + * + * @param array associative array of request headers, this method will + * add proper 'Content-Length' and 'Content-Type' headers + * to this array (or remove them if not needed) + */ + protected function calculateRequestLength(&$headers) + { + $this->requestBody = $this->request->getBody(); + + if (is_string($this->requestBody)) { + $this->contentLength = strlen($this->requestBody); + } elseif (is_resource($this->requestBody)) { + $stat = fstat($this->requestBody); + $this->contentLength = $stat['size']; + rewind($this->requestBody); + } else { + $this->contentLength = $this->requestBody->getLength(); + $headers['content-type'] = 'multipart/form-data; boundary=' . + $this->requestBody->getBoundary(); + $this->requestBody->rewind(); + } + + if (in_array($this->request->getMethod(), self::$bodyDisallowed) || + 0 == $this->contentLength + ) { + unset($headers['content-type']); + // No body: send a Content-Length header nonetheless (request #12900), + // but do that only for methods that require a body (bug #14740) + if (in_array($this->request->getMethod(), self::$bodyRequired)) { + $headers['content-length'] = 0; + } else { + unset($headers['content-length']); + } + } else { + if (empty($headers['content-type'])) { + $headers['content-type'] = 'application/x-www-form-urlencoded'; + } + $headers['content-length'] = $this->contentLength; + } + } +} +?> diff --git a/extlib/HTTP/Request2/Adapter/Curl.php b/extlib/HTTP/Request2/Adapter/Curl.php new file mode 100644 index 000000000..4d4de0dcc --- /dev/null +++ b/extlib/HTTP/Request2/Adapter/Curl.php @@ -0,0 +1,383 @@ + + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Curl.php 278226 2009-04-03 21:32:48Z avb $ + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** + * Base class for HTTP_Request2 adapters + */ +require_once 'HTTP/Request2/Adapter.php'; + +/** + * Adapter for HTTP_Request2 wrapping around cURL extension + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @version Release: 0.4.1 + */ +class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter +{ + /** + * Mapping of header names to cURL options + * @var array + */ + protected static $headerMap = array( + 'accept-encoding' => CURLOPT_ENCODING, + 'cookie' => CURLOPT_COOKIE, + 'referer' => CURLOPT_REFERER, + 'user-agent' => CURLOPT_USERAGENT + ); + + /** + * Mapping of SSL context options to cURL options + * @var array + */ + protected static $sslContextMap = array( + 'ssl_verify_peer' => CURLOPT_SSL_VERIFYPEER, + 'ssl_cafile' => CURLOPT_CAINFO, + 'ssl_capath' => CURLOPT_CAPATH, + 'ssl_local_cert' => CURLOPT_SSLCERT, + 'ssl_passphrase' => CURLOPT_SSLCERTPASSWD + ); + + /** + * Response being received + * @var HTTP_Request2_Response + */ + protected $response; + + /** + * Whether 'sentHeaders' event was sent to observers + * @var boolean + */ + protected $eventSentHeaders = false; + + /** + * Whether 'receivedHeaders' event was sent to observers + * @var boolean + */ + protected $eventReceivedHeaders = false; + + /** + * Position within request body + * @var integer + * @see callbackReadBody() + */ + protected $position = 0; + + /** + * Information about last transfer, as returned by curl_getinfo() + * @var array + */ + protected $lastInfo; + + /** + * Sends request to the remote server and returns its response + * + * @param HTTP_Request2 + * @return HTTP_Request2_Response + * @throws HTTP_Request2_Exception + */ + public function sendRequest(HTTP_Request2 $request) + { + if (!extension_loaded('curl')) { + throw new HTTP_Request2_Exception('cURL extension not available'); + } + + $this->request = $request; + $this->response = null; + $this->position = 0; + $this->eventSentHeaders = false; + $this->eventReceivedHeaders = false; + + try { + if (false === curl_exec($ch = $this->createCurlHandle())) { + $errorMessage = 'Error sending request: #' . curl_errno($ch) . + ' ' . curl_error($ch); + } + } catch (Exception $e) { + } + $this->lastInfo = curl_getinfo($ch); + curl_close($ch); + + if (!empty($e)) { + throw $e; + } elseif (!empty($errorMessage)) { + throw new HTTP_Request2_Exception($errorMessage); + } + + if (0 < $this->lastInfo['size_download']) { + $this->request->setLastEvent('receivedBody', $this->response); + } + return $this->response; + } + + /** + * Returns information about last transfer + * + * @return array associative array as returned by curl_getinfo() + */ + public function getInfo() + { + return $this->lastInfo; + } + + /** + * Creates a new cURL handle and populates it with data from the request + * + * @return resource a cURL handle, as created by curl_init() + * @throws HTTP_Request2_Exception + */ + protected function createCurlHandle() + { + $ch = curl_init(); + + curl_setopt_array($ch, array( + // setup callbacks + CURLOPT_READFUNCTION => array($this, 'callbackReadBody'), + CURLOPT_HEADERFUNCTION => array($this, 'callbackWriteHeader'), + CURLOPT_WRITEFUNCTION => array($this, 'callbackWriteBody'), + // disallow redirects + CURLOPT_FOLLOWLOCATION => false, + // buffer size + CURLOPT_BUFFERSIZE => $this->request->getConfig('buffer_size'), + // connection timeout + CURLOPT_CONNECTTIMEOUT => $this->request->getConfig('connect_timeout'), + // save full outgoing headers, in case someone is interested + CURLINFO_HEADER_OUT => true, + // request url + CURLOPT_URL => $this->request->getUrl()->getUrl() + )); + + // request timeout + if ($timeout = $this->request->getConfig('timeout')) { + curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); + } + + // set HTTP version + switch ($this->request->getConfig('protocol_version')) { + case '1.0': + curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + break; + case '1.1': + curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); + } + + // set request method + switch ($this->request->getMethod()) { + case HTTP_Request2::METHOD_GET: + curl_setopt($ch, CURLOPT_HTTPGET, true); + break; + case HTTP_Request2::METHOD_POST: + curl_setopt($ch, CURLOPT_POST, true); + break; + default: + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $this->request->getMethod()); + } + + // set proxy, if needed + if ($host = $this->request->getConfig('proxy_host')) { + if (!($port = $this->request->getConfig('proxy_port'))) { + throw new HTTP_Request2_Exception('Proxy port not provided'); + } + curl_setopt($ch, CURLOPT_PROXY, $host . ':' . $port); + if ($user = $this->request->getConfig('proxy_user')) { + curl_setopt($ch, CURLOPT_PROXYUSERPWD, $user . ':' . + $this->request->getConfig('proxy_password')); + switch ($this->request->getConfig('proxy_auth_scheme')) { + case HTTP_Request2::AUTH_BASIC: + curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC); + break; + case HTTP_Request2::AUTH_DIGEST: + curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_DIGEST); + } + } + } + + // set authentication data + if ($auth = $this->request->getAuth()) { + curl_setopt($ch, CURLOPT_USERPWD, $auth['user'] . ':' . $auth['password']); + switch ($auth['scheme']) { + case HTTP_Request2::AUTH_BASIC: + curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + break; + case HTTP_Request2::AUTH_DIGEST: + curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST); + } + } + + // set SSL options + if (0 == strcasecmp($this->request->getUrl()->getScheme(), 'https')) { + foreach ($this->request->getConfig() as $name => $value) { + if ('ssl_verify_host' == $name && null !== $value) { + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $value? 2: 0); + } elseif (isset(self::$sslContextMap[$name]) && null !== $value) { + curl_setopt($ch, self::$sslContextMap[$name], $value); + } + } + } + + $headers = $this->request->getHeaders(); + // make cURL automagically send proper header + if (!isset($headers['accept-encoding'])) { + $headers['accept-encoding'] = ''; + } + + // set headers having special cURL keys + foreach (self::$headerMap as $name => $option) { + if (isset($headers[$name])) { + curl_setopt($ch, $option, $headers[$name]); + unset($headers[$name]); + } + } + + $this->calculateRequestLength($headers); + + // set headers not having special keys + $headersFmt = array(); + foreach ($headers as $name => $value) { + $canonicalName = implode('-', array_map('ucfirst', explode('-', $name))); + $headersFmt[] = $canonicalName . ': ' . $value; + } + curl_setopt($ch, CURLOPT_HTTPHEADER, $headersFmt); + + return $ch; + } + + /** + * Callback function called by cURL for reading the request body + * + * @param resource cURL handle + * @param resource file descriptor (not used) + * @param integer maximum length of data to return + * @return string part of the request body, up to $length bytes + */ + protected function callbackReadBody($ch, $fd, $length) + { + if (!$this->eventSentHeaders) { + $this->request->setLastEvent( + 'sentHeaders', curl_getinfo($ch, CURLINFO_HEADER_OUT) + ); + $this->eventSentHeaders = true; + } + if (in_array($this->request->getMethod(), self::$bodyDisallowed) || + 0 == $this->contentLength || $this->position >= $this->contentLength + ) { + return ''; + } + if (is_string($this->requestBody)) { + $string = substr($this->requestBody, $this->position, $length); + } elseif (is_resource($this->requestBody)) { + $string = fread($this->requestBody, $length); + } else { + $string = $this->requestBody->read($length); + } + $this->request->setLastEvent('sentBodyPart', strlen($string)); + $this->position += strlen($string); + return $string; + } + + /** + * Callback function called by cURL for saving the response headers + * + * @param resource cURL handle + * @param string response header (with trailing CRLF) + * @return integer number of bytes saved + * @see HTTP_Request2_Response::parseHeaderLine() + */ + protected function callbackWriteHeader($ch, $string) + { + // we may receive a second set of headers if doing e.g. digest auth + if ($this->eventReceivedHeaders || !$this->eventSentHeaders) { + // don't bother with 100-Continue responses (bug #15785) + if (!$this->eventSentHeaders || + $this->response->getStatus() >= 200 + ) { + $this->request->setLastEvent( + 'sentHeaders', curl_getinfo($ch, CURLINFO_HEADER_OUT) + ); + } + $this->eventSentHeaders = true; + // we'll need a new response object + if ($this->eventReceivedHeaders) { + $this->eventReceivedHeaders = false; + $this->response = null; + } + } + if (empty($this->response)) { + $this->response = new HTTP_Request2_Response($string, false); + } else { + $this->response->parseHeaderLine($string); + if ('' == trim($string)) { + // don't bother with 100-Continue responses (bug #15785) + if (200 <= $this->response->getStatus()) { + $this->request->setLastEvent('receivedHeaders', $this->response); + } + $this->eventReceivedHeaders = true; + } + } + return strlen($string); + } + + /** + * Callback function called by cURL for saving the response body + * + * @param resource cURL handle (not used) + * @param string part of the response body + * @return integer number of bytes saved + * @see HTTP_Request2_Response::appendBody() + */ + protected function callbackWriteBody($ch, $string) + { + // cURL calls WRITEFUNCTION callback without calling HEADERFUNCTION if + // response doesn't start with proper HTTP status line (see bug #15716) + if (empty($this->response)) { + throw new HTTP_Request2_Exception("Malformed response: {$string}"); + } + if ($this->request->getConfig('store_body')) { + $this->response->appendBody($string); + } + $this->request->setLastEvent('receivedBodyPart', $string); + return strlen($string); + } +} +?> diff --git a/extlib/HTTP/Request2/Adapter/Mock.php b/extlib/HTTP/Request2/Adapter/Mock.php new file mode 100644 index 000000000..89688003b --- /dev/null +++ b/extlib/HTTP/Request2/Adapter/Mock.php @@ -0,0 +1,171 @@ + + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Mock.php 274406 2009-01-23 18:01:57Z avb $ + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** + * Base class for HTTP_Request2 adapters + */ +require_once 'HTTP/Request2/Adapter.php'; + +/** + * Mock adapter intended for testing + * + * Can be used to test applications depending on HTTP_Request2 package without + * actually performing any HTTP requests. This adapter will return responses + * previously added via addResponse() + * + * $mock = new HTTP_Request2_Adapter_Mock(); + * $mock->addResponse("HTTP/1.1 ... "); + * + * $request = new HTTP_Request2(); + * $request->setAdapter($mock); + * + * // This will return the response set above + * $response = $req->send(); + * + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @version Release: 0.4.1 + */ +class HTTP_Request2_Adapter_Mock extends HTTP_Request2_Adapter +{ + /** + * A queue of responses to be returned by sendRequest() + * @var array + */ + protected $responses = array(); + + /** + * Returns the next response from the queue built by addResponse() + * + * If the queue is empty will return default empty response with status 400, + * if an Exception object was added to the queue it will be thrown. + * + * @param HTTP_Request2 + * @return HTTP_Request2_Response + * @throws Exception + */ + public function sendRequest(HTTP_Request2 $request) + { + if (count($this->responses) > 0) { + $response = array_shift($this->responses); + if ($response instanceof HTTP_Request2_Response) { + return $response; + } else { + // rethrow the exception, + $class = get_class($response); + $message = $response->getMessage(); + $code = $response->getCode(); + throw new $class($message, $code); + } + } else { + return self::createResponseFromString("HTTP/1.1 400 Bad Request\r\n\r\n"); + } + } + + /** + * Adds response to the queue + * + * @param mixed either a string, a pointer to an open file, + * a HTTP_Request2_Response or Exception object + * @throws HTTP_Request2_Exception + */ + public function addResponse($response) + { + if (is_string($response)) { + $response = self::createResponseFromString($response); + } elseif (is_resource($response)) { + $response = self::createResponseFromFile($response); + } elseif (!$response instanceof HTTP_Request2_Response && + !$response instanceof Exception + ) { + throw new HTTP_Request2_Exception('Parameter is not a valid response'); + } + $this->responses[] = $response; + } + + /** + * Creates a new HTTP_Request2_Response object from a string + * + * @param string + * @return HTTP_Request2_Response + * @throws HTTP_Request2_Exception + */ + public static function createResponseFromString($str) + { + $parts = preg_split('!(\r?\n){2}!m', $str, 2); + $headerLines = explode("\n", $parts[0]); + $response = new HTTP_Request2_Response(array_shift($headerLines)); + foreach ($headerLines as $headerLine) { + $response->parseHeaderLine($headerLine); + } + $response->parseHeaderLine(''); + if (isset($parts[1])) { + $response->appendBody($parts[1]); + } + return $response; + } + + /** + * Creates a new HTTP_Request2_Response object from a file + * + * @param resource file pointer returned by fopen() + * @return HTTP_Request2_Response + * @throws HTTP_Request2_Exception + */ + public static function createResponseFromFile($fp) + { + $response = new HTTP_Request2_Response(fgets($fp)); + do { + $headerLine = fgets($fp); + $response->parseHeaderLine($headerLine); + } while ('' != trim($headerLine)); + + while (!feof($fp)) { + $response->appendBody(fread($fp, 8192)); + } + return $response; + } +} +?> \ No newline at end of file diff --git a/extlib/HTTP/Request2/Adapter/Socket.php b/extlib/HTTP/Request2/Adapter/Socket.php new file mode 100644 index 000000000..ff44d4959 --- /dev/null +++ b/extlib/HTTP/Request2/Adapter/Socket.php @@ -0,0 +1,971 @@ + + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Socket.php 279760 2009-05-03 10:46:42Z avb $ + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** + * Base class for HTTP_Request2 adapters + */ +require_once 'HTTP/Request2/Adapter.php'; + +/** + * Socket-based adapter for HTTP_Request2 + * + * This adapter uses only PHP sockets and will work on almost any PHP + * environment. Code is based on original HTTP_Request PEAR package. + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @version Release: 0.4.1 + */ +class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter +{ + /** + * Regular expression for 'token' rule from RFC 2616 + */ + const REGEXP_TOKEN = '[^\x00-\x1f\x7f-\xff()<>@,;:\\\\"/\[\]?={}\s]+'; + + /** + * Regular expression for 'quoted-string' rule from RFC 2616 + */ + const REGEXP_QUOTED_STRING = '"(?:\\\\.|[^\\\\"])*"'; + + /** + * Connected sockets, needed for Keep-Alive support + * @var array + * @see connect() + */ + protected static $sockets = array(); + + /** + * Data for digest authentication scheme + * + * The keys for the array are URL prefixes. + * + * The values are associative arrays with data (realm, nonce, nonce-count, + * opaque...) needed for digest authentication. Stored here to prevent making + * duplicate requests to digest-protected resources after we have already + * received the challenge. + * + * @var array + */ + protected static $challenges = array(); + + /** + * Connected socket + * @var resource + * @see connect() + */ + protected $socket; + + /** + * Challenge used for server digest authentication + * @var array + */ + protected $serverChallenge; + + /** + * Challenge used for proxy digest authentication + * @var array + */ + protected $proxyChallenge; + + /** + * Global timeout, exception will be raised if request continues past this time + * @var integer + */ + protected $timeout = null; + + /** + * Remaining length of the current chunk, when reading chunked response + * @var integer + * @see readChunked() + */ + protected $chunkLength = 0; + + /** + * Sends request to the remote server and returns its response + * + * @param HTTP_Request2 + * @return HTTP_Request2_Response + * @throws HTTP_Request2_Exception + */ + public function sendRequest(HTTP_Request2 $request) + { + $this->request = $request; + $keepAlive = $this->connect(); + $headers = $this->prepareHeaders(); + + // Use global request timeout if given, see feature requests #5735, #8964 + if ($timeout = $request->getConfig('timeout')) { + $this->timeout = time() + $timeout; + } else { + $this->timeout = null; + } + + try { + if (false === @fwrite($this->socket, $headers, strlen($headers))) { + throw new HTTP_Request2_Exception('Error writing request'); + } + // provide request headers to the observer, see request #7633 + $this->request->setLastEvent('sentHeaders', $headers); + $this->writeBody(); + + if ($this->timeout && time() > $this->timeout) { + throw new HTTP_Request2_Exception( + 'Request timed out after ' . + $request->getConfig('timeout') . ' second(s)' + ); + } + + $response = $this->readResponse(); + + if (!$this->canKeepAlive($keepAlive, $response)) { + $this->disconnect(); + } + + if ($this->shouldUseProxyDigestAuth($response)) { + return $this->sendRequest($request); + } + if ($this->shouldUseServerDigestAuth($response)) { + return $this->sendRequest($request); + } + if ($authInfo = $response->getHeader('authentication-info')) { + $this->updateChallenge($this->serverChallenge, $authInfo); + } + if ($proxyInfo = $response->getHeader('proxy-authentication-info')) { + $this->updateChallenge($this->proxyChallenge, $proxyInfo); + } + + } catch (Exception $e) { + $this->disconnect(); + throw $e; + } + + return $response; + } + + /** + * Connects to the remote server + * + * @return bool whether the connection can be persistent + * @throws HTTP_Request2_Exception + */ + protected function connect() + { + $secure = 0 == strcasecmp($this->request->getUrl()->getScheme(), 'https'); + $tunnel = HTTP_Request2::METHOD_CONNECT == $this->request->getMethod(); + $headers = $this->request->getHeaders(); + $reqHost = $this->request->getUrl()->getHost(); + if (!($reqPort = $this->request->getUrl()->getPort())) { + $reqPort = $secure? 443: 80; + } + + if ($host = $this->request->getConfig('proxy_host')) { + if (!($port = $this->request->getConfig('proxy_port'))) { + throw new HTTP_Request2_Exception('Proxy port not provided'); + } + $proxy = true; + } else { + $host = $reqHost; + $port = $reqPort; + $proxy = false; + } + + if ($tunnel && !$proxy) { + throw new HTTP_Request2_Exception( + "Trying to perform CONNECT request without proxy" + ); + } + if ($secure && !in_array('ssl', stream_get_transports())) { + throw new HTTP_Request2_Exception( + 'Need OpenSSL support for https:// requests' + ); + } + + // RFC 2068, section 19.7.1: A client MUST NOT send the Keep-Alive + // connection token to a proxy server... + if ($proxy && !$secure && + !empty($headers['connection']) && 'Keep-Alive' == $headers['connection'] + ) { + $this->request->setHeader('connection'); + } + + $keepAlive = ('1.1' == $this->request->getConfig('protocol_version') && + empty($headers['connection'])) || + (!empty($headers['connection']) && + 'Keep-Alive' == $headers['connection']); + $host = ((!$secure || $proxy)? 'tcp://': 'ssl://') . $host; + + $options = array(); + if ($secure || $tunnel) { + foreach ($this->request->getConfig() as $name => $value) { + if ('ssl_' == substr($name, 0, 4) && null !== $value) { + if ('ssl_verify_host' == $name) { + if ($value) { + $options['CN_match'] = $reqHost; + } + } else { + $options[substr($name, 4)] = $value; + } + } + } + ksort($options); + } + + // Changing SSL context options after connection is established does *not* + // work, we need a new connection if options change + $remote = $host . ':' . $port; + $socketKey = $remote . (($secure && $proxy)? "->{$reqHost}:{$reqPort}": '') . + (empty($options)? '': ':' . serialize($options)); + unset($this->socket); + + // We use persistent connections and have a connected socket? + // Ensure that the socket is still connected, see bug #16149 + if ($keepAlive && !empty(self::$sockets[$socketKey]) && + !feof(self::$sockets[$socketKey]) + ) { + $this->socket =& self::$sockets[$socketKey]; + + } elseif ($secure && $proxy && !$tunnel) { + $this->establishTunnel(); + $this->request->setLastEvent( + 'connect', "ssl://{$reqHost}:{$reqPort} via {$host}:{$port}" + ); + self::$sockets[$socketKey] =& $this->socket; + + } else { + // Set SSL context options if doing HTTPS request or creating a tunnel + $context = stream_context_create(); + foreach ($options as $name => $value) { + if (!stream_context_set_option($context, 'ssl', $name, $value)) { + throw new HTTP_Request2_Exception( + "Error setting SSL context option '{$name}'" + ); + } + } + $this->socket = @stream_socket_client( + $remote, $errno, $errstr, + $this->request->getConfig('connect_timeout'), + STREAM_CLIENT_CONNECT, $context + ); + if (!$this->socket) { + throw new HTTP_Request2_Exception( + "Unable to connect to {$remote}. Error #{$errno}: {$errstr}" + ); + } + $this->request->setLastEvent('connect', $remote); + self::$sockets[$socketKey] =& $this->socket; + } + return $keepAlive; + } + + /** + * Establishes a tunnel to a secure remote server via HTTP CONNECT request + * + * This method will fail if 'ssl_verify_peer' is enabled. Probably because PHP + * sees that we are connected to a proxy server (duh!) rather than the server + * that presents its certificate. + * + * @link http://tools.ietf.org/html/rfc2817#section-5.2 + * @throws HTTP_Request2_Exception + */ + protected function establishTunnel() + { + $donor = new self; + $connect = new HTTP_Request2( + $this->request->getUrl(), HTTP_Request2::METHOD_CONNECT, + array_merge($this->request->getConfig(), + array('adapter' => $donor)) + ); + $response = $connect->send(); + // Need any successful (2XX) response + if (200 > $response->getStatus() || 300 <= $response->getStatus()) { + throw new HTTP_Request2_Exception( + 'Failed to connect via HTTPS proxy. Proxy response: ' . + $response->getStatus() . ' ' . $response->getReasonPhrase() + ); + } + $this->socket = $donor->socket; + + $modes = array( + STREAM_CRYPTO_METHOD_TLS_CLIENT, + STREAM_CRYPTO_METHOD_SSLv3_CLIENT, + STREAM_CRYPTO_METHOD_SSLv23_CLIENT, + STREAM_CRYPTO_METHOD_SSLv2_CLIENT + ); + + foreach ($modes as $mode) { + if (stream_socket_enable_crypto($this->socket, true, $mode)) { + return; + } + } + throw new HTTP_Request2_Exception( + 'Failed to enable secure connection when connecting through proxy' + ); + } + + /** + * Checks whether current connection may be reused or should be closed + * + * @param boolean whether connection could be persistent + * in the first place + * @param HTTP_Request2_Response response object to check + * @return boolean + */ + protected function canKeepAlive($requestKeepAlive, HTTP_Request2_Response $response) + { + // Do not close socket on successful CONNECT request + if (HTTP_Request2::METHOD_CONNECT == $this->request->getMethod() && + 200 <= $response->getStatus() && 300 > $response->getStatus() + ) { + return true; + } + + $lengthKnown = 'chunked' == strtolower($response->getHeader('transfer-encoding')) || + null !== $response->getHeader('content-length'); + $persistent = 'keep-alive' == strtolower($response->getHeader('connection')) || + (null === $response->getHeader('connection') && + '1.1' == $response->getVersion()); + return $requestKeepAlive && $lengthKnown && $persistent; + } + + /** + * Disconnects from the remote server + */ + protected function disconnect() + { + if (is_resource($this->socket)) { + fclose($this->socket); + $this->socket = null; + $this->request->setLastEvent('disconnect'); + } + } + + /** + * Checks whether another request should be performed with server digest auth + * + * Several conditions should be satisfied for it to return true: + * - response status should be 401 + * - auth credentials should be set in the request object + * - response should contain WWW-Authenticate header with digest challenge + * - there is either no challenge stored for this URL or new challenge + * contains stale=true parameter (in other case we probably just failed + * due to invalid username / password) + * + * The method stores challenge values in $challenges static property + * + * @param HTTP_Request2_Response response to check + * @return boolean whether another request should be performed + * @throws HTTP_Request2_Exception in case of unsupported challenge parameters + */ + protected function shouldUseServerDigestAuth(HTTP_Request2_Response $response) + { + // no sense repeating a request if we don't have credentials + if (401 != $response->getStatus() || !$this->request->getAuth()) { + return false; + } + if (!$challenge = $this->parseDigestChallenge($response->getHeader('www-authenticate'))) { + return false; + } + + $url = $this->request->getUrl(); + $scheme = $url->getScheme(); + $host = $scheme . '://' . $url->getHost(); + if ($port = $url->getPort()) { + if ((0 == strcasecmp($scheme, 'http') && 80 != $port) || + (0 == strcasecmp($scheme, 'https') && 443 != $port) + ) { + $host .= ':' . $port; + } + } + + if (!empty($challenge['domain'])) { + $prefixes = array(); + foreach (preg_split('/\\s+/', $challenge['domain']) as $prefix) { + // don't bother with different servers + if ('/' == substr($prefix, 0, 1)) { + $prefixes[] = $host . $prefix; + } + } + } + if (empty($prefixes)) { + $prefixes = array($host . '/'); + } + + $ret = true; + foreach ($prefixes as $prefix) { + if (!empty(self::$challenges[$prefix]) && + (empty($challenge['stale']) || strcasecmp('true', $challenge['stale'])) + ) { + // probably credentials are invalid + $ret = false; + } + self::$challenges[$prefix] =& $challenge; + } + return $ret; + } + + /** + * Checks whether another request should be performed with proxy digest auth + * + * Several conditions should be satisfied for it to return true: + * - response status should be 407 + * - proxy auth credentials should be set in the request object + * - response should contain Proxy-Authenticate header with digest challenge + * - there is either no challenge stored for this proxy or new challenge + * contains stale=true parameter (in other case we probably just failed + * due to invalid username / password) + * + * The method stores challenge values in $challenges static property + * + * @param HTTP_Request2_Response response to check + * @return boolean whether another request should be performed + * @throws HTTP_Request2_Exception in case of unsupported challenge parameters + */ + protected function shouldUseProxyDigestAuth(HTTP_Request2_Response $response) + { + if (407 != $response->getStatus() || !$this->request->getConfig('proxy_user')) { + return false; + } + if (!($challenge = $this->parseDigestChallenge($response->getHeader('proxy-authenticate')))) { + return false; + } + + $key = 'proxy://' . $this->request->getConfig('proxy_host') . + ':' . $this->request->getConfig('proxy_port'); + + if (!empty(self::$challenges[$key]) && + (empty($challenge['stale']) || strcasecmp('true', $challenge['stale'])) + ) { + $ret = false; + } else { + $ret = true; + } + self::$challenges[$key] = $challenge; + return $ret; + } + + /** + * Extracts digest method challenge from (WWW|Proxy)-Authenticate header value + * + * There is a problem with implementation of RFC 2617: several of the parameters + * here are defined as quoted-string and thus may contain backslash escaped + * double quotes (RFC 2616, section 2.2). However, RFC 2617 defines unq(X) as + * just value of quoted-string X without surrounding quotes, it doesn't speak + * about removing backslash escaping. + * + * Now realm parameter is user-defined and human-readable, strange things + * happen when it contains quotes: + * - Apache allows quotes in realm, but apparently uses realm value without + * backslashes for digest computation + * - Squid allows (manually escaped) quotes there, but it is impossible to + * authorize with either escaped or unescaped quotes used in digest, + * probably it can't parse the response (?) + * - Both IE and Firefox display realm value with backslashes in + * the password popup and apparently use the same value for digest + * + * HTTP_Request2 follows IE and Firefox (and hopefully RFC 2617) in + * quoted-string handling, unfortunately that means failure to authorize + * sometimes + * + * @param string value of WWW-Authenticate or Proxy-Authenticate header + * @return mixed associative array with challenge parameters, false if + * no challenge is present in header value + * @throws HTTP_Request2_Exception in case of unsupported challenge parameters + */ + protected function parseDigestChallenge($headerValue) + { + $authParam = '(' . self::REGEXP_TOKEN . ')\\s*=\\s*(' . + self::REGEXP_TOKEN . '|' . self::REGEXP_QUOTED_STRING . ')'; + $challenge = "!(?<=^|\\s|,)Digest ({$authParam}\\s*(,\\s*|$))+!"; + if (!preg_match($challenge, $headerValue, $matches)) { + return false; + } + + preg_match_all('!' . $authParam . '!', $matches[0], $params); + $paramsAry = array(); + $knownParams = array('realm', 'domain', 'nonce', 'opaque', 'stale', + 'algorithm', 'qop'); + for ($i = 0; $i < count($params[0]); $i++) { + // section 3.2.1: Any unrecognized directive MUST be ignored. + if (in_array($params[1][$i], $knownParams)) { + if ('"' == substr($params[2][$i], 0, 1)) { + $paramsAry[$params[1][$i]] = substr($params[2][$i], 1, -1); + } else { + $paramsAry[$params[1][$i]] = $params[2][$i]; + } + } + } + // we only support qop=auth + if (!empty($paramsAry['qop']) && + !in_array('auth', array_map('trim', explode(',', $paramsAry['qop']))) + ) { + throw new HTTP_Request2_Exception( + "Only 'auth' qop is currently supported in digest authentication, " . + "server requested '{$paramsAry['qop']}'" + ); + } + // we only support algorithm=MD5 + if (!empty($paramsAry['algorithm']) && 'MD5' != $paramsAry['algorithm']) { + throw new HTTP_Request2_Exception( + "Only 'MD5' algorithm is currently supported in digest authentication, " . + "server requested '{$paramsAry['algorithm']}'" + ); + } + + return $paramsAry; + } + + /** + * Parses [Proxy-]Authentication-Info header value and updates challenge + * + * @param array challenge to update + * @param string value of [Proxy-]Authentication-Info header + * @todo validate server rspauth response + */ + protected function updateChallenge(&$challenge, $headerValue) + { + $authParam = '!(' . self::REGEXP_TOKEN . ')\\s*=\\s*(' . + self::REGEXP_TOKEN . '|' . self::REGEXP_QUOTED_STRING . ')!'; + $paramsAry = array(); + + preg_match_all($authParam, $headerValue, $params); + for ($i = 0; $i < count($params[0]); $i++) { + if ('"' == substr($params[2][$i], 0, 1)) { + $paramsAry[$params[1][$i]] = substr($params[2][$i], 1, -1); + } else { + $paramsAry[$params[1][$i]] = $params[2][$i]; + } + } + // for now, just update the nonce value + if (!empty($paramsAry['nextnonce'])) { + $challenge['nonce'] = $paramsAry['nextnonce']; + $challenge['nc'] = 1; + } + } + + /** + * Creates a value for [Proxy-]Authorization header when using digest authentication + * + * @param string user name + * @param string password + * @param string request URL + * @param array digest challenge parameters + * @return string value of [Proxy-]Authorization request header + * @link http://tools.ietf.org/html/rfc2617#section-3.2.2 + */ + protected function createDigestResponse($user, $password, $url, &$challenge) + { + if (false !== ($q = strpos($url, '?')) && + $this->request->getConfig('digest_compat_ie') + ) { + $url = substr($url, 0, $q); + } + + $a1 = md5($user . ':' . $challenge['realm'] . ':' . $password); + $a2 = md5($this->request->getMethod() . ':' . $url); + + if (empty($challenge['qop'])) { + $digest = md5($a1 . ':' . $challenge['nonce'] . ':' . $a2); + } else { + $challenge['cnonce'] = 'Req2.' . rand(); + if (empty($challenge['nc'])) { + $challenge['nc'] = 1; + } + $nc = sprintf('%08x', $challenge['nc']++); + $digest = md5($a1 . ':' . $challenge['nonce'] . ':' . $nc . ':' . + $challenge['cnonce'] . ':auth:' . $a2); + } + return 'Digest username="' . str_replace(array('\\', '"'), array('\\\\', '\\"'), $user) . '", ' . + 'realm="' . $challenge['realm'] . '", ' . + 'nonce="' . $challenge['nonce'] . '", ' . + 'uri="' . $url . '", ' . + 'response="' . $digest . '"' . + (!empty($challenge['opaque'])? + ', opaque="' . $challenge['opaque'] . '"': + '') . + (!empty($challenge['qop'])? + ', qop="auth", nc=' . $nc . ', cnonce="' . $challenge['cnonce'] . '"': + ''); + } + + /** + * Adds 'Authorization' header (if needed) to request headers array + * + * @param array request headers + * @param string request host (needed for digest authentication) + * @param string request URL (needed for digest authentication) + * @throws HTTP_Request2_Exception + */ + protected function addAuthorizationHeader(&$headers, $requestHost, $requestUrl) + { + if (!($auth = $this->request->getAuth())) { + return; + } + switch ($auth['scheme']) { + case HTTP_Request2::AUTH_BASIC: + $headers['authorization'] = + 'Basic ' . base64_encode($auth['user'] . ':' . $auth['password']); + break; + + case HTTP_Request2::AUTH_DIGEST: + unset($this->serverChallenge); + $fullUrl = ('/' == $requestUrl[0])? + $this->request->getUrl()->getScheme() . '://' . + $requestHost . $requestUrl: + $requestUrl; + foreach (array_keys(self::$challenges) as $key) { + if ($key == substr($fullUrl, 0, strlen($key))) { + $headers['authorization'] = $this->createDigestResponse( + $auth['user'], $auth['password'], + $requestUrl, self::$challenges[$key] + ); + $this->serverChallenge =& self::$challenges[$key]; + break; + } + } + break; + + default: + throw new HTTP_Request2_Exception( + "Unknown HTTP authentication scheme '{$auth['scheme']}'" + ); + } + } + + /** + * Adds 'Proxy-Authorization' header (if needed) to request headers array + * + * @param array request headers + * @param string request URL (needed for digest authentication) + * @throws HTTP_Request2_Exception + */ + protected function addProxyAuthorizationHeader(&$headers, $requestUrl) + { + if (!$this->request->getConfig('proxy_host') || + !($user = $this->request->getConfig('proxy_user')) || + (0 == strcasecmp('https', $this->request->getUrl()->getScheme()) && + HTTP_Request2::METHOD_CONNECT != $this->request->getMethod()) + ) { + return; + } + + $password = $this->request->getConfig('proxy_password'); + switch ($this->request->getConfig('proxy_auth_scheme')) { + case HTTP_Request2::AUTH_BASIC: + $headers['proxy-authorization'] = + 'Basic ' . base64_encode($user . ':' . $password); + break; + + case HTTP_Request2::AUTH_DIGEST: + unset($this->proxyChallenge); + $proxyUrl = 'proxy://' . $this->request->getConfig('proxy_host') . + ':' . $this->request->getConfig('proxy_port'); + if (!empty(self::$challenges[$proxyUrl])) { + $headers['proxy-authorization'] = $this->createDigestResponse( + $user, $password, + $requestUrl, self::$challenges[$proxyUrl] + ); + $this->proxyChallenge =& self::$challenges[$proxyUrl]; + } + break; + + default: + throw new HTTP_Request2_Exception( + "Unknown HTTP authentication scheme '" . + $this->request->getConfig('proxy_auth_scheme') . "'" + ); + } + } + + + /** + * Creates the string with the Request-Line and request headers + * + * @return string + * @throws HTTP_Request2_Exception + */ + protected function prepareHeaders() + { + $headers = $this->request->getHeaders(); + $url = $this->request->getUrl(); + $connect = HTTP_Request2::METHOD_CONNECT == $this->request->getMethod(); + $host = $url->getHost(); + + $defaultPort = 0 == strcasecmp($url->getScheme(), 'https')? 443: 80; + if (($port = $url->getPort()) && $port != $defaultPort || $connect) { + $host .= ':' . (empty($port)? $defaultPort: $port); + } + // Do not overwrite explicitly set 'Host' header, see bug #16146 + if (!isset($headers['host'])) { + $headers['host'] = $host; + } + + if ($connect) { + $requestUrl = $host; + + } else { + if (!$this->request->getConfig('proxy_host') || + 0 == strcasecmp($url->getScheme(), 'https') + ) { + $requestUrl = ''; + } else { + $requestUrl = $url->getScheme() . '://' . $host; + } + $path = $url->getPath(); + $query = $url->getQuery(); + $requestUrl .= (empty($path)? '/': $path) . (empty($query)? '': '?' . $query); + } + + if ('1.1' == $this->request->getConfig('protocol_version') && + extension_loaded('zlib') && !isset($headers['accept-encoding']) + ) { + $headers['accept-encoding'] = 'gzip, deflate'; + } + + $this->addAuthorizationHeader($headers, $host, $requestUrl); + $this->addProxyAuthorizationHeader($headers, $requestUrl); + $this->calculateRequestLength($headers); + + $headersStr = $this->request->getMethod() . ' ' . $requestUrl . ' HTTP/' . + $this->request->getConfig('protocol_version') . "\r\n"; + foreach ($headers as $name => $value) { + $canonicalName = implode('-', array_map('ucfirst', explode('-', $name))); + $headersStr .= $canonicalName . ': ' . $value . "\r\n"; + } + return $headersStr . "\r\n"; + } + + /** + * Sends the request body + * + * @throws HTTP_Request2_Exception + */ + protected function writeBody() + { + if (in_array($this->request->getMethod(), self::$bodyDisallowed) || + 0 == $this->contentLength + ) { + return; + } + + $position = 0; + $bufferSize = $this->request->getConfig('buffer_size'); + while ($position < $this->contentLength) { + if (is_string($this->requestBody)) { + $str = substr($this->requestBody, $position, $bufferSize); + } elseif (is_resource($this->requestBody)) { + $str = fread($this->requestBody, $bufferSize); + } else { + $str = $this->requestBody->read($bufferSize); + } + if (false === @fwrite($this->socket, $str, strlen($str))) { + throw new HTTP_Request2_Exception('Error writing request'); + } + // Provide the length of written string to the observer, request #7630 + $this->request->setLastEvent('sentBodyPart', strlen($str)); + $position += strlen($str); + } + } + + /** + * Reads the remote server's response + * + * @return HTTP_Request2_Response + * @throws HTTP_Request2_Exception + */ + protected function readResponse() + { + $bufferSize = $this->request->getConfig('buffer_size'); + + do { + $response = new HTTP_Request2_Response($this->readLine($bufferSize), true); + do { + $headerLine = $this->readLine($bufferSize); + $response->parseHeaderLine($headerLine); + } while ('' != $headerLine); + } while (in_array($response->getStatus(), array(100, 101))); + + $this->request->setLastEvent('receivedHeaders', $response); + + // No body possible in such responses + if (HTTP_Request2::METHOD_HEAD == $this->request->getMethod() || + (HTTP_Request2::METHOD_CONNECT == $this->request->getMethod() && + 200 <= $response->getStatus() && 300 > $response->getStatus()) || + in_array($response->getStatus(), array(204, 304)) + ) { + return $response; + } + + $chunked = 'chunked' == $response->getHeader('transfer-encoding'); + $length = $response->getHeader('content-length'); + $hasBody = false; + if ($chunked || null === $length || 0 < intval($length)) { + // RFC 2616, section 4.4: + // 3. ... If a message is received with both a + // Transfer-Encoding header field and a Content-Length header field, + // the latter MUST be ignored. + $toRead = ($chunked || null === $length)? null: $length; + $this->chunkLength = 0; + + while (!feof($this->socket) && (is_null($toRead) || 0 < $toRead)) { + if ($chunked) { + $data = $this->readChunked($bufferSize); + } elseif (is_null($toRead)) { + $data = $this->fread($bufferSize); + } else { + $data = $this->fread(min($toRead, $bufferSize)); + $toRead -= strlen($data); + } + if ('' == $data && (!$this->chunkLength || feof($this->socket))) { + break; + } + + $hasBody = true; + if ($this->request->getConfig('store_body')) { + $response->appendBody($data); + } + if (!in_array($response->getHeader('content-encoding'), array('identity', null))) { + $this->request->setLastEvent('receivedEncodedBodyPart', $data); + } else { + $this->request->setLastEvent('receivedBodyPart', $data); + } + } + } + + if ($hasBody) { + $this->request->setLastEvent('receivedBody', $response); + } + return $response; + } + + /** + * Reads until either the end of the socket or a newline, whichever comes first + * + * Strips the trailing newline from the returned data, handles global + * request timeout. Method idea borrowed from Net_Socket PEAR package. + * + * @param int buffer size to use for reading + * @return Available data up to the newline (not including newline) + * @throws HTTP_Request2_Exception In case of timeout + */ + protected function readLine($bufferSize) + { + $line = ''; + while (!feof($this->socket)) { + if ($this->timeout) { + stream_set_timeout($this->socket, max($this->timeout - time(), 1)); + } + $line .= @fgets($this->socket, $bufferSize); + $info = stream_get_meta_data($this->socket); + if ($info['timed_out'] || $this->timeout && time() > $this->timeout) { + throw new HTTP_Request2_Exception( + 'Request timed out after ' . + $this->request->getConfig('timeout') . ' second(s)' + ); + } + if (substr($line, -1) == "\n") { + return rtrim($line, "\r\n"); + } + } + return $line; + } + + /** + * Wrapper around fread(), handles global request timeout + * + * @param int Reads up to this number of bytes + * @return Data read from socket + * @throws HTTP_Request2_Exception In case of timeout + */ + protected function fread($length) + { + if ($this->timeout) { + stream_set_timeout($this->socket, max($this->timeout - time(), 1)); + } + $data = fread($this->socket, $length); + $info = stream_get_meta_data($this->socket); + if ($info['timed_out'] || $this->timeout && time() > $this->timeout) { + throw new HTTP_Request2_Exception( + 'Request timed out after ' . + $this->request->getConfig('timeout') . ' second(s)' + ); + } + return $data; + } + + /** + * Reads a part of response body encoded with chunked Transfer-Encoding + * + * @param int buffer size to use for reading + * @return string + * @throws HTTP_Request2_Exception + */ + protected function readChunked($bufferSize) + { + // at start of the next chunk? + if (0 == $this->chunkLength) { + $line = $this->readLine($bufferSize); + if (!preg_match('/^([0-9a-f]+)/i', $line, $matches)) { + throw new HTTP_Request2_Exception( + "Cannot decode chunked response, invalid chunk length '{$line}'" + ); + } else { + $this->chunkLength = hexdec($matches[1]); + // Chunk with zero length indicates the end + if (0 == $this->chunkLength) { + $this->readLine($bufferSize); + return ''; + } + } + } + $data = $this->fread(min($this->chunkLength, $bufferSize)); + $this->chunkLength -= strlen($data); + if (0 == $this->chunkLength) { + $this->readLine($bufferSize); // Trailing CRLF + } + return $data; + } +} + +?> \ No newline at end of file diff --git a/extlib/HTTP/Request2/Exception.php b/extlib/HTTP/Request2/Exception.php new file mode 100644 index 000000000..bfef7d6c2 --- /dev/null +++ b/extlib/HTTP/Request2/Exception.php @@ -0,0 +1,62 @@ + + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Exception.php 273003 2009-01-07 19:28:22Z avb $ + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** + * Base class for exceptions in PEAR + */ +require_once 'PEAR/Exception.php'; + +/** + * Exception class for HTTP_Request2 package + * + * Such a class is required by the Exception RFC: + * http://pear.php.net/pepr/pepr-proposal-show.php?id=132 + * + * @category HTTP + * @package HTTP_Request2 + * @version Release: 0.4.1 + */ +class HTTP_Request2_Exception extends PEAR_Exception +{ +} +?> \ No newline at end of file diff --git a/extlib/HTTP/Request2/MultipartBody.php b/extlib/HTTP/Request2/MultipartBody.php new file mode 100644 index 000000000..d8afd8344 --- /dev/null +++ b/extlib/HTTP/Request2/MultipartBody.php @@ -0,0 +1,274 @@ + + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: MultipartBody.php 287306 2009-08-14 15:22:52Z avb $ + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** + * Class for building multipart/form-data request body + * + * The class helps to reduce memory consumption by streaming large file uploads + * from disk, it also allows monitoring of upload progress (see request #7630) + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @version Release: 0.4.1 + * @link http://tools.ietf.org/html/rfc1867 + */ +class HTTP_Request2_MultipartBody +{ + /** + * MIME boundary + * @var string + */ + private $_boundary; + + /** + * Form parameters added via {@link HTTP_Request2::addPostParameter()} + * @var array + */ + private $_params = array(); + + /** + * File uploads added via {@link HTTP_Request2::addUpload()} + * @var array + */ + private $_uploads = array(); + + /** + * Header for parts with parameters + * @var string + */ + private $_headerParam = "--%s\r\nContent-Disposition: form-data; name=\"%s\"\r\n\r\n"; + + /** + * Header for parts with uploads + * @var string + */ + private $_headerUpload = "--%s\r\nContent-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\nContent-Type: %s\r\n\r\n"; + + /** + * Current position in parameter and upload arrays + * + * First number is index of "current" part, second number is position within + * "current" part + * + * @var array + */ + private $_pos = array(0, 0); + + + /** + * Constructor. Sets the arrays with POST data. + * + * @param array values of form fields set via {@link HTTP_Request2::addPostParameter()} + * @param array file uploads set via {@link HTTP_Request2::addUpload()} + * @param bool whether to append brackets to array variable names + */ + public function __construct(array $params, array $uploads, $useBrackets = true) + { + $this->_params = self::_flattenArray('', $params, $useBrackets); + foreach ($uploads as $fieldName => $f) { + if (!is_array($f['fp'])) { + $this->_uploads[] = $f + array('name' => $fieldName); + } else { + for ($i = 0; $i < count($f['fp']); $i++) { + $upload = array( + 'name' => ($useBrackets? $fieldName . '[' . $i . ']': $fieldName) + ); + foreach (array('fp', 'filename', 'size', 'type') as $key) { + $upload[$key] = $f[$key][$i]; + } + $this->_uploads[] = $upload; + } + } + } + } + + /** + * Returns the length of the body to use in Content-Length header + * + * @return integer + */ + public function getLength() + { + $boundaryLength = strlen($this->getBoundary()); + $headerParamLength = strlen($this->_headerParam) - 4 + $boundaryLength; + $headerUploadLength = strlen($this->_headerUpload) - 8 + $boundaryLength; + $length = $boundaryLength + 6; + foreach ($this->_params as $p) { + $length += $headerParamLength + strlen($p[0]) + strlen($p[1]) + 2; + } + foreach ($this->_uploads as $u) { + $length += $headerUploadLength + strlen($u['name']) + strlen($u['type']) + + strlen($u['filename']) + $u['size'] + 2; + } + return $length; + } + + /** + * Returns the boundary to use in Content-Type header + * + * @return string + */ + public function getBoundary() + { + if (empty($this->_boundary)) { + $this->_boundary = '--' . md5('PEAR-HTTP_Request2-' . microtime()); + } + return $this->_boundary; + } + + /** + * Returns next chunk of request body + * + * @param integer Amount of bytes to read + * @return string Up to $length bytes of data, empty string if at end + */ + public function read($length) + { + $ret = ''; + $boundary = $this->getBoundary(); + $paramCount = count($this->_params); + $uploadCount = count($this->_uploads); + while ($length > 0 && $this->_pos[0] <= $paramCount + $uploadCount) { + $oldLength = $length; + if ($this->_pos[0] < $paramCount) { + $param = sprintf($this->_headerParam, $boundary, + $this->_params[$this->_pos[0]][0]) . + $this->_params[$this->_pos[0]][1] . "\r\n"; + $ret .= substr($param, $this->_pos[1], $length); + $length -= min(strlen($param) - $this->_pos[1], $length); + + } elseif ($this->_pos[0] < $paramCount + $uploadCount) { + $pos = $this->_pos[0] - $paramCount; + $header = sprintf($this->_headerUpload, $boundary, + $this->_uploads[$pos]['name'], + $this->_uploads[$pos]['filename'], + $this->_uploads[$pos]['type']); + if ($this->_pos[1] < strlen($header)) { + $ret .= substr($header, $this->_pos[1], $length); + $length -= min(strlen($header) - $this->_pos[1], $length); + } + $filePos = max(0, $this->_pos[1] - strlen($header)); + if ($length > 0 && $filePos < $this->_uploads[$pos]['size']) { + $ret .= fread($this->_uploads[$pos]['fp'], $length); + $length -= min($length, $this->_uploads[$pos]['size'] - $filePos); + } + if ($length > 0) { + $start = $this->_pos[1] + ($oldLength - $length) - + strlen($header) - $this->_uploads[$pos]['size']; + $ret .= substr("\r\n", $start, $length); + $length -= min(2 - $start, $length); + } + + } else { + $closing = '--' . $boundary . "--\r\n"; + $ret .= substr($closing, $this->_pos[1], $length); + $length -= min(strlen($closing) - $this->_pos[1], $length); + } + if ($length > 0) { + $this->_pos = array($this->_pos[0] + 1, 0); + } else { + $this->_pos[1] += $oldLength; + } + } + return $ret; + } + + /** + * Sets the current position to the start of the body + * + * This allows reusing the same body in another request + */ + public function rewind() + { + $this->_pos = array(0, 0); + foreach ($this->_uploads as $u) { + rewind($u['fp']); + } + } + + /** + * Returns the body as string + * + * Note that it reads all file uploads into memory so it is a good idea not + * to use this method with large file uploads and rely on read() instead. + * + * @return string + */ + public function __toString() + { + $this->rewind(); + return $this->read($this->getLength()); + } + + + /** + * Helper function to change the (probably multidimensional) associative array + * into the simple one. + * + * @param string name for item + * @param mixed item's values + * @param bool whether to append [] to array variables' names + * @return array array with the following items: array('item name', 'item value'); + */ + private static function _flattenArray($name, $values, $useBrackets) + { + if (!is_array($values)) { + return array(array($name, $values)); + } else { + $ret = array(); + foreach ($values as $k => $v) { + if (empty($name)) { + $newName = $k; + } elseif ($useBrackets) { + $newName = $name . '[' . $k . ']'; + } else { + $newName = $name; + } + $ret = array_merge($ret, self::_flattenArray($newName, $v, $useBrackets)); + } + return $ret; + } + } +} +?> diff --git a/extlib/HTTP/Request2/Observer/Log.php b/extlib/HTTP/Request2/Observer/Log.php new file mode 100644 index 000000000..b1a055278 --- /dev/null +++ b/extlib/HTTP/Request2/Observer/Log.php @@ -0,0 +1,215 @@ + + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category HTTP + * @package HTTP_Request2 + * @author David Jean Louis + * @author Alexey Borzov + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Log.php 272593 2009-01-02 16:27:14Z avb $ + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** + * Exception class for HTTP_Request2 package + */ +require_once 'HTTP/Request2/Exception.php'; + +/** + * A debug observer useful for debugging / testing. + * + * This observer logs to a log target data corresponding to the various request + * and response events, it logs by default to php://output but can be configured + * to log to a file or via the PEAR Log package. + * + * A simple example: + * + * require_once 'HTTP/Request2.php'; + * require_once 'HTTP/Request2/Observer/Log.php'; + * + * $request = new HTTP_Request2('http://www.example.com'); + * $observer = new HTTP_Request2_Observer_Log(); + * $request->attach($observer); + * $request->send(); + * + * + * A more complex example with PEAR Log: + * + * require_once 'HTTP/Request2.php'; + * require_once 'HTTP/Request2/Observer/Log.php'; + * require_once 'Log.php'; + * + * $request = new HTTP_Request2('http://www.example.com'); + * // we want to log with PEAR log + * $observer = new HTTP_Request2_Observer_Log(Log::factory('console')); + * + * // we only want to log received headers + * $observer->events = array('receivedHeaders'); + * + * $request->attach($observer); + * $request->send(); + * + * + * @category HTTP + * @package HTTP_Request2 + * @author David Jean Louis + * @author Alexey Borzov + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version Release: 0.4.1 + * @link http://pear.php.net/package/HTTP_Request2 + */ +class HTTP_Request2_Observer_Log implements SplObserver +{ + // properties {{{ + + /** + * The log target, it can be a a resource or a PEAR Log instance. + * + * @var resource|Log $target + */ + protected $target = null; + + /** + * The events to log. + * + * @var array $events + */ + public $events = array( + 'connect', + 'sentHeaders', + 'sentBodyPart', + 'receivedHeaders', + 'receivedBody', + 'disconnect', + ); + + // }}} + // __construct() {{{ + + /** + * Constructor. + * + * @param mixed $target Can be a file path (default: php://output), a resource, + * or an instance of the PEAR Log class. + * @param array $events Array of events to listen to (default: all events) + * + * @return void + */ + public function __construct($target = 'php://output', array $events = array()) + { + if (!empty($events)) { + $this->events = $events; + } + if (is_resource($target) || $target instanceof Log) { + $this->target = $target; + } elseif (false === ($this->target = @fopen($target, 'w'))) { + throw new HTTP_Request2_Exception("Unable to open '{$target}'"); + } + } + + // }}} + // update() {{{ + + /** + * Called when the request notify us of an event. + * + * @param HTTP_Request2 $subject The HTTP_Request2 instance + * + * @return void + */ + public function update(SplSubject $subject) + { + $event = $subject->getLastEvent(); + if (!in_array($event['name'], $this->events)) { + return; + } + + switch ($event['name']) { + case 'connect': + $this->log('* Connected to ' . $event['data']); + break; + case 'sentHeaders': + $headers = explode("\r\n", $event['data']); + array_pop($headers); + foreach ($headers as $header) { + $this->log('> ' . $header); + } + break; + case 'sentBodyPart': + $this->log('> ' . $event['data']); + break; + case 'receivedHeaders': + $this->log(sprintf('< HTTP/%s %s %s', + $event['data']->getVersion(), + $event['data']->getStatus(), + $event['data']->getReasonPhrase())); + $headers = $event['data']->getHeader(); + foreach ($headers as $key => $val) { + $this->log('< ' . $key . ': ' . $val); + } + $this->log('< '); + break; + case 'receivedBody': + $this->log($event['data']->getBody()); + break; + case 'disconnect': + $this->log('* Disconnected'); + break; + } + } + + // }}} + // log() {{{ + + /** + * Log the given message to the configured target. + * + * @param string $message Message to display + * + * @return void + */ + protected function log($message) + { + if ($this->target instanceof Log) { + $this->target->debug($message); + } elseif (is_resource($this->target)) { + fwrite($this->target, $message . "\r\n"); + } + } + + // }}} +} + +?> \ No newline at end of file diff --git a/extlib/HTTP/Request2/Response.php b/extlib/HTTP/Request2/Response.php new file mode 100644 index 000000000..c7c1021fb --- /dev/null +++ b/extlib/HTTP/Request2/Response.php @@ -0,0 +1,549 @@ + + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Response.php 287948 2009-09-01 17:12:18Z avb $ + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** + * Exception class for HTTP_Request2 package + */ +require_once 'HTTP/Request2/Exception.php'; + +/** + * Class representing a HTTP response + * + * The class is designed to be used in "streaming" scenario, building the + * response as it is being received: + * + * $statusLine = read_status_line(); + * $response = new HTTP_Request2_Response($statusLine); + * do { + * $headerLine = read_header_line(); + * $response->parseHeaderLine($headerLine); + * } while ($headerLine != ''); + * + * while ($chunk = read_body()) { + * $response->appendBody($chunk); + * } + * + * var_dump($response->getHeader(), $response->getCookies(), $response->getBody()); + * + * + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @version Release: 0.4.1 + * @link http://tools.ietf.org/html/rfc2616#section-6 + */ +class HTTP_Request2_Response +{ + /** + * HTTP protocol version (e.g. 1.0, 1.1) + * @var string + */ + protected $version; + + /** + * Status code + * @var integer + * @link http://tools.ietf.org/html/rfc2616#section-6.1.1 + */ + protected $code; + + /** + * Reason phrase + * @var string + * @link http://tools.ietf.org/html/rfc2616#section-6.1.1 + */ + protected $reasonPhrase; + + /** + * Associative array of response headers + * @var array + */ + protected $headers = array(); + + /** + * Cookies set in the response + * @var array + */ + protected $cookies = array(); + + /** + * Name of last header processed by parseHederLine() + * + * Used to handle the headers that span multiple lines + * + * @var string + */ + protected $lastHeader = null; + + /** + * Response body + * @var string + */ + protected $body = ''; + + /** + * Whether the body is still encoded by Content-Encoding + * + * cURL provides the decoded body to the callback; if we are reading from + * socket the body is still gzipped / deflated + * + * @var bool + */ + protected $bodyEncoded; + + /** + * Associative array of HTTP status code / reason phrase. + * + * @var array + * @link http://tools.ietf.org/html/rfc2616#section-10 + */ + protected static $phrases = array( + + // 1xx: Informational - Request received, continuing process + 100 => 'Continue', + 101 => 'Switching Protocols', + + // 2xx: Success - The action was successfully received, understood and + // accepted + 200 => 'OK', + 201 => 'Created', + 202 => 'Accepted', + 203 => 'Non-Authoritative Information', + 204 => 'No Content', + 205 => 'Reset Content', + 206 => 'Partial Content', + + // 3xx: Redirection - Further action must be taken in order to complete + // the request + 300 => 'Multiple Choices', + 301 => 'Moved Permanently', + 302 => 'Found', // 1.1 + 303 => 'See Other', + 304 => 'Not Modified', + 305 => 'Use Proxy', + 307 => 'Temporary Redirect', + + // 4xx: Client Error - The request contains bad syntax or cannot be + // fulfilled + 400 => 'Bad Request', + 401 => 'Unauthorized', + 402 => 'Payment Required', + 403 => 'Forbidden', + 404 => 'Not Found', + 405 => 'Method Not Allowed', + 406 => 'Not Acceptable', + 407 => 'Proxy Authentication Required', + 408 => 'Request Timeout', + 409 => 'Conflict', + 410 => 'Gone', + 411 => 'Length Required', + 412 => 'Precondition Failed', + 413 => 'Request Entity Too Large', + 414 => 'Request-URI Too Long', + 415 => 'Unsupported Media Type', + 416 => 'Requested Range Not Satisfiable', + 417 => 'Expectation Failed', + + // 5xx: Server Error - The server failed to fulfill an apparently + // valid request + 500 => 'Internal Server Error', + 501 => 'Not Implemented', + 502 => 'Bad Gateway', + 503 => 'Service Unavailable', + 504 => 'Gateway Timeout', + 505 => 'HTTP Version Not Supported', + 509 => 'Bandwidth Limit Exceeded', + + ); + + /** + * Constructor, parses the response status line + * + * @param string Response status line (e.g. "HTTP/1.1 200 OK") + * @param bool Whether body is still encoded by Content-Encoding + * @throws HTTP_Request2_Exception if status line is invalid according to spec + */ + public function __construct($statusLine, $bodyEncoded = true) + { + if (!preg_match('!^HTTP/(\d\.\d) (\d{3})(?: (.+))?!', $statusLine, $m)) { + throw new HTTP_Request2_Exception("Malformed response: {$statusLine}"); + } + $this->version = $m[1]; + $this->code = intval($m[2]); + if (!empty($m[3])) { + $this->reasonPhrase = trim($m[3]); + } elseif (!empty(self::$phrases[$this->code])) { + $this->reasonPhrase = self::$phrases[$this->code]; + } + $this->bodyEncoded = (bool)$bodyEncoded; + } + + /** + * Parses the line from HTTP response filling $headers array + * + * The method should be called after reading the line from socket or receiving + * it into cURL callback. Passing an empty string here indicates the end of + * response headers and triggers additional processing, so be sure to pass an + * empty string in the end. + * + * @param string Line from HTTP response + */ + public function parseHeaderLine($headerLine) + { + $headerLine = trim($headerLine, "\r\n"); + + // empty string signals the end of headers, process the received ones + if ('' == $headerLine) { + if (!empty($this->headers['set-cookie'])) { + $cookies = is_array($this->headers['set-cookie'])? + $this->headers['set-cookie']: + array($this->headers['set-cookie']); + foreach ($cookies as $cookieString) { + $this->parseCookie($cookieString); + } + unset($this->headers['set-cookie']); + } + foreach (array_keys($this->headers) as $k) { + if (is_array($this->headers[$k])) { + $this->headers[$k] = implode(', ', $this->headers[$k]); + } + } + + // string of the form header-name: header value + } elseif (preg_match('!^([^\x00-\x1f\x7f-\xff()<>@,;:\\\\"/\[\]?={}\s]+):(.+)$!', $headerLine, $m)) { + $name = strtolower($m[1]); + $value = trim($m[2]); + if (empty($this->headers[$name])) { + $this->headers[$name] = $value; + } else { + if (!is_array($this->headers[$name])) { + $this->headers[$name] = array($this->headers[$name]); + } + $this->headers[$name][] = $value; + } + $this->lastHeader = $name; + + // string + } elseif (preg_match('!^\s+(.+)$!', $headerLine, $m) && $this->lastHeader) { + if (!is_array($this->headers[$this->lastHeader])) { + $this->headers[$this->lastHeader] .= ' ' . trim($m[1]); + } else { + $key = count($this->headers[$this->lastHeader]) - 1; + $this->headers[$this->lastHeader][$key] .= ' ' . trim($m[1]); + } + } + } + + /** + * Parses a Set-Cookie header to fill $cookies array + * + * @param string value of Set-Cookie header + * @link http://cgi.netscape.com/newsref/std/cookie_spec.html + */ + protected function parseCookie($cookieString) + { + $cookie = array( + 'expires' => null, + 'domain' => null, + 'path' => null, + 'secure' => false + ); + + // Only a name=value pair + if (!strpos($cookieString, ';')) { + $pos = strpos($cookieString, '='); + $cookie['name'] = trim(substr($cookieString, 0, $pos)); + $cookie['value'] = trim(substr($cookieString, $pos + 1)); + + // Some optional parameters are supplied + } else { + $elements = explode(';', $cookieString); + $pos = strpos($elements[0], '='); + $cookie['name'] = trim(substr($elements[0], 0, $pos)); + $cookie['value'] = trim(substr($elements[0], $pos + 1)); + + for ($i = 1; $i < count($elements); $i++) { + if (false === strpos($elements[$i], '=')) { + $elName = trim($elements[$i]); + $elValue = null; + } else { + list ($elName, $elValue) = array_map('trim', explode('=', $elements[$i])); + } + $elName = strtolower($elName); + if ('secure' == $elName) { + $cookie['secure'] = true; + } elseif ('expires' == $elName) { + $cookie['expires'] = str_replace('"', '', $elValue); + } elseif ('path' == $elName || 'domain' == $elName) { + $cookie[$elName] = urldecode($elValue); + } else { + $cookie[$elName] = $elValue; + } + } + } + $this->cookies[] = $cookie; + } + + /** + * Appends a string to the response body + * @param string + */ + public function appendBody($bodyChunk) + { + $this->body .= $bodyChunk; + } + + /** + * Returns the status code + * @return integer + */ + public function getStatus() + { + return $this->code; + } + + /** + * Returns the reason phrase + * @return string + */ + public function getReasonPhrase() + { + return $this->reasonPhrase; + } + + /** + * Returns either the named header or all response headers + * + * @param string Name of header to return + * @return string|array Value of $headerName header (null if header is + * not present), array of all response headers if + * $headerName is null + */ + public function getHeader($headerName = null) + { + if (null === $headerName) { + return $this->headers; + } else { + $headerName = strtolower($headerName); + return isset($this->headers[$headerName])? $this->headers[$headerName]: null; + } + } + + /** + * Returns cookies set in response + * + * @return array + */ + public function getCookies() + { + return $this->cookies; + } + + /** + * Returns the body of the response + * + * @return string + * @throws HTTP_Request2_Exception if body cannot be decoded + */ + public function getBody() + { + if (!$this->bodyEncoded || + !in_array(strtolower($this->getHeader('content-encoding')), array('gzip', 'deflate')) + ) { + return $this->body; + + } else { + if (extension_loaded('mbstring') && (2 & ini_get('mbstring.func_overload'))) { + $oldEncoding = mb_internal_encoding(); + mb_internal_encoding('iso-8859-1'); + } + + try { + switch (strtolower($this->getHeader('content-encoding'))) { + case 'gzip': + $decoded = self::decodeGzip($this->body); + break; + case 'deflate': + $decoded = self::decodeDeflate($this->body); + } + } catch (Exception $e) { + } + + if (!empty($oldEncoding)) { + mb_internal_encoding($oldEncoding); + } + if (!empty($e)) { + throw $e; + } + return $decoded; + } + } + + /** + * Get the HTTP version of the response + * + * @return string + */ + public function getVersion() + { + return $this->version; + } + + /** + * Decodes the message-body encoded by gzip + * + * The real decoding work is done by gzinflate() built-in function, this + * method only parses the header and checks data for compliance with + * RFC 1952 + * + * @param string gzip-encoded data + * @return string decoded data + * @throws HTTP_Request2_Exception + * @link http://tools.ietf.org/html/rfc1952 + */ + public static function decodeGzip($data) + { + $length = strlen($data); + // If it doesn't look like gzip-encoded data, don't bother + if (18 > $length || strcmp(substr($data, 0, 2), "\x1f\x8b")) { + return $data; + } + if (!function_exists('gzinflate')) { + throw new HTTP_Request2_Exception('Unable to decode body: gzip extension not available'); + } + $method = ord(substr($data, 2, 1)); + if (8 != $method) { + throw new HTTP_Request2_Exception('Error parsing gzip header: unknown compression method'); + } + $flags = ord(substr($data, 3, 1)); + if ($flags & 224) { + throw new HTTP_Request2_Exception('Error parsing gzip header: reserved bits are set'); + } + + // header is 10 bytes minimum. may be longer, though. + $headerLength = 10; + // extra fields, need to skip 'em + if ($flags & 4) { + if ($length - $headerLength - 2 < 8) { + throw new HTTP_Request2_Exception('Error parsing gzip header: data too short'); + } + $extraLength = unpack('v', substr($data, 10, 2)); + if ($length - $headerLength - 2 - $extraLength[1] < 8) { + throw new HTTP_Request2_Exception('Error parsing gzip header: data too short'); + } + $headerLength += $extraLength[1] + 2; + } + // file name, need to skip that + if ($flags & 8) { + if ($length - $headerLength - 1 < 8) { + throw new HTTP_Request2_Exception('Error parsing gzip header: data too short'); + } + $filenameLength = strpos(substr($data, $headerLength), chr(0)); + if (false === $filenameLength || $length - $headerLength - $filenameLength - 1 < 8) { + throw new HTTP_Request2_Exception('Error parsing gzip header: data too short'); + } + $headerLength += $filenameLength + 1; + } + // comment, need to skip that also + if ($flags & 16) { + if ($length - $headerLength - 1 < 8) { + throw new HTTP_Request2_Exception('Error parsing gzip header: data too short'); + } + $commentLength = strpos(substr($data, $headerLength), chr(0)); + if (false === $commentLength || $length - $headerLength - $commentLength - 1 < 8) { + throw new HTTP_Request2_Exception('Error parsing gzip header: data too short'); + } + $headerLength += $commentLength + 1; + } + // have a CRC for header. let's check + if ($flags & 2) { + if ($length - $headerLength - 2 < 8) { + throw new HTTP_Request2_Exception('Error parsing gzip header: data too short'); + } + $crcReal = 0xffff & crc32(substr($data, 0, $headerLength)); + $crcStored = unpack('v', substr($data, $headerLength, 2)); + if ($crcReal != $crcStored[1]) { + throw new HTTP_Request2_Exception('Header CRC check failed'); + } + $headerLength += 2; + } + // unpacked data CRC and size at the end of encoded data + $tmp = unpack('V2', substr($data, -8)); + $dataCrc = $tmp[1]; + $dataSize = $tmp[2]; + + // finally, call the gzinflate() function + // don't pass $dataSize to gzinflate, see bugs #13135, #14370 + $unpacked = gzinflate(substr($data, $headerLength, -8)); + if (false === $unpacked) { + throw new HTTP_Request2_Exception('gzinflate() call failed'); + } elseif ($dataSize != strlen($unpacked)) { + throw new HTTP_Request2_Exception('Data size check failed'); + } elseif ((0xffffffff & $dataCrc) != (0xffffffff & crc32($unpacked))) { + throw new HTTP_Request2_Exception('Data CRC check failed'); + } + return $unpacked; + } + + /** + * Decodes the message-body encoded by deflate + * + * @param string deflate-encoded data + * @return string decoded data + * @throws HTTP_Request2_Exception + */ + public static function decodeDeflate($data) + { + if (!function_exists('gzuncompress')) { + throw new HTTP_Request2_Exception('Unable to decode body: gzip extension not available'); + } + // RFC 2616 defines 'deflate' encoding as zlib format from RFC 1950, + // while many applications send raw deflate stream from RFC 1951. + // We should check for presence of zlib header and use gzuncompress() or + // gzinflate() as needed. See bug #15305 + $header = unpack('n', substr($data, 0, 2)); + return (0 == $header[1] % 31)? gzuncompress($data): gzinflate($data); + } +} +?> \ No newline at end of file diff --git a/extlib/Net/URL2.php b/extlib/Net/URL2.php index 7a654aed8..f7fbcd9ce 100644 --- a/extlib/Net/URL2.php +++ b/extlib/Net/URL2.php @@ -1,44 +1,58 @@ | -// +-----------------------------------------------------------------------+ -// -// $Id: URL2.php,v 1.10 2008/04/26 21:57:08 schmidt Exp $ -// -// Net_URL2 Class (PHP5 Only) - -// This code is released under the BSD License - http://www.opensource.org/licenses/bsd-license.php /** - * @license BSD License + * Net_URL2, a class representing a URL as per RFC 3986. + * + * PHP version 5 + * + * LICENSE: + * + * Copyright (c) 2007-2009, Peytz & Co. A/S + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * * Neither the name of the PHP_LexerGenerator nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category Networking + * @package Net_URL2 + * @author Christian Schmidt + * @copyright 2007-2008 Peytz & Co. A/S + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: URL2.php 286661 2009-08-02 12:50:54Z schmidt $ + * @link http://www.rfc-editor.org/rfc/rfc3986.txt + */ + +/** + * Represents a URL as per RFC 3986. + * + * @category Networking + * @package Net_URL2 + * @author Christian Schmidt + * @copyright 2007-2008 Peytz & Co. ApS + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version Release: @package_version@ + * @link http://pear.php.net/package/Net_URL2 */ class Net_URL2 { @@ -46,24 +60,24 @@ class Net_URL2 * Do strict parsing in resolve() (see RFC 3986, section 5.2.2). Default * is true. */ - const OPTION_STRICT = 'strict'; + const OPTION_STRICT = 'strict'; /** * Represent arrays in query using PHP's [] notation. Default is true. */ - const OPTION_USE_BRACKETS = 'use_brackets'; + const OPTION_USE_BRACKETS = 'use_brackets'; /** * URL-encode query variable keys. Default is true. */ - const OPTION_ENCODE_KEYS = 'encode_keys'; + const OPTION_ENCODE_KEYS = 'encode_keys'; /** * Query variable separators when parsing the query string. Every character * is considered a separator. Default is specified by the * arg_separator.input php.ini setting (this defaults to "&"). */ - const OPTION_SEPARATOR_INPUT = 'input_separator'; + const OPTION_SEPARATOR_INPUT = 'input_separator'; /** * Query variable separator used when generating the query string. Default @@ -75,7 +89,7 @@ class Net_URL2 /** * Default options corresponds to how PHP handles $_GET. */ - private $options = array( + private $_options = array( self::OPTION_STRICT => true, self::OPTION_USE_BRACKETS => true, self::OPTION_ENCODE_KEYS => true, @@ -86,41 +100,43 @@ class Net_URL2 /** * @var string|bool */ - private $scheme = false; + private $_scheme = false; /** * @var string|bool */ - private $userinfo = false; + private $_userinfo = false; /** * @var string|bool */ - private $host = false; + private $_host = false; /** * @var int|bool */ - private $port = false; + private $_port = false; /** * @var string */ - private $path = ''; + private $_path = ''; /** * @var string|bool */ - private $query = false; + private $_query = false; /** * @var string|bool */ - private $fragment = false; + private $_fragment = false; /** + * Constructor. + * * @param string $url an absolute or relative URL - * @param array $options + * @param array $options an array of OPTION_xxx constants */ public function __construct($url, $options = null) { @@ -130,12 +146,12 @@ class Net_URL2 ini_get('arg_separator.output')); if (is_array($options)) { foreach ($options as $optionName => $value) { - $this->setOption($optionName); + $this->setOption($optionName, $value); } } if (preg_match('@^([a-z][a-z0-9.+-]*):@i', $url, $reg)) { - $this->scheme = $reg[1]; + $this->_scheme = $reg[1]; $url = substr($url, strlen($reg[0])); } @@ -145,19 +161,58 @@ class Net_URL2 } $i = strcspn($url, '?#'); - $this->path = substr($url, 0, $i); + $this->_path = substr($url, 0, $i); $url = substr($url, $i); if (preg_match('@^\?([^#]*)@', $url, $reg)) { - $this->query = $reg[1]; + $this->_query = $reg[1]; $url = substr($url, strlen($reg[0])); } if ($url) { - $this->fragment = substr($url, 1); + $this->_fragment = substr($url, 1); } } + /** + * Magic Setter. + * + * This method will magically set the value of a private variable ($var) + * with the value passed as the args + * + * @param string $var The private variable to set. + * @param mixed $arg An argument of any type. + * @return void + */ + public function __set($var, $arg) + { + $method = 'set' . $var; + if (method_exists($this, $method)) { + $this->$method($arg); + } + } + + /** + * Magic Getter. + * + * This is the magic get method to retrieve the private variable + * that was set by either __set() or it's setter... + * + * @param string $var The property name to retrieve. + * @return mixed $this->$var Either a boolean false if the + * property is not set or the value + * of the private property. + */ + public function __get($var) + { + $method = 'get' . $var; + if (method_exists($this, $method)) { + return $this->$method(); + } + + return false; + } + /** * Returns the scheme, e.g. "http" or "urn", or false if there is no * scheme specified, i.e. if this is a relative URL. @@ -166,18 +221,23 @@ class Net_URL2 */ public function getScheme() { - return $this->scheme; + return $this->_scheme; } /** - * @param string|bool $scheme + * Sets the scheme, e.g. "http" or "urn". Specify false if there is no + * scheme specified, i.e. if this is a relative URL. + * + * @param string|bool $scheme e.g. "http" or "urn", or false if there is no + * scheme specified, i.e. if this is a relative + * URL * * @return void * @see getScheme() */ public function setScheme($scheme) { - $this->scheme = $scheme; + $this->_scheme = $scheme; } /** @@ -188,7 +248,9 @@ class Net_URL2 */ public function getUser() { - return $this->userinfo !== false ? preg_replace('@:.*$@', '', $this->userinfo) : false; + return $this->_userinfo !== false + ? preg_replace('@:.*$@', '', $this->_userinfo) + : false; } /** @@ -201,7 +263,9 @@ class Net_URL2 */ public function getPassword() { - return $this->userinfo !== false ? substr(strstr($this->userinfo, ':'), 1) : false; + return $this->_userinfo !== false + ? substr(strstr($this->_userinfo, ':'), 1) + : false; } /** @@ -212,7 +276,7 @@ class Net_URL2 */ public function getUserinfo() { - return $this->userinfo; + return $this->_userinfo; } /** @@ -220,15 +284,15 @@ class Net_URL2 * in the userinfo part as username ":" password. * * @param string|bool $userinfo userinfo or username - * @param string|bool $password + * @param string|bool $password optional password, or false * * @return void */ public function setUserinfo($userinfo, $password = false) { - $this->userinfo = $userinfo; + $this->_userinfo = $userinfo; if ($password !== false) { - $this->userinfo .= ':' . $password; + $this->_userinfo .= ':' . $password; } } @@ -236,21 +300,24 @@ class Net_URL2 * Returns the host part, or false if there is no authority part, e.g. * relative URLs. * - * @return string|bool + * @return string|bool a hostname, an IP address, or false */ public function getHost() { - return $this->host; + return $this->_host; } /** - * @param string|bool $host + * Sets the host part. Specify false if there is no authority part, e.g. + * relative URLs. + * + * @param string|bool $host a hostname, an IP address, or false * * @return void */ public function setHost($host) { - $this->host = $host; + $this->_host = $host; } /** @@ -261,65 +328,72 @@ class Net_URL2 */ public function getPort() { - return $this->port; + return $this->_port; } /** - * @param int|bool $port + * Sets the port number. Specify false if there is no port number specified, + * i.e. if the default port is to be used. + * + * @param int|bool $port a port number, or false * * @return void */ public function setPort($port) { - $this->port = intval($port); + $this->_port = intval($port); } /** * Returns the authority part, i.e. [ userinfo "@" ] host [ ":" port ], or - * false if there is no authority none. + * false if there is no authority. * * @return string|bool */ public function getAuthority() { - if (!$this->host) { + if (!$this->_host) { return false; } $authority = ''; - if ($this->userinfo !== false) { - $authority .= $this->userinfo . '@'; + if ($this->_userinfo !== false) { + $authority .= $this->_userinfo . '@'; } - $authority .= $this->host; + $authority .= $this->_host; - if ($this->port !== false) { - $authority .= ':' . $this->port; + if ($this->_port !== false) { + $authority .= ':' . $this->_port; } return $authority; } /** - * @param string|false $authority + * Sets the authority part, i.e. [ userinfo "@" ] host [ ":" port ]. Specify + * false if there is no authority. + * + * @param string|false $authority a hostname or an IP addresse, possibly + * with userinfo prefixed and port number + * appended, e.g. "foo:bar@example.org:81". * * @return void */ public function setAuthority($authority) { - $this->user = false; - $this->pass = false; - $this->host = false; - $this->port = false; - if (preg_match('@^(([^\@]+)\@)?([^:]+)(:(\d*))?$@', $authority, $reg)) { + $this->_userinfo = false; + $this->_host = false; + $this->_port = false; + if (preg_match('@^(([^\@]*)\@)?([^:]+)(:(\d*))?$@', $authority, $reg)) { if ($reg[1]) { - $this->userinfo = $reg[2]; + $this->_userinfo = $reg[2]; } - $this->host = $reg[3]; + $this->_host = $reg[3]; if (isset($reg[5])) { - $this->port = intval($reg[5]); + $this->_port = intval($reg[5]); } } } @@ -331,65 +405,74 @@ class Net_URL2 */ public function getPath() { - return $this->path; + return $this->_path; } /** - * @param string $path + * Sets the path part (possibly an empty string). + * + * @param string $path a path * * @return void */ public function setPath($path) { - $this->path = $path; + $this->_path = $path; } /** * Returns the query string (excluding the leading "?"), or false if "?" - * isn't present in the URL. + * is not present in the URL. * * @return string|bool * @see self::getQueryVariables() */ public function getQuery() { - return $this->query; + return $this->_query; } /** - * @param string|bool $query + * Sets the query string (excluding the leading "?"). Specify false if "?" + * is not present in the URL. + * + * @param string|bool $query a query string, e.g. "foo=1&bar=2" * * @return void * @see self::setQueryVariables() */ public function setQuery($query) { - $this->query = $query; + $this->_query = $query; } /** - * Returns the fragment name, or false if "#" isn't present in the URL. + * Returns the fragment name, or false if "#" is not present in the URL. * * @return string|bool */ public function getFragment() { - return $this->fragment; + return $this->_fragment; } /** - * @param string|bool $fragment + * Sets the fragment name. Specify false if "#" is not present in the URL. + * + * @param string|bool $fragment a fragment excluding the leading "#", or + * false * * @return void */ public function setFragment($fragment) { - $this->fragment = $fragment; + $this->_fragment = $fragment; } /** * Returns the query string like an array as the variables would appear in - * $_GET in a PHP script. + * $_GET in a PHP script. If the URL does not contain a "?", an empty array + * is returned. * * @return array */ @@ -398,7 +481,7 @@ class Net_URL2 $pattern = '/[' . preg_quote($this->getOption(self::OPTION_SEPARATOR_INPUT), '/') . ']/'; - $parts = preg_split($pattern, $this->query, -1, PREG_SPLIT_NO_EMPTY); + $parts = preg_split($pattern, $this->_query, -1, PREG_SPLIT_NO_EMPTY); $return = array(); foreach ($parts as $part) { @@ -445,6 +528,8 @@ class Net_URL2 } /** + * Sets the query string to the specified variable in the query string. + * * @param array $array (name => value) array * * @return void @@ -452,11 +537,11 @@ class Net_URL2 public function setQueryVariables(array $array) { if (!$array) { - $this->query = false; + $this->_query = false; } else { foreach ($array as $name => $value) { if ($this->getOption(self::OPTION_ENCODE_KEYS)) { - $name = rawurlencode($name); + $name = self::urlencode($name); } if (is_array($value)) { @@ -466,19 +551,21 @@ class Net_URL2 : ($name . '=' . $v); } } elseif (!is_null($value)) { - $parts[] = $name . '=' . $value; + $parts[] = $name . '=' . self::urlencode($value); } else { $parts[] = $name; } } - $this->query = implode($this->getOption(self::OPTION_SEPARATOR_OUTPUT), - $parts); + $this->_query = implode($this->getOption(self::OPTION_SEPARATOR_OUTPUT), + $parts); } } /** - * @param string $name - * @param mixed $value + * Sets the specified variable in the query string. + * + * @param string $name variable name + * @param mixed $value variable value * * @return array */ @@ -490,7 +577,9 @@ class Net_URL2 } /** - * @param string $name + * Removes the specifed variable from the query string. + * + * @param string $name a query string variable, e.g. "foo" in "?foo=1" * * @return void */ @@ -511,27 +600,38 @@ class Net_URL2 // See RFC 3986, section 5.3 $url = ""; - if ($this->scheme !== false) { - $url .= $this->scheme . ':'; + if ($this->_scheme !== false) { + $url .= $this->_scheme . ':'; } $authority = $this->getAuthority(); if ($authority !== false) { $url .= '//' . $authority; } - $url .= $this->path; + $url .= $this->_path; - if ($this->query !== false) { - $url .= '?' . $this->query; + if ($this->_query !== false) { + $url .= '?' . $this->_query; } - if ($this->fragment !== false) { - $url .= '#' . $this->fragment; + if ($this->_fragment !== false) { + $url .= '#' . $this->_fragment; } return $url; } + /** + * Returns a string representation of this URL. + * + * @return string + * @see toString() + */ + public function __toString() + { + return $this->getURL(); + } + /** * Returns a normalized string representation of this URL. This is useful * for comparison of URLs. @@ -555,36 +655,38 @@ class Net_URL2 // See RFC 3886, section 6 // Schemes are case-insensitive - if ($this->scheme) { - $this->scheme = strtolower($this->scheme); + if ($this->_scheme) { + $this->_scheme = strtolower($this->_scheme); } // Hostnames are case-insensitive - if ($this->host) { - $this->host = strtolower($this->host); + if ($this->_host) { + $this->_host = strtolower($this->_host); } // Remove default port number for known schemes (RFC 3986, section 6.2.3) - if ($this->port && - $this->scheme && - $this->port == getservbyname($this->scheme, 'tcp')) { + if ($this->_port && + $this->_scheme && + $this->_port == getservbyname($this->_scheme, 'tcp')) { - $this->port = false; + $this->_port = false; } // Normalize case of %XX percentage-encodings (RFC 3986, section 6.2.2.1) - foreach (array('userinfo', 'host', 'path') as $part) { + foreach (array('_userinfo', '_host', '_path') as $part) { if ($this->$part) { - $this->$part = preg_replace('/%[0-9a-f]{2}/ie', 'strtoupper("\0")', $this->$part); + $this->$part = preg_replace('/%[0-9a-f]{2}/ie', + 'strtoupper("\0")', + $this->$part); } } // Path segment normalization (RFC 3986, section 6.2.2.3) - $this->path = self::removeDotSegments($this->path); + $this->_path = self::removeDotSegments($this->_path); // Scheme based normalization (RFC 3986, section 6.2.3) - if ($this->host && !$this->path) { - $this->path = '/'; + if ($this->_host && !$this->_path) { + $this->_path = '/'; } } @@ -595,7 +697,7 @@ class Net_URL2 */ public function isAbsolute() { - return (bool) $this->scheme; + return (bool) $this->_scheme; } /** @@ -608,7 +710,7 @@ class Net_URL2 */ public function resolve($reference) { - if (is_string($reference)) { + if (!$reference instanceof Net_URL2) { $reference = new self($reference); } if (!$this->isAbsolute()) { @@ -617,54 +719,54 @@ class Net_URL2 // A non-strict parser may ignore a scheme in the reference if it is // identical to the base URI's scheme. - if (!$this->getOption(self::OPTION_STRICT) && $reference->scheme == $this->scheme) { - $reference->scheme = false; + if (!$this->getOption(self::OPTION_STRICT) && $reference->_scheme == $this->_scheme) { + $reference->_scheme = false; } $target = new self(''); - if ($reference->scheme !== false) { - $target->scheme = $reference->scheme; + if ($reference->_scheme !== false) { + $target->_scheme = $reference->_scheme; $target->setAuthority($reference->getAuthority()); - $target->path = self::removeDotSegments($reference->path); - $target->query = $reference->query; + $target->_path = self::removeDotSegments($reference->_path); + $target->_query = $reference->_query; } else { $authority = $reference->getAuthority(); if ($authority !== false) { $target->setAuthority($authority); - $target->path = self::removeDotSegments($reference->path); - $target->query = $reference->query; + $target->_path = self::removeDotSegments($reference->_path); + $target->_query = $reference->_query; } else { - if ($reference->path == '') { - $target->path = $this->path; - if ($reference->query !== false) { - $target->query = $reference->query; + if ($reference->_path == '') { + $target->_path = $this->_path; + if ($reference->_query !== false) { + $target->_query = $reference->_query; } else { - $target->query = $this->query; + $target->_query = $this->_query; } } else { - if (substr($reference->path, 0, 1) == '/') { - $target->path = self::removeDotSegments($reference->path); + if (substr($reference->_path, 0, 1) == '/') { + $target->_path = self::removeDotSegments($reference->_path); } else { // Merge paths (RFC 3986, section 5.2.3) - if ($this->host !== false && $this->path == '') { - $target->path = '/' . $this->path; + if ($this->_host !== false && $this->_path == '') { + $target->_path = '/' . $this->_path; } else { - $i = strrpos($this->path, '/'); + $i = strrpos($this->_path, '/'); if ($i !== false) { - $target->path = substr($this->path, 0, $i + 1); + $target->_path = substr($this->_path, 0, $i + 1); } - $target->path .= $reference->path; + $target->_path .= $reference->_path; } - $target->path = self::removeDotSegments($target->path); + $target->_path = self::removeDotSegments($target->_path); } - $target->query = $reference->query; + $target->_query = $reference->_query; } $target->setAuthority($this->getAuthority()); } - $target->scheme = $this->scheme; + $target->_scheme = $this->_scheme; } - $target->fragment = $reference->fragment; + $target->_fragment = $reference->_fragment; return $target; } @@ -677,7 +779,7 @@ class Net_URL2 * * @return string a path */ - private static function removeDotSegments($path) + public static function removeDotSegments($path) { $output = ''; @@ -685,28 +787,25 @@ class Net_URL2 // method $j = 0; while ($path && $j++ < 100) { - // Step A if (substr($path, 0, 2) == './') { + // Step 2.A $path = substr($path, 2); } elseif (substr($path, 0, 3) == '../') { + // Step 2.A $path = substr($path, 3); - - // Step B } elseif (substr($path, 0, 3) == '/./' || $path == '/.') { + // Step 2.B $path = '/' . substr($path, 3); - - // Step C } elseif (substr($path, 0, 4) == '/../' || $path == '/..') { - $path = '/' . substr($path, 4); - $i = strrpos($output, '/'); + // Step 2.C + $path = '/' . substr($path, 4); + $i = strrpos($output, '/'); $output = $i === false ? '' : substr($output, 0, $i); - - // Step D } elseif ($path == '.' || $path == '..') { + // Step 2.D $path = ''; - - // Step E } else { + // Step 2.E $i = strpos($path, '/'); if ($i === 0) { $i = strpos($path, '/', 1); @@ -722,6 +821,22 @@ class Net_URL2 return $output; } + /** + * Percent-encodes all non-alphanumeric characters except these: _ . - ~ + * Similar to PHP's rawurlencode(), except that it also encodes ~ in PHP + * 5.2.x and earlier. + * + * @param $raw the string to encode + * @return string + */ + public static function urlencode($string) + { + $encoded = rawurlencode($string); + // This is only necessary in PHP < 5.3. + $encoded = str_replace('%7E', '~', $encoded); + return $encoded; + } + /** * Returns a Net_URL2 instance representing the canonical URL of the * currently executing PHP script. @@ -737,13 +852,13 @@ class Net_URL2 // Begin with a relative URL $url = new self($_SERVER['PHP_SELF']); - $url->scheme = isset($_SERVER['HTTPS']) ? 'https' : 'http'; - $url->host = $_SERVER['SERVER_NAME']; + $url->_scheme = isset($_SERVER['HTTPS']) ? 'https' : 'http'; + $url->_host = $_SERVER['SERVER_NAME']; $port = intval($_SERVER['SERVER_PORT']); - if ($url->scheme == 'http' && $port != 80 || - $url->scheme == 'https' && $port != 443) { + if ($url->_scheme == 'http' && $port != 80 || + $url->_scheme == 'https' && $port != 443) { - $url->port = $port; + $url->_port = $port; } return $url; } @@ -773,7 +888,7 @@ class Net_URL2 // Begin with a relative URL $url = new self($_SERVER['REQUEST_URI']); - $url->scheme = isset($_SERVER['HTTPS']) ? 'https' : 'http'; + $url->_scheme = isset($_SERVER['HTTPS']) ? 'https' : 'http'; // Set host and possibly port $url->setAuthority($_SERVER['HTTP_HOST']); return $url; @@ -792,10 +907,10 @@ class Net_URL2 */ function setOption($optionName, $value) { - if (!array_key_exists($optionName, $this->options)) { + if (!array_key_exists($optionName, $this->_options)) { return false; } - $this->options[$optionName] = $value; + $this->_options[$optionName] = $value; } /** @@ -807,7 +922,7 @@ class Net_URL2 */ function getOption($optionName) { - return isset($this->options[$optionName]) - ? $this->options[$optionName] : false; + return isset($this->_options[$optionName]) + ? $this->_options[$optionName] : false; } } diff --git a/install.php b/install.php index 6bfc4c2e2..d34e92dab 100644 --- a/install.php +++ b/install.php @@ -93,6 +93,13 @@ $external_libraries=array( 'include'=>'HTTP/Request.php', 'check_class'=>'HTTP_Request' ), + array( + 'name'=>'HTTP_Request2', + 'pear'=>'HTTP_Request2', + 'url'=>'http://pear.php.net/package/HTTP_Request2', + 'include'=>'HTTP/Request2.php', + 'check_class'=>'HTTP_Request2' + ), array( 'name'=>'Mail', 'pear'=>'Mail', diff --git a/lib/Shorturl_api.php b/lib/Shorturl_api.php index 18ae7719b..de4d55012 100644 --- a/lib/Shorturl_api.php +++ b/lib/Shorturl_api.php @@ -41,22 +41,18 @@ abstract class ShortUrlApi return strlen($url) >= common_config('site', 'shorturllength'); } - protected function http_post($data) { - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $this->service_url); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch, CURLOPT_POST, 1); - curl_setopt($ch, CURLOPT_POSTFIELDS, $data); - $response = curl_exec($ch); - $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); - curl_close($ch); - if (($code < 200) || ($code >= 400)) return false; - return $response; + protected function http_post($data) + { + $request = HTTPClient::start(); + $response = $request->post($this->service_url, null, $data); + return $response->getBody(); } - protected function http_get($url) { - $encoded_url = urlencode($url); - return file_get_contents("{$this->service_url}$encoded_url"); + protected function http_get($url) + { + $request = HTTPClient::start(); + $response = $request->get($this->service_url . urlencode($url)); + return $response->getBody(); } protected function tidy($response) { diff --git a/lib/curlclient.php b/lib/curlclient.php deleted file mode 100644 index c307c2984..000000000 --- a/lib/curlclient.php +++ /dev/null @@ -1,179 +0,0 @@ -. - * - * @category HTTP - * @package StatusNet - * @author Evan Prodromou - * @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')) { - exit(1); -} - -define(CURLCLIENT_VERSION, "0.1"); - -/** - * Wrapper for Curl - * - * Makes Curl HTTP client calls within our HTTPClient framework - * - * @category HTTP - * @package StatusNet - * @author Evan Prodromou - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://status.net/ - */ - -class CurlClient extends HTTPClient -{ - function __construct() - { - } - - function head($url, $headers=null) - { - $ch = curl_init($url); - - $this->setup($ch); - - curl_setopt_array($ch, - array(CURLOPT_NOBODY => true)); - - if (!is_null($headers)) { - curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); - } - - $result = curl_exec($ch); - - curl_close($ch); - - return $this->parseResults($result); - } - - function get($url, $headers=null) - { - $ch = curl_init($url); - - $this->setup($ch); - - if (!is_null($headers)) { - curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); - } - - $result = curl_exec($ch); - - curl_close($ch); - - return $this->parseResults($result); - } - - function post($url, $headers=null, $body=null) - { - $ch = curl_init($url); - - $this->setup($ch); - - curl_setopt($ch, CURLOPT_POST, true); - - if (!is_null($body)) { - curl_setopt($ch, CURLOPT_POSTFIELDS, $body); - } - - if (!is_null($headers)) { - curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); - } - - $result = curl_exec($ch); - - curl_close($ch); - - return $this->parseResults($result); - } - - function setup($ch) - { - curl_setopt_array($ch, - array(CURLOPT_USERAGENT => $this->userAgent(), - CURLOPT_HEADER => true, - CURLOPT_RETURNTRANSFER => true)); - } - - function userAgent() - { - $version = curl_version(); - return parent::userAgent() . " CurlClient/".CURLCLIENT_VERSION . " cURL/" . $version['version']; - } - - function parseResults($results) - { - $resp = new HTTPResponse(); - - $lines = explode("\r\n", $results); - - if (preg_match("#^HTTP/1.[01] (\d\d\d) .+$#", $lines[0], $match)) { - $resp->code = $match[1]; - } else { - throw Exception("Bad format: initial line is not HTTP status line"); - } - - $lastk = null; - - for ($i = 1; $i < count($lines); $i++) { - $l =& $lines[$i]; - if (mb_strlen($l) == 0) { - $resp->body = implode("\r\n", array_slice($lines, $i + 1)); - break; - } - if (preg_match("#^(\S+):\s+(.*)$#", $l, $match)) { - $k = $match[1]; - $v = $match[2]; - - if (array_key_exists($k, $resp->headers)) { - if (is_array($resp->headers[$k])) { - $resp->headers[$k][] = $v; - } else { - $resp->headers[$k] = array($resp->headers[$k], $v); - } - } else { - $resp->headers[$k] = $v; - } - $lastk = $k; - } else if (preg_match("#^\s+(.*)$#", $l, $match)) { - // continuation line - if (is_null($lastk)) { - throw Exception("Bad format: initial whitespace in headers"); - } - $h =& $resp->headers[$lastk]; - if (is_array($h)) { - $n = count($h); - $h[$n-1] .= $match[1]; - } else { - $h .= $match[1]; - } - } - } - - return $resp; - } -} diff --git a/lib/default.php b/lib/default.php index 7ec8558b0..f6cc4b725 100644 --- a/lib/default.php +++ b/lib/default.php @@ -228,8 +228,6 @@ $default = array('contentlimit' => null), 'message' => array('contentlimit' => null), - 'http' => - array('client' => 'curl'), // XXX: should this be the default? 'location' => array('namespace' => 1), // 1 = geonames, 2 = Yahoo Where on Earth ); diff --git a/lib/httpclient.php b/lib/httpclient.php index f16e31e10..3f8262076 100644 --- a/lib/httpclient.php +++ b/lib/httpclient.php @@ -31,6 +31,9 @@ if (!defined('STATUSNET')) { exit(1); } +require_once 'HTTP/Request2.php'; +require_once 'HTTP/Request2/Response.php'; + /** * Useful structure for HTTP responses * @@ -38,18 +41,53 @@ if (!defined('STATUSNET')) { * ways of doing them. This class hides the specifics of what underlying * library (curl or PHP-HTTP or whatever) that's used. * + * This extends the HTTP_Request2_Response class with methods to get info + * about any followed redirects. + * * @category HTTP - * @package StatusNet - * @author Evan Prodromou - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://status.net/ + * @package StatusNet + * @author Evan Prodromou + * @author Brion Vibber + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ */ - -class HTTPResponse +class HTTPResponse extends HTTP_Request2_Response { - public $code = null; - public $headers = array(); - public $body = null; + function __construct(HTTP_Request2_Response $response, $url, $redirects=0) + { + foreach (get_object_vars($response) as $key => $val) { + $this->$key = $val; + } + $this->url = strval($url); + $this->redirectCount = intval($redirects); + } + + /** + * Get the count of redirects that have been followed, if any. + * @return int + */ + function getRedirectCount() + { + return $this->redirectCount; + } + + /** + * Gets the final target URL, after any redirects have been followed. + * @return string URL + */ + function getUrl() + { + return $this->url; + } + + /** + * Check if the response is OK, generally a 200 status code. + * @return bool + */ + function isOk() + { + return ($this->getStatus() == 200); + } } /** @@ -59,64 +97,163 @@ class HTTPResponse * ways of doing them. This class hides the specifics of what underlying * library (curl or PHP-HTTP or whatever) that's used. * + * This extends the PEAR HTTP_Request2 package: + * - sends StatusNet-specific User-Agent header + * - 'follow_redirects' config option, defaulting off + * - 'max_redirs' config option, defaulting to 10 + * - extended response class adds getRedirectCount() and getUrl() methods + * - get() and post() convenience functions return body content directly + * * @category HTTP * @package StatusNet * @author Evan Prodromou + * @author Brion Vibber * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ */ -class HTTPClient +class HTTPClient extends HTTP_Request2 { - static $_client = null; - static function start() + function __construct($url=null, $method=self::METHOD_GET, $config=array()) { - if (!is_null(self::$_client)) { - return self::$_client; - } - - $type = common_config('http', 'client'); - - switch ($type) { - case 'curl': - self::$_client = new CurlClient(); - break; - default: - throw new Exception("Unknown HTTP client type '$type'"); - break; - } - - return self::$_client; + $this->config['max_redirs'] = 10; + $this->config['follow_redirects'] = true; + parent::__construct($url, $method, $config); + $this->setHeader('User-Agent', $this->userAgent()); } - function head($url, $headers) + /** + * Convenience/back-compat instantiator + * @return HTTPClient + */ + public static function start() { - throw new Exception("HEAD method unimplemented"); + return new HTTPClient(); } - function get($url, $headers) + /** + * Convenience function to run a GET request. + * + * @return HTTPResponse + * @throws HTTP_Request2_Exception + */ + public function get($url, $headers=array()) { - throw new Exception("GET method unimplemented"); + return $this->doRequest($url, self::METHOD_GET, $headers); } - function post($url, $headers, $body) + /** + * Convenience function to run a HEAD request. + * + * @return HTTPResponse + * @throws HTTP_Request2_Exception + */ + public function head($url, $headers=array()) { - throw new Exception("POST method unimplemented"); + return $this->doRequest($url, self::METHOD_HEAD, $headers); } - function put($url, $headers, $body) + /** + * Convenience function to POST form data. + * + * @param string $url + * @param array $headers optional associative array of HTTP headers + * @param array $data optional associative array or blob of form data to submit + * @return HTTPResponse + * @throws HTTP_Request2_Exception + */ + public function post($url, $headers=array(), $data=array()) { - throw new Exception("PUT method unimplemented"); + if ($data) { + $this->addPostParameter($data); + } + return $this->doRequest($url, self::METHOD_POST, $headers); } - function delete($url, $headers) + /** + * @return HTTPResponse + * @throws HTTP_Request2_Exception + */ + protected function doRequest($url, $method, $headers) { - throw new Exception("DELETE method unimplemented"); + $this->setUrl($url); + $this->setMethod($method); + if ($headers) { + foreach ($headers as $header) { + $this->setHeader($header); + } + } + $response = $this->send(); + return $response; + } + + protected function log($level, $detail) { + $method = $this->getMethod(); + $url = $this->getUrl(); + common_log($level, __CLASS__ . ": HTTP $method $url - $detail"); } + /** + * Pulls up StatusNet's customized user-agent string, so services + * we hit can track down the responsible software. + * + * @return string + */ function userAgent() { return "StatusNet/".STATUSNET_VERSION." (".STATUSNET_CODENAME.")"; } + + /** + * Actually performs the HTTP request and returns an HTTPResponse object + * with response body and header info. + * + * Wraps around parent send() to add logging and redirection processing. + * + * @return HTTPResponse + * @throw HTTP_Request2_Exception + */ + public function send() + { + $maxRedirs = intval($this->config['max_redirs']); + if (empty($this->config['follow_redirects'])) { + $maxRedirs = 0; + } + $redirs = 0; + do { + try { + $response = parent::send(); + } catch (HTTP_Request2_Exception $e) { + $this->log(LOG_ERR, $e->getMessage()); + throw $e; + } + $code = $response->getStatus(); + if ($code >= 200 && $code < 300) { + $reason = $response->getReasonPhrase(); + $this->log(LOG_INFO, "$code $reason"); + } elseif ($code >= 300 && $code < 400) { + $url = $this->getUrl(); + $target = $response->getHeader('Location'); + + if (++$redirs >= $maxRedirs) { + common_log(LOG_ERR, __CLASS__ . ": Too many redirects: skipping $code redirect from $url to $target"); + break; + } + try { + $this->setUrl($target); + $this->setHeader('Referer', $url); + common_log(LOG_INFO, __CLASS__ . ": Following $code redirect from $url to $target"); + continue; + } catch (HTTP_Request2_Exception $e) { + common_log(LOG_ERR, __CLASS__ . ": Invalid $code redirect from $url to $target"); + } + } else { + $reason = $response->getReasonPhrase(); + $this->log(LOG_ERR, "$code $reason"); + } + break; + } while ($maxRedirs); + return new HTTPResponse($response, $this->getUrl(), $redirs); + } } diff --git a/lib/oauthclient.php b/lib/oauthclient.php index f1827726e..1a86e2460 100644 --- a/lib/oauthclient.php +++ b/lib/oauthclient.php @@ -43,7 +43,7 @@ require_once 'OAuth.php'; * @link http://status.net/ * */ -class OAuthClientCurlException extends Exception +class OAuthClientException extends Exception { } @@ -97,9 +97,14 @@ class OAuthClient function getRequestToken($url) { $response = $this->oAuthGet($url); - parse_str($response); - $token = new OAuthToken($oauth_token, $oauth_token_secret); - return $token; + $arr = array(); + parse_str($response, $arr); + if (isset($arr['oauth_token']) && isset($arr['oauth_token_secret'])) { + $token = new OAuthToken($arr['oauth_token'], @$arr['oauth_token_secret']); + return $token; + } else { + throw new OAuthClientException(); + } } /** @@ -177,7 +182,7 @@ class OAuthClient } /** - * Make a HTTP request using cURL. + * Make a HTTP request. * * @param string $url Where to make the * @param array $params post parameters @@ -186,40 +191,32 @@ class OAuthClient */ function httpRequest($url, $params = null) { - $options = array( - CURLOPT_RETURNTRANSFER => true, - CURLOPT_FAILONERROR => true, - CURLOPT_HEADER => false, - CURLOPT_FOLLOWLOCATION => true, - CURLOPT_USERAGENT => 'StatusNet', - CURLOPT_CONNECTTIMEOUT => 120, - CURLOPT_TIMEOUT => 120, - CURLOPT_HTTPAUTH => CURLAUTH_ANY, - CURLOPT_SSL_VERIFYPEER => false, - - // Twitter is strict about accepting invalid "Expect" headers - - CURLOPT_HTTPHEADER => array('Expect:') - ); + $request = new HTTPClient($url); + $request->setConfig(array( + 'connect_timeout' => 120, + 'timeout' => 120, + 'follow_redirects' => true, + 'ssl_verify_peer' => false, + )); + + // Twitter is strict about accepting invalid "Expect" headers + $request->setHeader('Expect', ''); if (isset($params)) { - $options[CURLOPT_POST] = true; - $options[CURLOPT_POSTFIELDS] = $params; + $request->setMethod(HTTP_Request2::METHOD_POST); + $request->setBody($params); } - $ch = curl_init($url); - curl_setopt_array($ch, $options); - $response = curl_exec($ch); - - if ($response === false) { - $msg = curl_error($ch); - $code = curl_errno($ch); - throw new OAuthClientCurlException($msg, $code); + try { + $response = $request->send(); + $code = $response->getStatus(); + if ($code < 200 || $code >= 400) { + throw new OAuthClientException($response->getBody(), $code); + } + return $response->getBody(); + } catch (Exception $e) { + throw new OAuthClientException($e->getMessage(), $e->getCode()); } - - curl_close($ch); - - return $response; } } diff --git a/lib/ping.php b/lib/ping.php index 175bf8440..5698c4038 100644 --- a/lib/ping.php +++ b/lib/ping.php @@ -44,20 +44,16 @@ function ping_broadcast_notice($notice) { array('nickname' => $profile->nickname)), $tags)); - $context = stream_context_create(array('http' => array('method' => "POST", - 'header' => - "Content-Type: text/xml\r\n". - "User-Agent: StatusNet/".STATUSNET_VERSION."\r\n", - 'content' => $req))); - $file = file_get_contents($notify_url, false, $context); + $request = HTTPClient::start(); + $httpResponse = $request->post($notify_url, array('Content-Type: text/xml'), $req); - if ($file === false || mb_strlen($file) == 0) { + if (!$httpResponse || mb_strlen($httpResponse->getBody()) == 0) { common_log(LOG_WARNING, "XML-RPC empty results for ping ($notify_url, $notice->id) "); continue; } - $response = xmlrpc_decode($file); + $response = xmlrpc_decode($httpResponse->getBody()); if (is_array($response) && xmlrpc_is_fault($response)) { common_log(LOG_WARNING, diff --git a/lib/snapshot.php b/lib/snapshot.php index ede846e5b..2a10c6b93 100644 --- a/lib/snapshot.php +++ b/lib/snapshot.php @@ -172,26 +172,9 @@ class Snapshot { // XXX: Use OICU2 and OAuth to make authorized requests - $postdata = http_build_query($this->stats); - - $opts = - array('http' => - array( - 'method' => 'POST', - 'header' => 'Content-type: '. - 'application/x-www-form-urlencoded', - 'content' => $postdata, - 'user_agent' => 'StatusNet/'.STATUSNET_VERSION - ) - ); - - $context = stream_context_create($opts); - $reporturl = common_config('snapshot', 'reporturl'); - - $result = @file_get_contents($reporturl, false, $context); - - return $result; + $request = HTTPClient::start(); + $request->post($reporturl, null, $this->stats); } /** diff --git a/plugins/BlogspamNetPlugin.php b/plugins/BlogspamNetPlugin.php index c14569746..51236001a 100644 --- a/plugins/BlogspamNetPlugin.php +++ b/plugins/BlogspamNetPlugin.php @@ -22,6 +22,7 @@ * @category Plugin * @package StatusNet * @author Evan Prodromou + * @author Brion Vibber * @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/ @@ -69,14 +70,12 @@ class BlogspamNetPlugin extends Plugin { $args = $this->testArgs($notice); common_debug("Blogspamnet args = " . print_r($args, TRUE)); - $request = xmlrpc_encode_request('testComment', array($args)); - $context = stream_context_create(array('http' => array('method' => "POST", - 'header' => - "Content-Type: text/xml\r\n". - "User-Agent: " . $this->userAgent(), - 'content' => $request))); - $file = file_get_contents($this->baseUrl, false, $context); - $response = xmlrpc_decode($file); + $requestBody = xmlrpc_encode_request('testComment', array($args)); + + $request = HTTPClient::start(); + $httpResponse = $request->post($this->baseUrl, array('Content-Type: text/xml'), $requestBody); + + $response = xmlrpc_decode($httpResponse->getBody()); if (xmlrpc_is_fault($response)) { throw new ServerException("$response[faultString] ($response[faultCode])", 500); } else { diff --git a/plugins/GeonamesPlugin.php b/plugins/GeonamesPlugin.php index 80ef44cc9..e18957c36 100644 --- a/plugins/GeonamesPlugin.php +++ b/plugins/GeonamesPlugin.php @@ -74,8 +74,8 @@ class GeonamesPlugin extends Plugin $result = $client->get('http://ws.geonames.org/search?'.$str); - if ($result->code == "200") { - $rj = json_decode($result->body); + if ($result->isOk()) { + $rj = json_decode($result->getBody()); if (count($rj->geonames) > 0) { $n = $rj->geonames[0]; @@ -121,9 +121,9 @@ class GeonamesPlugin extends Plugin $result = $client->get('http://ws.geonames.org/hierarchyJSON?'.$str); - if ($result->code == "200") { + if ($result->isOk()) { - $rj = json_decode($result->body); + $rj = json_decode($result->getBody()); if (count($rj->geonames) > 0) { @@ -182,9 +182,9 @@ class GeonamesPlugin extends Plugin $result = $client->get('http://ws.geonames.org/findNearbyPlaceNameJSON?'.$str); - if ($result->code == "200") { + if ($result->isOk()) { - $rj = json_decode($result->body); + $rj = json_decode($result->getBody()); if (count($rj->geonames) > 0) { @@ -249,9 +249,9 @@ class GeonamesPlugin extends Plugin $result = $client->get('http://ws.geonames.org/hierarchyJSON?'.$str); - if ($result->code == "200") { + if ($result->isOk()) { - $rj = json_decode($result->body); + $rj = json_decode($result->getBody()); if (count($rj->geonames) > 0) { diff --git a/plugins/LilUrl/LilUrlPlugin.php b/plugins/LilUrl/LilUrlPlugin.php index 7665b6c1e..852253b02 100644 --- a/plugins/LilUrl/LilUrlPlugin.php +++ b/plugins/LilUrl/LilUrlPlugin.php @@ -58,7 +58,10 @@ class LilUrl extends ShortUrlApi $y = @simplexml_load_string($response); if (!isset($y->body)) return $url; $x = $y->body->p[0]->a->attributes(); - if (isset($x['href'])) return $x['href']; + if (isset($x['href'])) { + common_log(LOG_INFO, __CLASS__ . ": shortened $url to $x[href]"); + return $x['href']; + } return $url; } } diff --git a/plugins/LinkbackPlugin.php b/plugins/LinkbackPlugin.php index 60f7a60c7..915d15c07 100644 --- a/plugins/LinkbackPlugin.php +++ b/plugins/LinkbackPlugin.php @@ -129,18 +129,12 @@ class LinkbackPlugin extends Plugin } } - $request = xmlrpc_encode_request('pingback.ping', $args); - $context = stream_context_create(array('http' => array('method' => "POST", - 'header' => - "Content-Type: text/xml\r\n". - "User-Agent: " . $this->userAgent(), - 'content' => $request))); - $file = file_get_contents($endpoint, false, $context); - if (!$file) { - common_log(LOG_WARNING, - "Pingback request failed for '$url' ($endpoint)"); - } else { - $response = xmlrpc_decode($file); + $request = HTTPClient::start(); + try { + $response = $request->post($endpoint, + array('Content-Type: text/xml'), + xmlrpc_encode_request('pingback.ping', $args)); + $response = xmlrpc_decode($response->getBody()); if (xmlrpc_is_fault($response)) { common_log(LOG_WARNING, "Pingback error for '$url' ($endpoint): ". @@ -150,6 +144,9 @@ class LinkbackPlugin extends Plugin "Pingback success for '$url' ($endpoint): ". "'$response'"); } + } catch (HTTP_Request2_Exception $e) { + common_log(LOG_WARNING, + "Pingback request failed for '$url' ($endpoint)"); } } diff --git a/plugins/SimpleUrl/SimpleUrlPlugin.php b/plugins/SimpleUrl/SimpleUrlPlugin.php index 82d772048..d59d63e47 100644 --- a/plugins/SimpleUrl/SimpleUrlPlugin.php +++ b/plugins/SimpleUrl/SimpleUrlPlugin.php @@ -65,15 +65,6 @@ class SimpleUrlPlugin extends Plugin class SimpleUrl extends ShortUrlApi { protected function shorten_imp($url) { - $curlh = curl_init(); - curl_setopt($curlh, CURLOPT_CONNECTTIMEOUT, 20); // # seconds to wait - curl_setopt($curlh, CURLOPT_USERAGENT, 'StatusNet'); - curl_setopt($curlh, CURLOPT_RETURNTRANSFER, true); - - curl_setopt($curlh, CURLOPT_URL, $this->service_url.urlencode($url)); - $short_url = curl_exec($curlh); - - curl_close($curlh); - return $short_url; + return $this->http_get($url); } } diff --git a/plugins/TwitterBridge/daemons/synctwitterfriends.php b/plugins/TwitterBridge/daemons/synctwitterfriends.php index ed2bf48a2..671e3c7af 100755 --- a/plugins/TwitterBridge/daemons/synctwitterfriends.php +++ b/plugins/TwitterBridge/daemons/synctwitterfriends.php @@ -152,8 +152,8 @@ class SyncTwitterFriendsDaemon extends ParallelizingDaemon $friends_ids = $client->friendsIds(); } catch (Exception $e) { common_log(LOG_WARNING, $this->name() . - ' - cURL error getting friend ids ' . - $e->getCode() . ' - ' . $e->getMessage()); + ' - error getting friend ids: ' . + $e->getMessage()); return $friends; } diff --git a/plugins/TwitterBridge/daemons/twitterstatusfetcher.php b/plugins/TwitterBridge/daemons/twitterstatusfetcher.php index 81bbbc7c5..b5428316b 100755 --- a/plugins/TwitterBridge/daemons/twitterstatusfetcher.php +++ b/plugins/TwitterBridge/daemons/twitterstatusfetcher.php @@ -109,12 +109,16 @@ class TwitterStatusFetcher extends ParallelizingDaemon $flink->find(); $flinks = array(); + common_log(LOG_INFO, "hello"); while ($flink->fetch()) { if (($flink->noticesync & FOREIGN_NOTICE_RECV) == FOREIGN_NOTICE_RECV) { $flinks[] = clone($flink); + common_log(LOG_INFO, "sync: foreign id $flink->foreign_id"); + } else { + common_log(LOG_INFO, "nothing to sync"); } } @@ -515,31 +519,32 @@ class TwitterStatusFetcher extends ParallelizingDaemon return $id; } + /** + * Fetch a remote avatar image and save to local storage. + * + * @param string $url avatar source URL + * @param string $filename bare local filename for download + * @return bool true on success, false on failure + */ function fetchAvatar($url, $filename) { - $avatarfile = Avatar::path($filename); + common_debug($this->name() . " - Fetching Twitter avatar: $url"); - $out = fopen($avatarfile, 'wb'); - if (!$out) { - common_log(LOG_WARNING, $this->name() . - " - Couldn't open file $filename"); + $request = HTTPClient::start(); + $response = $request->get($url); + if ($response->isOk()) { + $avatarfile = Avatar::path($filename); + $ok = file_put_contents($avatarfile, $response->getBody()); + if (!$ok) { + common_log(LOG_WARNING, $this->name() . + " - Couldn't open file $filename"); + return false; + } + } else { return false; } - common_debug($this->name() . " - Fetching Twitter avatar: $url"); - - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_FILE, $out); - curl_setopt($ch, CURLOPT_BINARYTRANSFER, true); - curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); - curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0); - $result = curl_exec($ch); - curl_close($ch); - - fclose($out); - - return $result; + return true; } } diff --git a/plugins/TwitterBridge/twitter.php b/plugins/TwitterBridge/twitter.php index 1a5248a9b..3c6803e49 100644 --- a/plugins/TwitterBridge/twitter.php +++ b/plugins/TwitterBridge/twitter.php @@ -215,7 +215,7 @@ function broadcast_basicauth($notice, $flink) try { $status = $client->statusesUpdate($statustxt); - } catch (BasicAuthCurlException $e) { + } catch (HTTP_Request2_Exception $e) { return process_error($e, $flink); } diff --git a/plugins/TwitterBridge/twitterauthorization.php b/plugins/TwitterBridge/twitterauthorization.php index 2a93ff13e..f1daefab1 100644 --- a/plugins/TwitterBridge/twitterauthorization.php +++ b/plugins/TwitterBridge/twitterauthorization.php @@ -125,7 +125,7 @@ class TwitterauthorizationAction extends Action $auth_link = $client->getAuthorizeLink($req_tok); - } catch (TwitterOAuthClientException $e) { + } catch (OAuthClientException $e) { $msg = sprintf('OAuth client cURL error - code: %1s, msg: %2s', $e->getCode(), $e->getMessage()); $this->serverError(_('Couldn\'t link your Twitter account.')); diff --git a/plugins/TwitterBridge/twitterbasicauthclient.php b/plugins/TwitterBridge/twitterbasicauthclient.php index 1040d72fb..d1cf45aec 100644 --- a/plugins/TwitterBridge/twitterbasicauthclient.php +++ b/plugins/TwitterBridge/twitterbasicauthclient.php @@ -31,26 +31,6 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } -/** - * Exception wrapper for cURL errors - * - * @category Integration - * @package StatusNet - * @author Adrian Lang - * @author Brenda Wallace - * @author Craig Andrews - * @author Dan Moore - * @author Evan Prodromou - * @author mEDI - * @author Sarven Capadisli - * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://status.net/ - * - */ -class BasicAuthCurlException extends Exception -{ -} - /** * Class for talking to the Twitter API with HTTP Basic Auth. * @@ -198,45 +178,27 @@ class TwitterBasicAuthClient */ function httpRequest($url, $params = null, $auth = true) { - $options = array( - CURLOPT_RETURNTRANSFER => true, - CURLOPT_FAILONERROR => true, - CURLOPT_HEADER => false, - CURLOPT_FOLLOWLOCATION => true, - CURLOPT_USERAGENT => 'StatusNet', - CURLOPT_CONNECTTIMEOUT => 120, - CURLOPT_TIMEOUT => 120, - CURLOPT_HTTPAUTH => CURLAUTH_ANY, - CURLOPT_SSL_VERIFYPEER => false, - - // Twitter is strict about accepting invalid "Expect" headers - - CURLOPT_HTTPHEADER => array('Expect:') - ); - - if (isset($params)) { - $options[CURLOPT_POST] = true; - $options[CURLOPT_POSTFIELDS] = $params; - } + $request = HTTPClient::start(); + $request->setConfig(array( + 'follow_redirects' => true, + 'connect_timeout' => 120, + 'timeout' => 120, + 'ssl_verifypeer' => false, + )); if ($auth) { - $options[CURLOPT_USERPWD] = $this->screen_name . - ':' . $this->password; + $request->setAuth($this->screen_name, $this->password); } - $ch = curl_init($url); - curl_setopt_array($ch, $options); - $response = curl_exec($ch); - - if ($response === false) { - $msg = curl_error($ch); - $code = curl_errno($ch); - throw new BasicAuthCurlException($msg, $code); + if (isset($params)) { + // Twitter is strict about accepting invalid "Expect" headers + $headers = array('Expect:'); + $response = $request->post($url, $headers, $params); + } else { + $response = $request->get($url); } - curl_close($ch); - - return $response; + return $response->getBody(); } } diff --git a/plugins/WikiHashtagsPlugin.php b/plugins/WikiHashtagsPlugin.php index 0c5649aa4..334fc13ba 100644 --- a/plugins/WikiHashtagsPlugin.php +++ b/plugins/WikiHashtagsPlugin.php @@ -68,14 +68,13 @@ class WikiHashtagsPlugin extends Plugin $editurl = sprintf('http://hashtags.wikia.com/index.php?title=%s&action=edit', urlencode($tag)); - $context = stream_context_create(array('http' => array('method' => "GET", - 'header' => - "User-Agent: " . $this->userAgent()))); - $html = @file_get_contents($url, false, $context); + $request = HTTPClient::start(); + $response = $request->get($url); + $html = $response->getBody(); $action->elementStart('div', array('id' => 'wikihashtags', 'class' => 'section')); - if (!empty($html)) { + if ($response->isOk() && !empty($html)) { $action->element('style', null, "span.editsection { display: none }\n". "table.toc { display: none }"); @@ -100,10 +99,4 @@ class WikiHashtagsPlugin extends Plugin return true; } - - function userAgent() - { - return 'WikiHashtagsPlugin/'.WIKIHASHTAGSPLUGIN_VERSION . - ' StatusNet/' . STATUSNET_VERSION; - } } diff --git a/scripts/enjitqueuehandler.php b/scripts/enjitqueuehandler.php index 08f733b07..afcac539a 100755 --- a/scripts/enjitqueuehandler.php +++ b/scripts/enjitqueuehandler.php @@ -46,8 +46,8 @@ class EnjitQueueHandler extends QueueHandler function start() { - $this->log(LOG_INFO, "Starting EnjitQueueHandler"); - $this->log(LOG_INFO, "Broadcasting to ".common_config('enjit', 'apiurl')); + $this->log(LOG_INFO, "Starting EnjitQueueHandler"); + $this->log(LOG_INFO, "Broadcasting to ".common_config('enjit', 'apiurl')); return true; } @@ -56,16 +56,16 @@ class EnjitQueueHandler extends QueueHandler $profile = Profile::staticGet($notice->profile_id); - $this->log(LOG_INFO, "Posting Notice ".$notice->id." from ".$profile->nickname); + $this->log(LOG_INFO, "Posting Notice ".$notice->id." from ".$profile->nickname); - if ( ! $notice->is_local ) { - $this->log(LOG_INFO, "Skipping remote notice"); - return "skipped"; - } + if ( ! $notice->is_local ) { + $this->log(LOG_INFO, "Skipping remote notice"); + return "skipped"; + } - # - # Build an Atom message from the notice - # + # + # Build an Atom message from the notice + # $noticeurl = common_local_url('shownotice', array('notice' => $notice->id)); $msg = $profile->nickname . ': ' . $notice->content; @@ -86,36 +86,18 @@ class EnjitQueueHandler extends QueueHandler $atom .= "".common_date_w3dtf($notice->modified)."\n"; $atom .= "\n"; - $url = common_config('enjit', 'apiurl') . "/submit/". common_config('enjit','apikey'); - $data = "msg=$atom"; + $url = common_config('enjit', 'apiurl') . "/submit/". common_config('enjit','apikey'); + $data = array( + 'msg' => $atom, + ); - # - # POST the message to $config['enjit']['apiurl'] - # - $ch = curl_init(); + # + # POST the message to $config['enjit']['apiurl'] + # + $request = HTTPClient::start(); + $response = $request->post($url, null, $data); - curl_setopt($ch, CURLOPT_URL, $url); - - curl_setopt($ch, CURLOPT_HEADER, 1); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch, CURLOPT_POST, 1) ; - curl_setopt($ch, CURLOPT_POSTFIELDS, $data); - - # SSL and Debugging options - # - # curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); - # curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); - # curl_setopt($ch, CURLOPT_VERBOSE, 1); - - $result = curl_exec($ch); - - $code = curl_getinfo($ch, CURLINFO_HTTP_CODE ); - - $this->log(LOG_INFO, "Response Code: $code"); - - curl_close($ch); - - return $code; + return $response->isOk(); } } -- cgit v1.2.3-54-g00ecf From 0ab17f382b9993ada3d12d4cdace72cca53fb545 Mon Sep 17 00:00:00 2001 From: Siebrand Mazeland Date: Sun, 8 Nov 2009 23:22:38 +0100 Subject: * [Cc]an't -> [Cc]annot * [Cc]ould't -> [Cc]ould not --- actions/emailsettings.php | 4 +- actions/smssettings.php | 2 +- classes/File.php | 2 +- classes/Notice.php | 4 +- extlib/Auth/OpenID/Consumer.php | 2 +- extlib/Auth/OpenID/Discover.php | 4 +- extlib/Auth/OpenID/FileStore.php | 2 +- extlib/DB.php | 2 +- extlib/DB/DataObject/Generator.php | 4 +- extlib/DB/dbase.php | 6 +- extlib/DB/fbsql.php | 8 +- extlib/DB/ibase.php | 6 +- extlib/DB/ifx.php | 12 +- extlib/DB/msql.php | 8 +- extlib/DB/mssql.php | 10 +- extlib/DB/mysql.php | 14 +- extlib/DB/mysqli.php | 14 +- extlib/DB/oci8.php | 10 +- extlib/DB/odbc.php | 8 +- extlib/DB/pgsql.php | 10 +- extlib/DB/sqlite.php | 8 +- extlib/DB/sybase.php | 12 +- extlib/HTTP/Request2/Adapter/Socket.php | 1940 ++--- extlib/MIME/Type.php | 4 +- extlib/MIME/Type/Extension.php | 4 +- extlib/Mail/mail.php | 2 +- extlib/Mail/sendmail.php | 2 +- extlib/Net/LDAP2/Entry.php | 2 +- extlib/Net/LDAP2/Filter.php | 2 +- extlib/System/Command.php | 2 +- extlib/markdown.php | 2 +- install.php | 16 +- lib/attachmentlist.php | 2 +- lib/noticelist.php | 2 +- lib/profilelist.php | 2 +- lib/serverexception.php | 2 +- lib/settingsaction.php | 2 +- lib/util.php | 2 +- lib/xmppqueuehandler.php | 2 +- locale/statusnet.po | 7814 +++++++------------- .../Facebook/facebook/facebookapi_php5_restlib.php | 2 +- .../Facebook/facebook/jsonwrapper/JSON/JSON.php | 2 +- plugins/Facebook/facebookaction.php | 2 +- plugins/Facebook/facebookhome.php | 2 +- plugins/LinkbackPlugin.php | 2 +- plugins/Meteor/MeteorPlugin.php | 2 +- plugins/OpenID/openid.php | 4 +- .../TwitterBridge/daemons/synctwitterfriends.php | 8 +- .../TwitterBridge/daemons/twitterstatusfetcher.php | 8 +- plugins/UserFlag/flagprofile.php | 2 +- scripts/console.php | 2 +- scripts/createsim.php | 4 +- scripts/deleteuser.php | 4 +- scripts/fixup_utf8.php | 2 +- scripts/makegroupadmin.php | 4 +- scripts/registeruser.php | 4 +- scripts/showcache.php | 2 +- scripts/sitemap.php | 4 +- scripts/update_translations.php | 2 +- 59 files changed, 3575 insertions(+), 6443 deletions(-) (limited to 'plugins/TwitterBridge/daemons') diff --git a/actions/emailsettings.php b/actions/emailsettings.php index 67b991cdc..715457eab 100644 --- a/actions/emailsettings.php +++ b/actions/emailsettings.php @@ -452,7 +452,7 @@ class EmailsettingsAction extends AccountSettingsAction if (!$user->updateKeys($orig)) { common_log_db_error($user, 'UPDATE', __FILE__); - $this->serverError(_("Couldn't update user record.")); + $this->serverError(_("Could not update user record.")); } $this->showForm(_('Incoming email address removed.'), true); @@ -474,7 +474,7 @@ class EmailsettingsAction extends AccountSettingsAction if (!$user->updateKeys($orig)) { common_log_db_error($user, 'UPDATE', __FILE__); - $this->serverError(_("Couldn't update user record.")); + $this->serverError(_("Could not update user record.")); } $this->showForm(_('New incoming email address added.'), true); diff --git a/actions/smssettings.php b/actions/smssettings.php index 9fa7f62fb..4debe1967 100644 --- a/actions/smssettings.php +++ b/actions/smssettings.php @@ -525,7 +525,7 @@ class SmssettingsAction extends ConnectSettingsAction if (!$user->updateKeys($orig)) { common_log_db_error($user, 'UPDATE', __FILE__); - $this->serverError(_("Couldn't update user record.")); + $this->serverError(_("Could not update user record.")); } $this->showForm(_('Incoming email address removed.'), true); diff --git a/classes/File.php b/classes/File.php index e04a9d525..dd0c3227e 100644 --- a/classes/File.php +++ b/classes/File.php @@ -99,7 +99,7 @@ class File extends Memcached_DataObject } elseif (is_string($redir_data)) { $redir_url = $redir_data; } else { - throw new ServerException("Can't process url '$given_url'"); + throw new ServerException("Cannot process url '$given_url'"); } // TODO: max field length if ($redir_url === $given_url || strlen($redir_url) > 255) { diff --git a/classes/Notice.php b/classes/Notice.php index 9886875cb..862d4c762 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -680,7 +680,7 @@ class Notice extends Memcached_DataObject return Notice::getStreamDirect($qry, $offset, $limit, null, null, $order, null); } - # Get the cache; if we can't, just go to the DB + # Get the cache; if we cannot, just go to the DB $cache = common_memcache(); @@ -1364,7 +1364,7 @@ class Notice extends Memcached_DataObject } } - // If it's not a "low bandwidth" source (one where you can't set + // If it's not a "low bandwidth" source (one where you cannot set // a reply_to argument), we return. This is mostly web and API // clients. diff --git a/extlib/Auth/OpenID/Consumer.php b/extlib/Auth/OpenID/Consumer.php index 500890b65..c75ef4c06 100644 --- a/extlib/Auth/OpenID/Consumer.php +++ b/extlib/Auth/OpenID/Consumer.php @@ -1059,7 +1059,7 @@ class Auth_OpenID_GenericConsumer { } } - // Fragments do not influence discovery, so we can't compare a + // Fragments do not influence discovery, so we cannot compare a // claimed identifier with a fragment to discovered // information. list($defragged_claimed_id, $_) = diff --git a/extlib/Auth/OpenID/Discover.php b/extlib/Auth/OpenID/Discover.php index 62aeb1d2b..9bb3ee357 100644 --- a/extlib/Auth/OpenID/Discover.php +++ b/extlib/Auth/OpenID/Discover.php @@ -515,7 +515,7 @@ function Auth_OpenID_discoverXRI($iname, &$fetcher) function Auth_OpenID_discover($uri, &$fetcher) { - // If the fetcher (i.e., PHP) doesn't support SSL, we can't do + // If the fetcher (i.e., PHP) doesn't support SSL, we cannot do // discovery on an HTTPS URL. if ($fetcher->isHTTPS($uri) && !$fetcher->supportsSSL()) { return array($uri, array()); @@ -527,7 +527,7 @@ function Auth_OpenID_discover($uri, &$fetcher) $result = Auth_OpenID_discoverURI($uri, $fetcher); } - // If the fetcher doesn't support SSL, we can't interact with + // If the fetcher doesn't support SSL, we cannot interact with // HTTPS server URLs; remove those endpoints from the list. if (!$fetcher->supportsSSL()) { $http_endpoints = array(); diff --git a/extlib/Auth/OpenID/FileStore.php b/extlib/Auth/OpenID/FileStore.php index 29d8d20e7..d9962e153 100644 --- a/extlib/Auth/OpenID/FileStore.php +++ b/extlib/Auth/OpenID/FileStore.php @@ -496,7 +496,7 @@ class Auth_OpenID_FileStore extends Auth_OpenID_OpenIDStore { return true; } else { - // Couldn't open directory. + // Could not open directory. return false; } } diff --git a/extlib/DB.php b/extlib/DB.php index a511979e6..4ef66f66f 100644 --- a/extlib/DB.php +++ b/extlib/DB.php @@ -1341,7 +1341,7 @@ class DB_result * returning the total number of rows that would have been returned, * rather than the real number. As a result, we'll just do the limit * calculations for fbsql in the same way as a database with emulated - * limits. Unfortunately, we can't just do this in DB_fbsql::numRows() + * limits. Unfortunately, we cannot just do this in DB_fbsql::numRows() * because that only gets the result resource, rather than the full * DB_Result object. */ if (($this->dbh->features['limit'] === 'emulate' diff --git a/extlib/DB/DataObject/Generator.php b/extlib/DB/DataObject/Generator.php index ff6e42c7d..e14e3ef7f 100644 --- a/extlib/DB/DataObject/Generator.php +++ b/extlib/DB/DataObject/Generator.php @@ -632,7 +632,7 @@ class DB_DataObject_Generator extends DB_DataObject echo "*****************************************************************\n". "** WARNING COLUMN NAME UNUSABLE **\n". "** Found column '{$t->name}', of type '{$t->type}' **\n". - "** Since this column name can't be converted to a php variable **\n". + "** Since this column name cannot be converted to a php variable **\n". "** name, and the whole idea of mapping would result in a mess **\n". "** This column has been ignored... **\n". "*****************************************************************\n"; @@ -910,7 +910,7 @@ class DB_DataObject_Generator extends DB_DataObject echo "*****************************************************************\n". "** WARNING COLUMN NAME UNUSABLE **\n". "** Found column '{$t->name}', of type '{$t->type}' **\n". - "** Since this column name can't be converted to a php variable **\n". + "** Since this column name cannot be converted to a php variable **\n". "** name, and the whole idea of mapping would result in a mess **\n". "** This column has been ignored... **\n". "*****************************************************************\n"; diff --git a/extlib/DB/dbase.php b/extlib/DB/dbase.php index 67afc897d..15d259c4d 100644 --- a/extlib/DB/dbase.php +++ b/extlib/DB/dbase.php @@ -287,7 +287,7 @@ class DB_dbase extends DB_common * See DB_result::fetchInto() for more information. * * This method is not meant to be called directly. Use - * DB_result::fetchInto() instead. It can't be declared "protected" + * DB_result::fetchInto() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result the query result resource @@ -352,7 +352,7 @@ class DB_dbase extends DB_common * Gets the number of columns in a result set * * This method is not meant to be called directly. Use - * DB_result::numCols() instead. It can't be declared "protected" + * DB_result::numCols() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -373,7 +373,7 @@ class DB_dbase extends DB_common * Gets the number of rows in a result set * * This method is not meant to be called directly. Use - * DB_result::numRows() instead. It can't be declared "protected" + * DB_result::numRows() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource diff --git a/extlib/DB/fbsql.php b/extlib/DB/fbsql.php index 4de4078f7..48ff705cf 100644 --- a/extlib/DB/fbsql.php +++ b/extlib/DB/fbsql.php @@ -262,7 +262,7 @@ class DB_fbsql extends DB_common * See DB_result::fetchInto() for more information. * * This method is not meant to be called directly. Use - * DB_result::fetchInto() instead. It can't be declared "protected" + * DB_result::fetchInto() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result the query result resource @@ -309,7 +309,7 @@ class DB_fbsql extends DB_common * Deletes the result set and frees the memory occupied by the result set * * This method is not meant to be called directly. Use - * DB_result::free() instead. It can't be declared "protected" + * DB_result::free() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -376,7 +376,7 @@ class DB_fbsql extends DB_common * Gets the number of columns in a result set * * This method is not meant to be called directly. Use - * DB_result::numCols() instead. It can't be declared "protected" + * DB_result::numCols() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -401,7 +401,7 @@ class DB_fbsql extends DB_common * Gets the number of rows in a result set * * This method is not meant to be called directly. Use - * DB_result::numRows() instead. It can't be declared "protected" + * DB_result::numRows() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource diff --git a/extlib/DB/ibase.php b/extlib/DB/ibase.php index ee19c5589..1e444d634 100644 --- a/extlib/DB/ibase.php +++ b/extlib/DB/ibase.php @@ -353,7 +353,7 @@ class DB_ibase extends DB_common * See DB_result::fetchInto() for more information. * * This method is not meant to be called directly. Use - * DB_result::fetchInto() instead. It can't be declared "protected" + * DB_result::fetchInto() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result the query result resource @@ -402,7 +402,7 @@ class DB_ibase extends DB_common * Deletes the result set and frees the memory occupied by the result set * * This method is not meant to be called directly. Use - * DB_result::free() instead. It can't be declared "protected" + * DB_result::free() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -449,7 +449,7 @@ class DB_ibase extends DB_common * Gets the number of columns in a result set * * This method is not meant to be called directly. Use - * DB_result::numCols() instead. It can't be declared "protected" + * DB_result::numCols() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource diff --git a/extlib/DB/ifx.php b/extlib/DB/ifx.php index baa6f2867..dcb3dbd3e 100644 --- a/extlib/DB/ifx.php +++ b/extlib/DB/ifx.php @@ -147,7 +147,7 @@ class DB_ifx extends DB_common /** * The quantity of transactions begun * - * {@internal While this is private, it can't actually be designated + * {@internal While this is private, it cannot actually be designated * private in PHP 5 because it is directly accessed in the test suite.}} * * @var integer @@ -328,7 +328,7 @@ class DB_ifx extends DB_common * See DB_result::fetchInto() for more information. * * This method is not meant to be called directly. Use - * DB_result::fetchInto() instead. It can't be declared "protected" + * DB_result::fetchInto() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result the query result resource @@ -387,7 +387,7 @@ class DB_ifx extends DB_common * Gets the number of columns in a result set * * This method is not meant to be called directly. Use - * DB_result::numCols() instead. It can't be declared "protected" + * DB_result::numCols() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -411,7 +411,7 @@ class DB_ifx extends DB_common * Deletes the result set and frees the memory occupied by the result set * * This method is not meant to be called directly. Use - * DB_result::free() instead. It can't be declared "protected" + * DB_result::free() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -555,7 +555,7 @@ class DB_ifx extends DB_common * * If analyzing a query result and the result has duplicate field names, * an error will be raised saying - * can't distinguish duplicate field names. + * cannot distinguish duplicate field names. * * @param object|string $result DB_result object from a query or a * string containing the name of a table. @@ -604,7 +604,7 @@ class DB_ifx extends DB_common $count = @ifx_num_fields($id); if (count($flds) != $count) { - return $this->raiseError("can't distinguish duplicate field names"); + return $this->raiseError("cannot distinguish duplicate field names"); } if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { diff --git a/extlib/DB/msql.php b/extlib/DB/msql.php index 34854f472..ee64f932f 100644 --- a/extlib/DB/msql.php +++ b/extlib/DB/msql.php @@ -288,7 +288,7 @@ class DB_msql extends DB_common * See DB_result::fetchInto() for more information. * * This method is not meant to be called directly. Use - * DB_result::fetchInto() instead. It can't be declared "protected" + * DB_result::fetchInto() instead. It cannot be declared "protected" * because DB_result is a separate object. * * PHP's mSQL extension did weird things with NULL values prior to PHP @@ -339,7 +339,7 @@ class DB_msql extends DB_common * Deletes the result set and frees the memory occupied by the result set * * This method is not meant to be called directly. Use - * DB_result::free() instead. It can't be declared "protected" + * DB_result::free() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -360,7 +360,7 @@ class DB_msql extends DB_common * Gets the number of columns in a result set * * This method is not meant to be called directly. Use - * DB_result::numCols() instead. It can't be declared "protected" + * DB_result::numCols() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -385,7 +385,7 @@ class DB_msql extends DB_common * Gets the number of rows in a result set * * This method is not meant to be called directly. Use - * DB_result::numRows() instead. It can't be declared "protected" + * DB_result::numRows() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource diff --git a/extlib/DB/mssql.php b/extlib/DB/mssql.php index 511a2b686..1aad75671 100644 --- a/extlib/DB/mssql.php +++ b/extlib/DB/mssql.php @@ -156,7 +156,7 @@ class DB_mssql extends DB_common /** * The quantity of transactions begun * - * {@internal While this is private, it can't actually be designated + * {@internal While this is private, it cannot actually be designated * private in PHP 5 because it is directly accessed in the test suite.}} * * @var integer @@ -324,7 +324,7 @@ class DB_mssql extends DB_common * See DB_result::fetchInto() for more information. * * This method is not meant to be called directly. Use - * DB_result::fetchInto() instead. It can't be declared "protected" + * DB_result::fetchInto() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result the query result resource @@ -371,7 +371,7 @@ class DB_mssql extends DB_common * Deletes the result set and frees the memory occupied by the result set * * This method is not meant to be called directly. Use - * DB_result::free() instead. It can't be declared "protected" + * DB_result::free() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -392,7 +392,7 @@ class DB_mssql extends DB_common * Gets the number of columns in a result set * * This method is not meant to be called directly. Use - * DB_result::numCols() instead. It can't be declared "protected" + * DB_result::numCols() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -417,7 +417,7 @@ class DB_mssql extends DB_common * Gets the number of rows in a result set * * This method is not meant to be called directly. Use - * DB_result::numRows() instead. It can't be declared "protected" + * DB_result::numRows() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource diff --git a/extlib/DB/mysql.php b/extlib/DB/mysql.php index c67254520..bfe34dbe8 100644 --- a/extlib/DB/mysql.php +++ b/extlib/DB/mysql.php @@ -139,7 +139,7 @@ class DB_mysql extends DB_common /** * The quantity of transactions begun * - * {@internal While this is private, it can't actually be designated + * {@internal While this is private, it cannot actually be designated * private in PHP 5 because it is directly accessed in the test suite.}} * * @var integer @@ -359,7 +359,7 @@ class DB_mysql extends DB_common * See DB_result::fetchInto() for more information. * * This method is not meant to be called directly. Use - * DB_result::fetchInto() instead. It can't be declared "protected" + * DB_result::fetchInto() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result the query result resource @@ -411,7 +411,7 @@ class DB_mysql extends DB_common * Deletes the result set and frees the memory occupied by the result set * * This method is not meant to be called directly. Use - * DB_result::free() instead. It can't be declared "protected" + * DB_result::free() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -432,7 +432,7 @@ class DB_mysql extends DB_common * Gets the number of columns in a result set * * This method is not meant to be called directly. Use - * DB_result::numCols() instead. It can't be declared "protected" + * DB_result::numCols() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -457,7 +457,7 @@ class DB_mysql extends DB_common * Gets the number of rows in a result set * * This method is not meant to be called directly. Use - * DB_result::numRows() instead. It can't be declared "protected" + * DB_result::numRows() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -722,7 +722,7 @@ class DB_mysql extends DB_common return $result; } if ($result == 0) { - // Failed to get the lock, can't do the conversion, bail + // Failed to get the lock, cannot do the conversion, bail // with a DB_ERROR_NOT_LOCKED error return $this->mysqlRaiseError(DB_ERROR_NOT_LOCKED); } @@ -757,7 +757,7 @@ class DB_mysql extends DB_common * Quotes a string so it can be safely used as a table or column name * (WARNING: using names that require this is a REALLY BAD IDEA) * - * WARNING: Older versions of MySQL can't handle the backtick + * WARNING: Older versions of MySQL cannot handle the backtick * character (`) in table or column names. * * @param string $str identifier name to be quoted diff --git a/extlib/DB/mysqli.php b/extlib/DB/mysqli.php index c6941b170..b6196dfcc 100644 --- a/extlib/DB/mysqli.php +++ b/extlib/DB/mysqli.php @@ -142,7 +142,7 @@ class DB_mysqli extends DB_common /** * The quantity of transactions begun * - * {@internal While this is private, it can't actually be designated + * {@internal While this is private, it cannot actually be designated * private in PHP 5 because it is directly accessed in the test suite.}} * * @var integer @@ -434,7 +434,7 @@ class DB_mysqli extends DB_common * See DB_result::fetchInto() for more information. * * This method is not meant to be called directly. Use - * DB_result::fetchInto() instead. It can't be declared "protected" + * DB_result::fetchInto() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result the query result resource @@ -486,7 +486,7 @@ class DB_mysqli extends DB_common * Deletes the result set and frees the memory occupied by the result set * * This method is not meant to be called directly. Use - * DB_result::free() instead. It can't be declared "protected" + * DB_result::free() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -507,7 +507,7 @@ class DB_mysqli extends DB_common * Gets the number of columns in a result set * * This method is not meant to be called directly. Use - * DB_result::numCols() instead. It can't be declared "protected" + * DB_result::numCols() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -532,7 +532,7 @@ class DB_mysqli extends DB_common * Gets the number of rows in a result set * * This method is not meant to be called directly. Use - * DB_result::numRows() instead. It can't be declared "protected" + * DB_result::numRows() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -796,7 +796,7 @@ class DB_mysqli extends DB_common return $result; } if ($result == 0) { - // Failed to get the lock, can't do the conversion, bail + // Failed to get the lock, cannot do the conversion, bail // with a DB_ERROR_NOT_LOCKED error return $this->mysqliRaiseError(DB_ERROR_NOT_LOCKED); } @@ -832,7 +832,7 @@ class DB_mysqli extends DB_common * Quotes a string so it can be safely used as a table or column name * (WARNING: using names that require this is a REALLY BAD IDEA) * - * WARNING: Older versions of MySQL can't handle the backtick + * WARNING: Older versions of MySQL cannot handle the backtick * character (`) in table or column names. * * @param string $str identifier name to be quoted diff --git a/extlib/DB/oci8.php b/extlib/DB/oci8.php index d30794871..6ad36643a 100644 --- a/extlib/DB/oci8.php +++ b/extlib/DB/oci8.php @@ -251,7 +251,7 @@ class DB_oci8 extends DB_common $char); $error = OCIError(); if (!empty($error) && $error['code'] == 12541) { - // Couldn't find TNS listener. Try direct connection. + // Could not find TNS listener. Try direct connection. $this->connection = @$connect_function($dsn['username'], $dsn['password'], null, @@ -368,7 +368,7 @@ class DB_oci8 extends DB_common * See DB_result::fetchInto() for more information. * * This method is not meant to be called directly. Use - * DB_result::fetchInto() instead. It can't be declared "protected" + * DB_result::fetchInto() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result the query result resource @@ -415,7 +415,7 @@ class DB_oci8 extends DB_common * Deletes the result set and frees the memory occupied by the result set * * This method is not meant to be called directly. Use - * DB_result::free() instead. It can't be declared "protected" + * DB_result::free() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -468,7 +468,7 @@ class DB_oci8 extends DB_common * is turned on. * * This method is not meant to be called directly. Use - * DB_result::numRows() instead. It can't be declared "protected" + * DB_result::numRows() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -511,7 +511,7 @@ class DB_oci8 extends DB_common * Gets the number of columns in a result set * * This method is not meant to be called directly. Use - * DB_result::numCols() instead. It can't be declared "protected" + * DB_result::numCols() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource diff --git a/extlib/DB/odbc.php b/extlib/DB/odbc.php index eba43659a..b0dc83ab5 100644 --- a/extlib/DB/odbc.php +++ b/extlib/DB/odbc.php @@ -301,7 +301,7 @@ class DB_odbc extends DB_common * See DB_result::fetchInto() for more information. * * This method is not meant to be called directly. Use - * DB_result::fetchInto() instead. It can't be declared "protected" + * DB_result::fetchInto() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result the query result resource @@ -356,7 +356,7 @@ class DB_odbc extends DB_common * Deletes the result set and frees the memory occupied by the result set * * This method is not meant to be called directly. Use - * DB_result::free() instead. It can't be declared "protected" + * DB_result::free() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -377,7 +377,7 @@ class DB_odbc extends DB_common * Gets the number of columns in a result set * * This method is not meant to be called directly. Use - * DB_result::numCols() instead. It can't be declared "protected" + * DB_result::numCols() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -427,7 +427,7 @@ class DB_odbc extends DB_common * a DB_Error object for DB_ERROR_UNSUPPORTED is returned. * * This method is not meant to be called directly. Use - * DB_result::numRows() instead. It can't be declared "protected" + * DB_result::numRows() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource diff --git a/extlib/DB/pgsql.php b/extlib/DB/pgsql.php index 6030bb4c1..498ef8ade 100644 --- a/extlib/DB/pgsql.php +++ b/extlib/DB/pgsql.php @@ -115,7 +115,7 @@ class DB_pgsql extends DB_common /** * The quantity of transactions begun * - * {@internal While this is private, it can't actually be designated + * {@internal While this is private, it cannot actually be designated * private in PHP 5 because it is directly accessed in the test suite.}} * * @var integer @@ -397,7 +397,7 @@ class DB_pgsql extends DB_common * See DB_result::fetchInto() for more information. * * This method is not meant to be called directly. Use - * DB_result::fetchInto() instead. It can't be declared "protected" + * DB_result::fetchInto() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result the query result resource @@ -445,7 +445,7 @@ class DB_pgsql extends DB_common * Deletes the result set and frees the memory occupied by the result set * * This method is not meant to be called directly. Use - * DB_result::free() instead. It can't be declared "protected" + * DB_result::free() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -535,7 +535,7 @@ class DB_pgsql extends DB_common * Gets the number of columns in a result set * * This method is not meant to be called directly. Use - * DB_result::numCols() instead. It can't be declared "protected" + * DB_result::numCols() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -560,7 +560,7 @@ class DB_pgsql extends DB_common * Gets the number of rows in a result set * * This method is not meant to be called directly. Use - * DB_result::numRows() instead. It can't be declared "protected" + * DB_result::numRows() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource diff --git a/extlib/DB/sqlite.php b/extlib/DB/sqlite.php index 5c4b396e5..96d5c934a 100644 --- a/extlib/DB/sqlite.php +++ b/extlib/DB/sqlite.php @@ -334,7 +334,7 @@ class DB_sqlite extends DB_common * See DB_result::fetchInto() for more information. * * This method is not meant to be called directly. Use - * DB_result::fetchInto() instead. It can't be declared "protected" + * DB_result::fetchInto() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result the query result resource @@ -396,7 +396,7 @@ class DB_sqlite extends DB_common * Deletes the result set and frees the memory occupied by the result set * * This method is not meant to be called directly. Use - * DB_result::free() instead. It can't be declared "protected" + * DB_result::free() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -422,7 +422,7 @@ class DB_sqlite extends DB_common * Gets the number of columns in a result set * * This method is not meant to be called directly. Use - * DB_result::numCols() instead. It can't be declared "protected" + * DB_result::numCols() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -447,7 +447,7 @@ class DB_sqlite extends DB_common * Gets the number of rows in a result set * * This method is not meant to be called directly. Use - * DB_result::numRows() instead. It can't be declared "protected" + * DB_result::numRows() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource diff --git a/extlib/DB/sybase.php b/extlib/DB/sybase.php index 3befbf6ea..97ab41a22 100644 --- a/extlib/DB/sybase.php +++ b/extlib/DB/sybase.php @@ -118,7 +118,7 @@ class DB_sybase extends DB_common /** * The quantity of transactions begun * - * {@internal While this is private, it can't actually be designated + * {@internal While this is private, it cannot actually be designated * private in PHP 5 because it is directly accessed in the test suite.}} * * @var integer @@ -302,7 +302,7 @@ class DB_sybase extends DB_common * See DB_result::fetchInto() for more information. * * This method is not meant to be called directly. Use - * DB_result::fetchInto() instead. It can't be declared "protected" + * DB_result::fetchInto() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result the query result resource @@ -359,7 +359,7 @@ class DB_sybase extends DB_common * Deletes the result set and frees the memory occupied by the result set * * This method is not meant to be called directly. Use - * DB_result::free() instead. It can't be declared "protected" + * DB_result::free() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -380,7 +380,7 @@ class DB_sybase extends DB_common * Gets the number of columns in a result set * * This method is not meant to be called directly. Use - * DB_result::numCols() instead. It can't be declared "protected" + * DB_result::numCols() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -405,7 +405,7 @@ class DB_sybase extends DB_common * Gets the number of rows in a result set * * This method is not meant to be called directly. Use - * DB_result::numRows() instead. It can't be declared "protected" + * DB_result::numRows() instead. It cannot be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -835,7 +835,7 @@ class DB_sybase extends DB_common $tableName = $table; /* We're running sp_helpindex directly because it doesn't exist in - * older versions of ASE -- unfortunately, we can't just use + * older versions of ASE -- unfortunately, we cannot just use * DB::isError() because the user may be using callback error * handling. */ $res = @sybase_query("sp_helpindex $table", $this->connection); diff --git a/extlib/HTTP/Request2/Adapter/Socket.php b/extlib/HTTP/Request2/Adapter/Socket.php index ff44d4959..13cd6136f 100644 --- a/extlib/HTTP/Request2/Adapter/Socket.php +++ b/extlib/HTTP/Request2/Adapter/Socket.php @@ -1,971 +1,971 @@ - - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * The names of the authors may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * @category HTTP - * @package HTTP_Request2 - * @author Alexey Borzov - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version CVS: $Id: Socket.php 279760 2009-05-03 10:46:42Z avb $ - * @link http://pear.php.net/package/HTTP_Request2 - */ - -/** - * Base class for HTTP_Request2 adapters - */ -require_once 'HTTP/Request2/Adapter.php'; - -/** - * Socket-based adapter for HTTP_Request2 - * - * This adapter uses only PHP sockets and will work on almost any PHP - * environment. Code is based on original HTTP_Request PEAR package. - * - * @category HTTP - * @package HTTP_Request2 - * @author Alexey Borzov - * @version Release: 0.4.1 - */ -class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter -{ - /** - * Regular expression for 'token' rule from RFC 2616 - */ - const REGEXP_TOKEN = '[^\x00-\x1f\x7f-\xff()<>@,;:\\\\"/\[\]?={}\s]+'; - - /** - * Regular expression for 'quoted-string' rule from RFC 2616 - */ - const REGEXP_QUOTED_STRING = '"(?:\\\\.|[^\\\\"])*"'; - - /** - * Connected sockets, needed for Keep-Alive support - * @var array - * @see connect() - */ - protected static $sockets = array(); - - /** - * Data for digest authentication scheme - * - * The keys for the array are URL prefixes. - * - * The values are associative arrays with data (realm, nonce, nonce-count, - * opaque...) needed for digest authentication. Stored here to prevent making - * duplicate requests to digest-protected resources after we have already - * received the challenge. - * - * @var array - */ - protected static $challenges = array(); - - /** - * Connected socket - * @var resource - * @see connect() - */ - protected $socket; - - /** - * Challenge used for server digest authentication - * @var array - */ - protected $serverChallenge; - - /** - * Challenge used for proxy digest authentication - * @var array - */ - protected $proxyChallenge; - - /** - * Global timeout, exception will be raised if request continues past this time - * @var integer - */ - protected $timeout = null; - - /** - * Remaining length of the current chunk, when reading chunked response - * @var integer - * @see readChunked() - */ - protected $chunkLength = 0; - - /** - * Sends request to the remote server and returns its response - * - * @param HTTP_Request2 - * @return HTTP_Request2_Response - * @throws HTTP_Request2_Exception - */ - public function sendRequest(HTTP_Request2 $request) - { - $this->request = $request; - $keepAlive = $this->connect(); - $headers = $this->prepareHeaders(); - - // Use global request timeout if given, see feature requests #5735, #8964 - if ($timeout = $request->getConfig('timeout')) { - $this->timeout = time() + $timeout; - } else { - $this->timeout = null; - } - - try { - if (false === @fwrite($this->socket, $headers, strlen($headers))) { - throw new HTTP_Request2_Exception('Error writing request'); - } - // provide request headers to the observer, see request #7633 - $this->request->setLastEvent('sentHeaders', $headers); - $this->writeBody(); - - if ($this->timeout && time() > $this->timeout) { - throw new HTTP_Request2_Exception( - 'Request timed out after ' . - $request->getConfig('timeout') . ' second(s)' - ); - } - - $response = $this->readResponse(); - - if (!$this->canKeepAlive($keepAlive, $response)) { - $this->disconnect(); - } - - if ($this->shouldUseProxyDigestAuth($response)) { - return $this->sendRequest($request); - } - if ($this->shouldUseServerDigestAuth($response)) { - return $this->sendRequest($request); - } - if ($authInfo = $response->getHeader('authentication-info')) { - $this->updateChallenge($this->serverChallenge, $authInfo); - } - if ($proxyInfo = $response->getHeader('proxy-authentication-info')) { - $this->updateChallenge($this->proxyChallenge, $proxyInfo); - } - - } catch (Exception $e) { - $this->disconnect(); - throw $e; - } - - return $response; - } - - /** - * Connects to the remote server - * - * @return bool whether the connection can be persistent - * @throws HTTP_Request2_Exception - */ - protected function connect() - { - $secure = 0 == strcasecmp($this->request->getUrl()->getScheme(), 'https'); - $tunnel = HTTP_Request2::METHOD_CONNECT == $this->request->getMethod(); - $headers = $this->request->getHeaders(); - $reqHost = $this->request->getUrl()->getHost(); - if (!($reqPort = $this->request->getUrl()->getPort())) { - $reqPort = $secure? 443: 80; - } - - if ($host = $this->request->getConfig('proxy_host')) { - if (!($port = $this->request->getConfig('proxy_port'))) { - throw new HTTP_Request2_Exception('Proxy port not provided'); - } - $proxy = true; - } else { - $host = $reqHost; - $port = $reqPort; - $proxy = false; - } - - if ($tunnel && !$proxy) { - throw new HTTP_Request2_Exception( - "Trying to perform CONNECT request without proxy" - ); - } - if ($secure && !in_array('ssl', stream_get_transports())) { - throw new HTTP_Request2_Exception( - 'Need OpenSSL support for https:// requests' - ); - } - - // RFC 2068, section 19.7.1: A client MUST NOT send the Keep-Alive - // connection token to a proxy server... - if ($proxy && !$secure && - !empty($headers['connection']) && 'Keep-Alive' == $headers['connection'] - ) { - $this->request->setHeader('connection'); - } - - $keepAlive = ('1.1' == $this->request->getConfig('protocol_version') && - empty($headers['connection'])) || - (!empty($headers['connection']) && - 'Keep-Alive' == $headers['connection']); - $host = ((!$secure || $proxy)? 'tcp://': 'ssl://') . $host; - - $options = array(); - if ($secure || $tunnel) { - foreach ($this->request->getConfig() as $name => $value) { - if ('ssl_' == substr($name, 0, 4) && null !== $value) { - if ('ssl_verify_host' == $name) { - if ($value) { - $options['CN_match'] = $reqHost; - } - } else { - $options[substr($name, 4)] = $value; - } - } - } - ksort($options); - } - - // Changing SSL context options after connection is established does *not* - // work, we need a new connection if options change - $remote = $host . ':' . $port; - $socketKey = $remote . (($secure && $proxy)? "->{$reqHost}:{$reqPort}": '') . - (empty($options)? '': ':' . serialize($options)); - unset($this->socket); - - // We use persistent connections and have a connected socket? - // Ensure that the socket is still connected, see bug #16149 - if ($keepAlive && !empty(self::$sockets[$socketKey]) && - !feof(self::$sockets[$socketKey]) - ) { - $this->socket =& self::$sockets[$socketKey]; - - } elseif ($secure && $proxy && !$tunnel) { - $this->establishTunnel(); - $this->request->setLastEvent( - 'connect', "ssl://{$reqHost}:{$reqPort} via {$host}:{$port}" - ); - self::$sockets[$socketKey] =& $this->socket; - - } else { - // Set SSL context options if doing HTTPS request or creating a tunnel - $context = stream_context_create(); - foreach ($options as $name => $value) { - if (!stream_context_set_option($context, 'ssl', $name, $value)) { - throw new HTTP_Request2_Exception( - "Error setting SSL context option '{$name}'" - ); - } - } - $this->socket = @stream_socket_client( - $remote, $errno, $errstr, - $this->request->getConfig('connect_timeout'), - STREAM_CLIENT_CONNECT, $context - ); - if (!$this->socket) { - throw new HTTP_Request2_Exception( - "Unable to connect to {$remote}. Error #{$errno}: {$errstr}" - ); - } - $this->request->setLastEvent('connect', $remote); - self::$sockets[$socketKey] =& $this->socket; - } - return $keepAlive; - } - - /** - * Establishes a tunnel to a secure remote server via HTTP CONNECT request - * - * This method will fail if 'ssl_verify_peer' is enabled. Probably because PHP - * sees that we are connected to a proxy server (duh!) rather than the server - * that presents its certificate. - * - * @link http://tools.ietf.org/html/rfc2817#section-5.2 - * @throws HTTP_Request2_Exception - */ - protected function establishTunnel() - { - $donor = new self; - $connect = new HTTP_Request2( - $this->request->getUrl(), HTTP_Request2::METHOD_CONNECT, - array_merge($this->request->getConfig(), - array('adapter' => $donor)) - ); - $response = $connect->send(); - // Need any successful (2XX) response - if (200 > $response->getStatus() || 300 <= $response->getStatus()) { - throw new HTTP_Request2_Exception( - 'Failed to connect via HTTPS proxy. Proxy response: ' . - $response->getStatus() . ' ' . $response->getReasonPhrase() - ); - } - $this->socket = $donor->socket; - - $modes = array( - STREAM_CRYPTO_METHOD_TLS_CLIENT, - STREAM_CRYPTO_METHOD_SSLv3_CLIENT, - STREAM_CRYPTO_METHOD_SSLv23_CLIENT, - STREAM_CRYPTO_METHOD_SSLv2_CLIENT - ); - - foreach ($modes as $mode) { - if (stream_socket_enable_crypto($this->socket, true, $mode)) { - return; - } - } - throw new HTTP_Request2_Exception( - 'Failed to enable secure connection when connecting through proxy' - ); - } - - /** - * Checks whether current connection may be reused or should be closed - * - * @param boolean whether connection could be persistent - * in the first place - * @param HTTP_Request2_Response response object to check - * @return boolean - */ - protected function canKeepAlive($requestKeepAlive, HTTP_Request2_Response $response) - { - // Do not close socket on successful CONNECT request - if (HTTP_Request2::METHOD_CONNECT == $this->request->getMethod() && - 200 <= $response->getStatus() && 300 > $response->getStatus() - ) { - return true; - } - - $lengthKnown = 'chunked' == strtolower($response->getHeader('transfer-encoding')) || - null !== $response->getHeader('content-length'); - $persistent = 'keep-alive' == strtolower($response->getHeader('connection')) || - (null === $response->getHeader('connection') && - '1.1' == $response->getVersion()); - return $requestKeepAlive && $lengthKnown && $persistent; - } - - /** - * Disconnects from the remote server - */ - protected function disconnect() - { - if (is_resource($this->socket)) { - fclose($this->socket); - $this->socket = null; - $this->request->setLastEvent('disconnect'); - } - } - - /** - * Checks whether another request should be performed with server digest auth - * - * Several conditions should be satisfied for it to return true: - * - response status should be 401 - * - auth credentials should be set in the request object - * - response should contain WWW-Authenticate header with digest challenge - * - there is either no challenge stored for this URL or new challenge - * contains stale=true parameter (in other case we probably just failed - * due to invalid username / password) - * - * The method stores challenge values in $challenges static property - * - * @param HTTP_Request2_Response response to check - * @return boolean whether another request should be performed - * @throws HTTP_Request2_Exception in case of unsupported challenge parameters - */ - protected function shouldUseServerDigestAuth(HTTP_Request2_Response $response) - { - // no sense repeating a request if we don't have credentials - if (401 != $response->getStatus() || !$this->request->getAuth()) { - return false; - } - if (!$challenge = $this->parseDigestChallenge($response->getHeader('www-authenticate'))) { - return false; - } - - $url = $this->request->getUrl(); - $scheme = $url->getScheme(); - $host = $scheme . '://' . $url->getHost(); - if ($port = $url->getPort()) { - if ((0 == strcasecmp($scheme, 'http') && 80 != $port) || - (0 == strcasecmp($scheme, 'https') && 443 != $port) - ) { - $host .= ':' . $port; - } - } - - if (!empty($challenge['domain'])) { - $prefixes = array(); - foreach (preg_split('/\\s+/', $challenge['domain']) as $prefix) { - // don't bother with different servers - if ('/' == substr($prefix, 0, 1)) { - $prefixes[] = $host . $prefix; - } - } - } - if (empty($prefixes)) { - $prefixes = array($host . '/'); - } - - $ret = true; - foreach ($prefixes as $prefix) { - if (!empty(self::$challenges[$prefix]) && - (empty($challenge['stale']) || strcasecmp('true', $challenge['stale'])) - ) { - // probably credentials are invalid - $ret = false; - } - self::$challenges[$prefix] =& $challenge; - } - return $ret; - } - - /** - * Checks whether another request should be performed with proxy digest auth - * - * Several conditions should be satisfied for it to return true: - * - response status should be 407 - * - proxy auth credentials should be set in the request object - * - response should contain Proxy-Authenticate header with digest challenge - * - there is either no challenge stored for this proxy or new challenge - * contains stale=true parameter (in other case we probably just failed - * due to invalid username / password) - * - * The method stores challenge values in $challenges static property - * - * @param HTTP_Request2_Response response to check - * @return boolean whether another request should be performed - * @throws HTTP_Request2_Exception in case of unsupported challenge parameters - */ - protected function shouldUseProxyDigestAuth(HTTP_Request2_Response $response) - { - if (407 != $response->getStatus() || !$this->request->getConfig('proxy_user')) { - return false; - } - if (!($challenge = $this->parseDigestChallenge($response->getHeader('proxy-authenticate')))) { - return false; - } - - $key = 'proxy://' . $this->request->getConfig('proxy_host') . - ':' . $this->request->getConfig('proxy_port'); - - if (!empty(self::$challenges[$key]) && - (empty($challenge['stale']) || strcasecmp('true', $challenge['stale'])) - ) { - $ret = false; - } else { - $ret = true; - } - self::$challenges[$key] = $challenge; - return $ret; - } - - /** - * Extracts digest method challenge from (WWW|Proxy)-Authenticate header value - * - * There is a problem with implementation of RFC 2617: several of the parameters - * here are defined as quoted-string and thus may contain backslash escaped - * double quotes (RFC 2616, section 2.2). However, RFC 2617 defines unq(X) as - * just value of quoted-string X without surrounding quotes, it doesn't speak - * about removing backslash escaping. - * - * Now realm parameter is user-defined and human-readable, strange things - * happen when it contains quotes: - * - Apache allows quotes in realm, but apparently uses realm value without - * backslashes for digest computation - * - Squid allows (manually escaped) quotes there, but it is impossible to - * authorize with either escaped or unescaped quotes used in digest, - * probably it can't parse the response (?) - * - Both IE and Firefox display realm value with backslashes in - * the password popup and apparently use the same value for digest - * - * HTTP_Request2 follows IE and Firefox (and hopefully RFC 2617) in - * quoted-string handling, unfortunately that means failure to authorize - * sometimes - * - * @param string value of WWW-Authenticate or Proxy-Authenticate header - * @return mixed associative array with challenge parameters, false if - * no challenge is present in header value - * @throws HTTP_Request2_Exception in case of unsupported challenge parameters - */ - protected function parseDigestChallenge($headerValue) - { - $authParam = '(' . self::REGEXP_TOKEN . ')\\s*=\\s*(' . - self::REGEXP_TOKEN . '|' . self::REGEXP_QUOTED_STRING . ')'; - $challenge = "!(?<=^|\\s|,)Digest ({$authParam}\\s*(,\\s*|$))+!"; - if (!preg_match($challenge, $headerValue, $matches)) { - return false; - } - - preg_match_all('!' . $authParam . '!', $matches[0], $params); - $paramsAry = array(); - $knownParams = array('realm', 'domain', 'nonce', 'opaque', 'stale', - 'algorithm', 'qop'); - for ($i = 0; $i < count($params[0]); $i++) { - // section 3.2.1: Any unrecognized directive MUST be ignored. - if (in_array($params[1][$i], $knownParams)) { - if ('"' == substr($params[2][$i], 0, 1)) { - $paramsAry[$params[1][$i]] = substr($params[2][$i], 1, -1); - } else { - $paramsAry[$params[1][$i]] = $params[2][$i]; - } - } - } - // we only support qop=auth - if (!empty($paramsAry['qop']) && - !in_array('auth', array_map('trim', explode(',', $paramsAry['qop']))) - ) { - throw new HTTP_Request2_Exception( - "Only 'auth' qop is currently supported in digest authentication, " . - "server requested '{$paramsAry['qop']}'" - ); - } - // we only support algorithm=MD5 - if (!empty($paramsAry['algorithm']) && 'MD5' != $paramsAry['algorithm']) { - throw new HTTP_Request2_Exception( - "Only 'MD5' algorithm is currently supported in digest authentication, " . - "server requested '{$paramsAry['algorithm']}'" - ); - } - - return $paramsAry; - } - - /** - * Parses [Proxy-]Authentication-Info header value and updates challenge - * - * @param array challenge to update - * @param string value of [Proxy-]Authentication-Info header - * @todo validate server rspauth response - */ - protected function updateChallenge(&$challenge, $headerValue) - { - $authParam = '!(' . self::REGEXP_TOKEN . ')\\s*=\\s*(' . - self::REGEXP_TOKEN . '|' . self::REGEXP_QUOTED_STRING . ')!'; - $paramsAry = array(); - - preg_match_all($authParam, $headerValue, $params); - for ($i = 0; $i < count($params[0]); $i++) { - if ('"' == substr($params[2][$i], 0, 1)) { - $paramsAry[$params[1][$i]] = substr($params[2][$i], 1, -1); - } else { - $paramsAry[$params[1][$i]] = $params[2][$i]; - } - } - // for now, just update the nonce value - if (!empty($paramsAry['nextnonce'])) { - $challenge['nonce'] = $paramsAry['nextnonce']; - $challenge['nc'] = 1; - } - } - - /** - * Creates a value for [Proxy-]Authorization header when using digest authentication - * - * @param string user name - * @param string password - * @param string request URL - * @param array digest challenge parameters - * @return string value of [Proxy-]Authorization request header - * @link http://tools.ietf.org/html/rfc2617#section-3.2.2 - */ - protected function createDigestResponse($user, $password, $url, &$challenge) - { - if (false !== ($q = strpos($url, '?')) && - $this->request->getConfig('digest_compat_ie') - ) { - $url = substr($url, 0, $q); - } - - $a1 = md5($user . ':' . $challenge['realm'] . ':' . $password); - $a2 = md5($this->request->getMethod() . ':' . $url); - - if (empty($challenge['qop'])) { - $digest = md5($a1 . ':' . $challenge['nonce'] . ':' . $a2); - } else { - $challenge['cnonce'] = 'Req2.' . rand(); - if (empty($challenge['nc'])) { - $challenge['nc'] = 1; - } - $nc = sprintf('%08x', $challenge['nc']++); - $digest = md5($a1 . ':' . $challenge['nonce'] . ':' . $nc . ':' . - $challenge['cnonce'] . ':auth:' . $a2); - } - return 'Digest username="' . str_replace(array('\\', '"'), array('\\\\', '\\"'), $user) . '", ' . - 'realm="' . $challenge['realm'] . '", ' . - 'nonce="' . $challenge['nonce'] . '", ' . - 'uri="' . $url . '", ' . - 'response="' . $digest . '"' . - (!empty($challenge['opaque'])? - ', opaque="' . $challenge['opaque'] . '"': - '') . - (!empty($challenge['qop'])? - ', qop="auth", nc=' . $nc . ', cnonce="' . $challenge['cnonce'] . '"': - ''); - } - - /** - * Adds 'Authorization' header (if needed) to request headers array - * - * @param array request headers - * @param string request host (needed for digest authentication) - * @param string request URL (needed for digest authentication) - * @throws HTTP_Request2_Exception - */ - protected function addAuthorizationHeader(&$headers, $requestHost, $requestUrl) - { - if (!($auth = $this->request->getAuth())) { - return; - } - switch ($auth['scheme']) { - case HTTP_Request2::AUTH_BASIC: - $headers['authorization'] = - 'Basic ' . base64_encode($auth['user'] . ':' . $auth['password']); - break; - - case HTTP_Request2::AUTH_DIGEST: - unset($this->serverChallenge); - $fullUrl = ('/' == $requestUrl[0])? - $this->request->getUrl()->getScheme() . '://' . - $requestHost . $requestUrl: - $requestUrl; - foreach (array_keys(self::$challenges) as $key) { - if ($key == substr($fullUrl, 0, strlen($key))) { - $headers['authorization'] = $this->createDigestResponse( - $auth['user'], $auth['password'], - $requestUrl, self::$challenges[$key] - ); - $this->serverChallenge =& self::$challenges[$key]; - break; - } - } - break; - - default: - throw new HTTP_Request2_Exception( - "Unknown HTTP authentication scheme '{$auth['scheme']}'" - ); - } - } - - /** - * Adds 'Proxy-Authorization' header (if needed) to request headers array - * - * @param array request headers - * @param string request URL (needed for digest authentication) - * @throws HTTP_Request2_Exception - */ - protected function addProxyAuthorizationHeader(&$headers, $requestUrl) - { - if (!$this->request->getConfig('proxy_host') || - !($user = $this->request->getConfig('proxy_user')) || - (0 == strcasecmp('https', $this->request->getUrl()->getScheme()) && - HTTP_Request2::METHOD_CONNECT != $this->request->getMethod()) - ) { - return; - } - - $password = $this->request->getConfig('proxy_password'); - switch ($this->request->getConfig('proxy_auth_scheme')) { - case HTTP_Request2::AUTH_BASIC: - $headers['proxy-authorization'] = - 'Basic ' . base64_encode($user . ':' . $password); - break; - - case HTTP_Request2::AUTH_DIGEST: - unset($this->proxyChallenge); - $proxyUrl = 'proxy://' . $this->request->getConfig('proxy_host') . - ':' . $this->request->getConfig('proxy_port'); - if (!empty(self::$challenges[$proxyUrl])) { - $headers['proxy-authorization'] = $this->createDigestResponse( - $user, $password, - $requestUrl, self::$challenges[$proxyUrl] - ); - $this->proxyChallenge =& self::$challenges[$proxyUrl]; - } - break; - - default: - throw new HTTP_Request2_Exception( - "Unknown HTTP authentication scheme '" . - $this->request->getConfig('proxy_auth_scheme') . "'" - ); - } - } - - - /** - * Creates the string with the Request-Line and request headers - * - * @return string - * @throws HTTP_Request2_Exception - */ - protected function prepareHeaders() - { - $headers = $this->request->getHeaders(); - $url = $this->request->getUrl(); - $connect = HTTP_Request2::METHOD_CONNECT == $this->request->getMethod(); - $host = $url->getHost(); - - $defaultPort = 0 == strcasecmp($url->getScheme(), 'https')? 443: 80; - if (($port = $url->getPort()) && $port != $defaultPort || $connect) { - $host .= ':' . (empty($port)? $defaultPort: $port); - } - // Do not overwrite explicitly set 'Host' header, see bug #16146 - if (!isset($headers['host'])) { - $headers['host'] = $host; - } - - if ($connect) { - $requestUrl = $host; - - } else { - if (!$this->request->getConfig('proxy_host') || - 0 == strcasecmp($url->getScheme(), 'https') - ) { - $requestUrl = ''; - } else { - $requestUrl = $url->getScheme() . '://' . $host; - } - $path = $url->getPath(); - $query = $url->getQuery(); - $requestUrl .= (empty($path)? '/': $path) . (empty($query)? '': '?' . $query); - } - - if ('1.1' == $this->request->getConfig('protocol_version') && - extension_loaded('zlib') && !isset($headers['accept-encoding']) - ) { - $headers['accept-encoding'] = 'gzip, deflate'; - } - - $this->addAuthorizationHeader($headers, $host, $requestUrl); - $this->addProxyAuthorizationHeader($headers, $requestUrl); - $this->calculateRequestLength($headers); - - $headersStr = $this->request->getMethod() . ' ' . $requestUrl . ' HTTP/' . - $this->request->getConfig('protocol_version') . "\r\n"; - foreach ($headers as $name => $value) { - $canonicalName = implode('-', array_map('ucfirst', explode('-', $name))); - $headersStr .= $canonicalName . ': ' . $value . "\r\n"; - } - return $headersStr . "\r\n"; - } - - /** - * Sends the request body - * - * @throws HTTP_Request2_Exception - */ - protected function writeBody() - { - if (in_array($this->request->getMethod(), self::$bodyDisallowed) || - 0 == $this->contentLength - ) { - return; - } - - $position = 0; - $bufferSize = $this->request->getConfig('buffer_size'); - while ($position < $this->contentLength) { - if (is_string($this->requestBody)) { - $str = substr($this->requestBody, $position, $bufferSize); - } elseif (is_resource($this->requestBody)) { - $str = fread($this->requestBody, $bufferSize); - } else { - $str = $this->requestBody->read($bufferSize); - } - if (false === @fwrite($this->socket, $str, strlen($str))) { - throw new HTTP_Request2_Exception('Error writing request'); - } - // Provide the length of written string to the observer, request #7630 - $this->request->setLastEvent('sentBodyPart', strlen($str)); - $position += strlen($str); - } - } - - /** - * Reads the remote server's response - * - * @return HTTP_Request2_Response - * @throws HTTP_Request2_Exception - */ - protected function readResponse() - { - $bufferSize = $this->request->getConfig('buffer_size'); - - do { - $response = new HTTP_Request2_Response($this->readLine($bufferSize), true); - do { - $headerLine = $this->readLine($bufferSize); - $response->parseHeaderLine($headerLine); - } while ('' != $headerLine); - } while (in_array($response->getStatus(), array(100, 101))); - - $this->request->setLastEvent('receivedHeaders', $response); - - // No body possible in such responses - if (HTTP_Request2::METHOD_HEAD == $this->request->getMethod() || - (HTTP_Request2::METHOD_CONNECT == $this->request->getMethod() && - 200 <= $response->getStatus() && 300 > $response->getStatus()) || - in_array($response->getStatus(), array(204, 304)) - ) { - return $response; - } - - $chunked = 'chunked' == $response->getHeader('transfer-encoding'); - $length = $response->getHeader('content-length'); - $hasBody = false; - if ($chunked || null === $length || 0 < intval($length)) { - // RFC 2616, section 4.4: - // 3. ... If a message is received with both a - // Transfer-Encoding header field and a Content-Length header field, - // the latter MUST be ignored. - $toRead = ($chunked || null === $length)? null: $length; - $this->chunkLength = 0; - - while (!feof($this->socket) && (is_null($toRead) || 0 < $toRead)) { - if ($chunked) { - $data = $this->readChunked($bufferSize); - } elseif (is_null($toRead)) { - $data = $this->fread($bufferSize); - } else { - $data = $this->fread(min($toRead, $bufferSize)); - $toRead -= strlen($data); - } - if ('' == $data && (!$this->chunkLength || feof($this->socket))) { - break; - } - - $hasBody = true; - if ($this->request->getConfig('store_body')) { - $response->appendBody($data); - } - if (!in_array($response->getHeader('content-encoding'), array('identity', null))) { - $this->request->setLastEvent('receivedEncodedBodyPart', $data); - } else { - $this->request->setLastEvent('receivedBodyPart', $data); - } - } - } - - if ($hasBody) { - $this->request->setLastEvent('receivedBody', $response); - } - return $response; - } - - /** - * Reads until either the end of the socket or a newline, whichever comes first - * - * Strips the trailing newline from the returned data, handles global - * request timeout. Method idea borrowed from Net_Socket PEAR package. - * - * @param int buffer size to use for reading - * @return Available data up to the newline (not including newline) - * @throws HTTP_Request2_Exception In case of timeout - */ - protected function readLine($bufferSize) - { - $line = ''; - while (!feof($this->socket)) { - if ($this->timeout) { - stream_set_timeout($this->socket, max($this->timeout - time(), 1)); - } - $line .= @fgets($this->socket, $bufferSize); - $info = stream_get_meta_data($this->socket); - if ($info['timed_out'] || $this->timeout && time() > $this->timeout) { - throw new HTTP_Request2_Exception( - 'Request timed out after ' . - $this->request->getConfig('timeout') . ' second(s)' - ); - } - if (substr($line, -1) == "\n") { - return rtrim($line, "\r\n"); - } - } - return $line; - } - - /** - * Wrapper around fread(), handles global request timeout - * - * @param int Reads up to this number of bytes - * @return Data read from socket - * @throws HTTP_Request2_Exception In case of timeout - */ - protected function fread($length) - { - if ($this->timeout) { - stream_set_timeout($this->socket, max($this->timeout - time(), 1)); - } - $data = fread($this->socket, $length); - $info = stream_get_meta_data($this->socket); - if ($info['timed_out'] || $this->timeout && time() > $this->timeout) { - throw new HTTP_Request2_Exception( - 'Request timed out after ' . - $this->request->getConfig('timeout') . ' second(s)' - ); - } - return $data; - } - - /** - * Reads a part of response body encoded with chunked Transfer-Encoding - * - * @param int buffer size to use for reading - * @return string - * @throws HTTP_Request2_Exception - */ - protected function readChunked($bufferSize) - { - // at start of the next chunk? - if (0 == $this->chunkLength) { - $line = $this->readLine($bufferSize); - if (!preg_match('/^([0-9a-f]+)/i', $line, $matches)) { - throw new HTTP_Request2_Exception( - "Cannot decode chunked response, invalid chunk length '{$line}'" - ); - } else { - $this->chunkLength = hexdec($matches[1]); - // Chunk with zero length indicates the end - if (0 == $this->chunkLength) { - $this->readLine($bufferSize); - return ''; - } - } - } - $data = $this->fread(min($this->chunkLength, $bufferSize)); - $this->chunkLength -= strlen($data); - if (0 == $this->chunkLength) { - $this->readLine($bufferSize); // Trailing CRLF - } - return $data; - } -} - + + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Socket.php 279760 2009-05-03 10:46:42Z avb $ + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** + * Base class for HTTP_Request2 adapters + */ +require_once 'HTTP/Request2/Adapter.php'; + +/** + * Socket-based adapter for HTTP_Request2 + * + * This adapter uses only PHP sockets and will work on almost any PHP + * environment. Code is based on original HTTP_Request PEAR package. + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @version Release: 0.4.1 + */ +class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter +{ + /** + * Regular expression for 'token' rule from RFC 2616 + */ + const REGEXP_TOKEN = '[^\x00-\x1f\x7f-\xff()<>@,;:\\\\"/\[\]?={}\s]+'; + + /** + * Regular expression for 'quoted-string' rule from RFC 2616 + */ + const REGEXP_QUOTED_STRING = '"(?:\\\\.|[^\\\\"])*"'; + + /** + * Connected sockets, needed for Keep-Alive support + * @var array + * @see connect() + */ + protected static $sockets = array(); + + /** + * Data for digest authentication scheme + * + * The keys for the array are URL prefixes. + * + * The values are associative arrays with data (realm, nonce, nonce-count, + * opaque...) needed for digest authentication. Stored here to prevent making + * duplicate requests to digest-protected resources after we have already + * received the challenge. + * + * @var array + */ + protected static $challenges = array(); + + /** + * Connected socket + * @var resource + * @see connect() + */ + protected $socket; + + /** + * Challenge used for server digest authentication + * @var array + */ + protected $serverChallenge; + + /** + * Challenge used for proxy digest authentication + * @var array + */ + protected $proxyChallenge; + + /** + * Global timeout, exception will be raised if request continues past this time + * @var integer + */ + protected $timeout = null; + + /** + * Remaining length of the current chunk, when reading chunked response + * @var integer + * @see readChunked() + */ + protected $chunkLength = 0; + + /** + * Sends request to the remote server and returns its response + * + * @param HTTP_Request2 + * @return HTTP_Request2_Response + * @throws HTTP_Request2_Exception + */ + public function sendRequest(HTTP_Request2 $request) + { + $this->request = $request; + $keepAlive = $this->connect(); + $headers = $this->prepareHeaders(); + + // Use global request timeout if given, see feature requests #5735, #8964 + if ($timeout = $request->getConfig('timeout')) { + $this->timeout = time() + $timeout; + } else { + $this->timeout = null; + } + + try { + if (false === @fwrite($this->socket, $headers, strlen($headers))) { + throw new HTTP_Request2_Exception('Error writing request'); + } + // provide request headers to the observer, see request #7633 + $this->request->setLastEvent('sentHeaders', $headers); + $this->writeBody(); + + if ($this->timeout && time() > $this->timeout) { + throw new HTTP_Request2_Exception( + 'Request timed out after ' . + $request->getConfig('timeout') . ' second(s)' + ); + } + + $response = $this->readResponse(); + + if (!$this->canKeepAlive($keepAlive, $response)) { + $this->disconnect(); + } + + if ($this->shouldUseProxyDigestAuth($response)) { + return $this->sendRequest($request); + } + if ($this->shouldUseServerDigestAuth($response)) { + return $this->sendRequest($request); + } + if ($authInfo = $response->getHeader('authentication-info')) { + $this->updateChallenge($this->serverChallenge, $authInfo); + } + if ($proxyInfo = $response->getHeader('proxy-authentication-info')) { + $this->updateChallenge($this->proxyChallenge, $proxyInfo); + } + + } catch (Exception $e) { + $this->disconnect(); + throw $e; + } + + return $response; + } + + /** + * Connects to the remote server + * + * @return bool whether the connection can be persistent + * @throws HTTP_Request2_Exception + */ + protected function connect() + { + $secure = 0 == strcasecmp($this->request->getUrl()->getScheme(), 'https'); + $tunnel = HTTP_Request2::METHOD_CONNECT == $this->request->getMethod(); + $headers = $this->request->getHeaders(); + $reqHost = $this->request->getUrl()->getHost(); + if (!($reqPort = $this->request->getUrl()->getPort())) { + $reqPort = $secure? 443: 80; + } + + if ($host = $this->request->getConfig('proxy_host')) { + if (!($port = $this->request->getConfig('proxy_port'))) { + throw new HTTP_Request2_Exception('Proxy port not provided'); + } + $proxy = true; + } else { + $host = $reqHost; + $port = $reqPort; + $proxy = false; + } + + if ($tunnel && !$proxy) { + throw new HTTP_Request2_Exception( + "Trying to perform CONNECT request without proxy" + ); + } + if ($secure && !in_array('ssl', stream_get_transports())) { + throw new HTTP_Request2_Exception( + 'Need OpenSSL support for https:// requests' + ); + } + + // RFC 2068, section 19.7.1: A client MUST NOT send the Keep-Alive + // connection token to a proxy server... + if ($proxy && !$secure && + !empty($headers['connection']) && 'Keep-Alive' == $headers['connection'] + ) { + $this->request->setHeader('connection'); + } + + $keepAlive = ('1.1' == $this->request->getConfig('protocol_version') && + empty($headers['connection'])) || + (!empty($headers['connection']) && + 'Keep-Alive' == $headers['connection']); + $host = ((!$secure || $proxy)? 'tcp://': 'ssl://') . $host; + + $options = array(); + if ($secure || $tunnel) { + foreach ($this->request->getConfig() as $name => $value) { + if ('ssl_' == substr($name, 0, 4) && null !== $value) { + if ('ssl_verify_host' == $name) { + if ($value) { + $options['CN_match'] = $reqHost; + } + } else { + $options[substr($name, 4)] = $value; + } + } + } + ksort($options); + } + + // Changing SSL context options after connection is established does *not* + // work, we need a new connection if options change + $remote = $host . ':' . $port; + $socketKey = $remote . (($secure && $proxy)? "->{$reqHost}:{$reqPort}": '') . + (empty($options)? '': ':' . serialize($options)); + unset($this->socket); + + // We use persistent connections and have a connected socket? + // Ensure that the socket is still connected, see bug #16149 + if ($keepAlive && !empty(self::$sockets[$socketKey]) && + !feof(self::$sockets[$socketKey]) + ) { + $this->socket =& self::$sockets[$socketKey]; + + } elseif ($secure && $proxy && !$tunnel) { + $this->establishTunnel(); + $this->request->setLastEvent( + 'connect', "ssl://{$reqHost}:{$reqPort} via {$host}:{$port}" + ); + self::$sockets[$socketKey] =& $this->socket; + + } else { + // Set SSL context options if doing HTTPS request or creating a tunnel + $context = stream_context_create(); + foreach ($options as $name => $value) { + if (!stream_context_set_option($context, 'ssl', $name, $value)) { + throw new HTTP_Request2_Exception( + "Error setting SSL context option '{$name}'" + ); + } + } + $this->socket = @stream_socket_client( + $remote, $errno, $errstr, + $this->request->getConfig('connect_timeout'), + STREAM_CLIENT_CONNECT, $context + ); + if (!$this->socket) { + throw new HTTP_Request2_Exception( + "Unable to connect to {$remote}. Error #{$errno}: {$errstr}" + ); + } + $this->request->setLastEvent('connect', $remote); + self::$sockets[$socketKey] =& $this->socket; + } + return $keepAlive; + } + + /** + * Establishes a tunnel to a secure remote server via HTTP CONNECT request + * + * This method will fail if 'ssl_verify_peer' is enabled. Probably because PHP + * sees that we are connected to a proxy server (duh!) rather than the server + * that presents its certificate. + * + * @link http://tools.ietf.org/html/rfc2817#section-5.2 + * @throws HTTP_Request2_Exception + */ + protected function establishTunnel() + { + $donor = new self; + $connect = new HTTP_Request2( + $this->request->getUrl(), HTTP_Request2::METHOD_CONNECT, + array_merge($this->request->getConfig(), + array('adapter' => $donor)) + ); + $response = $connect->send(); + // Need any successful (2XX) response + if (200 > $response->getStatus() || 300 <= $response->getStatus()) { + throw new HTTP_Request2_Exception( + 'Failed to connect via HTTPS proxy. Proxy response: ' . + $response->getStatus() . ' ' . $response->getReasonPhrase() + ); + } + $this->socket = $donor->socket; + + $modes = array( + STREAM_CRYPTO_METHOD_TLS_CLIENT, + STREAM_CRYPTO_METHOD_SSLv3_CLIENT, + STREAM_CRYPTO_METHOD_SSLv23_CLIENT, + STREAM_CRYPTO_METHOD_SSLv2_CLIENT + ); + + foreach ($modes as $mode) { + if (stream_socket_enable_crypto($this->socket, true, $mode)) { + return; + } + } + throw new HTTP_Request2_Exception( + 'Failed to enable secure connection when connecting through proxy' + ); + } + + /** + * Checks whether current connection may be reused or should be closed + * + * @param boolean whether connection could be persistent + * in the first place + * @param HTTP_Request2_Response response object to check + * @return boolean + */ + protected function canKeepAlive($requestKeepAlive, HTTP_Request2_Response $response) + { + // Do not close socket on successful CONNECT request + if (HTTP_Request2::METHOD_CONNECT == $this->request->getMethod() && + 200 <= $response->getStatus() && 300 > $response->getStatus() + ) { + return true; + } + + $lengthKnown = 'chunked' == strtolower($response->getHeader('transfer-encoding')) || + null !== $response->getHeader('content-length'); + $persistent = 'keep-alive' == strtolower($response->getHeader('connection')) || + (null === $response->getHeader('connection') && + '1.1' == $response->getVersion()); + return $requestKeepAlive && $lengthKnown && $persistent; + } + + /** + * Disconnects from the remote server + */ + protected function disconnect() + { + if (is_resource($this->socket)) { + fclose($this->socket); + $this->socket = null; + $this->request->setLastEvent('disconnect'); + } + } + + /** + * Checks whether another request should be performed with server digest auth + * + * Several conditions should be satisfied for it to return true: + * - response status should be 401 + * - auth credentials should be set in the request object + * - response should contain WWW-Authenticate header with digest challenge + * - there is either no challenge stored for this URL or new challenge + * contains stale=true parameter (in other case we probably just failed + * due to invalid username / password) + * + * The method stores challenge values in $challenges static property + * + * @param HTTP_Request2_Response response to check + * @return boolean whether another request should be performed + * @throws HTTP_Request2_Exception in case of unsupported challenge parameters + */ + protected function shouldUseServerDigestAuth(HTTP_Request2_Response $response) + { + // no sense repeating a request if we don't have credentials + if (401 != $response->getStatus() || !$this->request->getAuth()) { + return false; + } + if (!$challenge = $this->parseDigestChallenge($response->getHeader('www-authenticate'))) { + return false; + } + + $url = $this->request->getUrl(); + $scheme = $url->getScheme(); + $host = $scheme . '://' . $url->getHost(); + if ($port = $url->getPort()) { + if ((0 == strcasecmp($scheme, 'http') && 80 != $port) || + (0 == strcasecmp($scheme, 'https') && 443 != $port) + ) { + $host .= ':' . $port; + } + } + + if (!empty($challenge['domain'])) { + $prefixes = array(); + foreach (preg_split('/\\s+/', $challenge['domain']) as $prefix) { + // don't bother with different servers + if ('/' == substr($prefix, 0, 1)) { + $prefixes[] = $host . $prefix; + } + } + } + if (empty($prefixes)) { + $prefixes = array($host . '/'); + } + + $ret = true; + foreach ($prefixes as $prefix) { + if (!empty(self::$challenges[$prefix]) && + (empty($challenge['stale']) || strcasecmp('true', $challenge['stale'])) + ) { + // probably credentials are invalid + $ret = false; + } + self::$challenges[$prefix] =& $challenge; + } + return $ret; + } + + /** + * Checks whether another request should be performed with proxy digest auth + * + * Several conditions should be satisfied for it to return true: + * - response status should be 407 + * - proxy auth credentials should be set in the request object + * - response should contain Proxy-Authenticate header with digest challenge + * - there is either no challenge stored for this proxy or new challenge + * contains stale=true parameter (in other case we probably just failed + * due to invalid username / password) + * + * The method stores challenge values in $challenges static property + * + * @param HTTP_Request2_Response response to check + * @return boolean whether another request should be performed + * @throws HTTP_Request2_Exception in case of unsupported challenge parameters + */ + protected function shouldUseProxyDigestAuth(HTTP_Request2_Response $response) + { + if (407 != $response->getStatus() || !$this->request->getConfig('proxy_user')) { + return false; + } + if (!($challenge = $this->parseDigestChallenge($response->getHeader('proxy-authenticate')))) { + return false; + } + + $key = 'proxy://' . $this->request->getConfig('proxy_host') . + ':' . $this->request->getConfig('proxy_port'); + + if (!empty(self::$challenges[$key]) && + (empty($challenge['stale']) || strcasecmp('true', $challenge['stale'])) + ) { + $ret = false; + } else { + $ret = true; + } + self::$challenges[$key] = $challenge; + return $ret; + } + + /** + * Extracts digest method challenge from (WWW|Proxy)-Authenticate header value + * + * There is a problem with implementation of RFC 2617: several of the parameters + * here are defined as quoted-string and thus may contain backslash escaped + * double quotes (RFC 2616, section 2.2). However, RFC 2617 defines unq(X) as + * just value of quoted-string X without surrounding quotes, it doesn't speak + * about removing backslash escaping. + * + * Now realm parameter is user-defined and human-readable, strange things + * happen when it contains quotes: + * - Apache allows quotes in realm, but apparently uses realm value without + * backslashes for digest computation + * - Squid allows (manually escaped) quotes there, but it is impossible to + * authorize with either escaped or unescaped quotes used in digest, + * probably it cannot parse the response (?) + * - Both IE and Firefox display realm value with backslashes in + * the password popup and apparently use the same value for digest + * + * HTTP_Request2 follows IE and Firefox (and hopefully RFC 2617) in + * quoted-string handling, unfortunately that means failure to authorize + * sometimes + * + * @param string value of WWW-Authenticate or Proxy-Authenticate header + * @return mixed associative array with challenge parameters, false if + * no challenge is present in header value + * @throws HTTP_Request2_Exception in case of unsupported challenge parameters + */ + protected function parseDigestChallenge($headerValue) + { + $authParam = '(' . self::REGEXP_TOKEN . ')\\s*=\\s*(' . + self::REGEXP_TOKEN . '|' . self::REGEXP_QUOTED_STRING . ')'; + $challenge = "!(?<=^|\\s|,)Digest ({$authParam}\\s*(,\\s*|$))+!"; + if (!preg_match($challenge, $headerValue, $matches)) { + return false; + } + + preg_match_all('!' . $authParam . '!', $matches[0], $params); + $paramsAry = array(); + $knownParams = array('realm', 'domain', 'nonce', 'opaque', 'stale', + 'algorithm', 'qop'); + for ($i = 0; $i < count($params[0]); $i++) { + // section 3.2.1: Any unrecognized directive MUST be ignored. + if (in_array($params[1][$i], $knownParams)) { + if ('"' == substr($params[2][$i], 0, 1)) { + $paramsAry[$params[1][$i]] = substr($params[2][$i], 1, -1); + } else { + $paramsAry[$params[1][$i]] = $params[2][$i]; + } + } + } + // we only support qop=auth + if (!empty($paramsAry['qop']) && + !in_array('auth', array_map('trim', explode(',', $paramsAry['qop']))) + ) { + throw new HTTP_Request2_Exception( + "Only 'auth' qop is currently supported in digest authentication, " . + "server requested '{$paramsAry['qop']}'" + ); + } + // we only support algorithm=MD5 + if (!empty($paramsAry['algorithm']) && 'MD5' != $paramsAry['algorithm']) { + throw new HTTP_Request2_Exception( + "Only 'MD5' algorithm is currently supported in digest authentication, " . + "server requested '{$paramsAry['algorithm']}'" + ); + } + + return $paramsAry; + } + + /** + * Parses [Proxy-]Authentication-Info header value and updates challenge + * + * @param array challenge to update + * @param string value of [Proxy-]Authentication-Info header + * @todo validate server rspauth response + */ + protected function updateChallenge(&$challenge, $headerValue) + { + $authParam = '!(' . self::REGEXP_TOKEN . ')\\s*=\\s*(' . + self::REGEXP_TOKEN . '|' . self::REGEXP_QUOTED_STRING . ')!'; + $paramsAry = array(); + + preg_match_all($authParam, $headerValue, $params); + for ($i = 0; $i < count($params[0]); $i++) { + if ('"' == substr($params[2][$i], 0, 1)) { + $paramsAry[$params[1][$i]] = substr($params[2][$i], 1, -1); + } else { + $paramsAry[$params[1][$i]] = $params[2][$i]; + } + } + // for now, just update the nonce value + if (!empty($paramsAry['nextnonce'])) { + $challenge['nonce'] = $paramsAry['nextnonce']; + $challenge['nc'] = 1; + } + } + + /** + * Creates a value for [Proxy-]Authorization header when using digest authentication + * + * @param string user name + * @param string password + * @param string request URL + * @param array digest challenge parameters + * @return string value of [Proxy-]Authorization request header + * @link http://tools.ietf.org/html/rfc2617#section-3.2.2 + */ + protected function createDigestResponse($user, $password, $url, &$challenge) + { + if (false !== ($q = strpos($url, '?')) && + $this->request->getConfig('digest_compat_ie') + ) { + $url = substr($url, 0, $q); + } + + $a1 = md5($user . ':' . $challenge['realm'] . ':' . $password); + $a2 = md5($this->request->getMethod() . ':' . $url); + + if (empty($challenge['qop'])) { + $digest = md5($a1 . ':' . $challenge['nonce'] . ':' . $a2); + } else { + $challenge['cnonce'] = 'Req2.' . rand(); + if (empty($challenge['nc'])) { + $challenge['nc'] = 1; + } + $nc = sprintf('%08x', $challenge['nc']++); + $digest = md5($a1 . ':' . $challenge['nonce'] . ':' . $nc . ':' . + $challenge['cnonce'] . ':auth:' . $a2); + } + return 'Digest username="' . str_replace(array('\\', '"'), array('\\\\', '\\"'), $user) . '", ' . + 'realm="' . $challenge['realm'] . '", ' . + 'nonce="' . $challenge['nonce'] . '", ' . + 'uri="' . $url . '", ' . + 'response="' . $digest . '"' . + (!empty($challenge['opaque'])? + ', opaque="' . $challenge['opaque'] . '"': + '') . + (!empty($challenge['qop'])? + ', qop="auth", nc=' . $nc . ', cnonce="' . $challenge['cnonce'] . '"': + ''); + } + + /** + * Adds 'Authorization' header (if needed) to request headers array + * + * @param array request headers + * @param string request host (needed for digest authentication) + * @param string request URL (needed for digest authentication) + * @throws HTTP_Request2_Exception + */ + protected function addAuthorizationHeader(&$headers, $requestHost, $requestUrl) + { + if (!($auth = $this->request->getAuth())) { + return; + } + switch ($auth['scheme']) { + case HTTP_Request2::AUTH_BASIC: + $headers['authorization'] = + 'Basic ' . base64_encode($auth['user'] . ':' . $auth['password']); + break; + + case HTTP_Request2::AUTH_DIGEST: + unset($this->serverChallenge); + $fullUrl = ('/' == $requestUrl[0])? + $this->request->getUrl()->getScheme() . '://' . + $requestHost . $requestUrl: + $requestUrl; + foreach (array_keys(self::$challenges) as $key) { + if ($key == substr($fullUrl, 0, strlen($key))) { + $headers['authorization'] = $this->createDigestResponse( + $auth['user'], $auth['password'], + $requestUrl, self::$challenges[$key] + ); + $this->serverChallenge =& self::$challenges[$key]; + break; + } + } + break; + + default: + throw new HTTP_Request2_Exception( + "Unknown HTTP authentication scheme '{$auth['scheme']}'" + ); + } + } + + /** + * Adds 'Proxy-Authorization' header (if needed) to request headers array + * + * @param array request headers + * @param string request URL (needed for digest authentication) + * @throws HTTP_Request2_Exception + */ + protected function addProxyAuthorizationHeader(&$headers, $requestUrl) + { + if (!$this->request->getConfig('proxy_host') || + !($user = $this->request->getConfig('proxy_user')) || + (0 == strcasecmp('https', $this->request->getUrl()->getScheme()) && + HTTP_Request2::METHOD_CONNECT != $this->request->getMethod()) + ) { + return; + } + + $password = $this->request->getConfig('proxy_password'); + switch ($this->request->getConfig('proxy_auth_scheme')) { + case HTTP_Request2::AUTH_BASIC: + $headers['proxy-authorization'] = + 'Basic ' . base64_encode($user . ':' . $password); + break; + + case HTTP_Request2::AUTH_DIGEST: + unset($this->proxyChallenge); + $proxyUrl = 'proxy://' . $this->request->getConfig('proxy_host') . + ':' . $this->request->getConfig('proxy_port'); + if (!empty(self::$challenges[$proxyUrl])) { + $headers['proxy-authorization'] = $this->createDigestResponse( + $user, $password, + $requestUrl, self::$challenges[$proxyUrl] + ); + $this->proxyChallenge =& self::$challenges[$proxyUrl]; + } + break; + + default: + throw new HTTP_Request2_Exception( + "Unknown HTTP authentication scheme '" . + $this->request->getConfig('proxy_auth_scheme') . "'" + ); + } + } + + + /** + * Creates the string with the Request-Line and request headers + * + * @return string + * @throws HTTP_Request2_Exception + */ + protected function prepareHeaders() + { + $headers = $this->request->getHeaders(); + $url = $this->request->getUrl(); + $connect = HTTP_Request2::METHOD_CONNECT == $this->request->getMethod(); + $host = $url->getHost(); + + $defaultPort = 0 == strcasecmp($url->getScheme(), 'https')? 443: 80; + if (($port = $url->getPort()) && $port != $defaultPort || $connect) { + $host .= ':' . (empty($port)? $defaultPort: $port); + } + // Do not overwrite explicitly set 'Host' header, see bug #16146 + if (!isset($headers['host'])) { + $headers['host'] = $host; + } + + if ($connect) { + $requestUrl = $host; + + } else { + if (!$this->request->getConfig('proxy_host') || + 0 == strcasecmp($url->getScheme(), 'https') + ) { + $requestUrl = ''; + } else { + $requestUrl = $url->getScheme() . '://' . $host; + } + $path = $url->getPath(); + $query = $url->getQuery(); + $requestUrl .= (empty($path)? '/': $path) . (empty($query)? '': '?' . $query); + } + + if ('1.1' == $this->request->getConfig('protocol_version') && + extension_loaded('zlib') && !isset($headers['accept-encoding']) + ) { + $headers['accept-encoding'] = 'gzip, deflate'; + } + + $this->addAuthorizationHeader($headers, $host, $requestUrl); + $this->addProxyAuthorizationHeader($headers, $requestUrl); + $this->calculateRequestLength($headers); + + $headersStr = $this->request->getMethod() . ' ' . $requestUrl . ' HTTP/' . + $this->request->getConfig('protocol_version') . "\r\n"; + foreach ($headers as $name => $value) { + $canonicalName = implode('-', array_map('ucfirst', explode('-', $name))); + $headersStr .= $canonicalName . ': ' . $value . "\r\n"; + } + return $headersStr . "\r\n"; + } + + /** + * Sends the request body + * + * @throws HTTP_Request2_Exception + */ + protected function writeBody() + { + if (in_array($this->request->getMethod(), self::$bodyDisallowed) || + 0 == $this->contentLength + ) { + return; + } + + $position = 0; + $bufferSize = $this->request->getConfig('buffer_size'); + while ($position < $this->contentLength) { + if (is_string($this->requestBody)) { + $str = substr($this->requestBody, $position, $bufferSize); + } elseif (is_resource($this->requestBody)) { + $str = fread($this->requestBody, $bufferSize); + } else { + $str = $this->requestBody->read($bufferSize); + } + if (false === @fwrite($this->socket, $str, strlen($str))) { + throw new HTTP_Request2_Exception('Error writing request'); + } + // Provide the length of written string to the observer, request #7630 + $this->request->setLastEvent('sentBodyPart', strlen($str)); + $position += strlen($str); + } + } + + /** + * Reads the remote server's response + * + * @return HTTP_Request2_Response + * @throws HTTP_Request2_Exception + */ + protected function readResponse() + { + $bufferSize = $this->request->getConfig('buffer_size'); + + do { + $response = new HTTP_Request2_Response($this->readLine($bufferSize), true); + do { + $headerLine = $this->readLine($bufferSize); + $response->parseHeaderLine($headerLine); + } while ('' != $headerLine); + } while (in_array($response->getStatus(), array(100, 101))); + + $this->request->setLastEvent('receivedHeaders', $response); + + // No body possible in such responses + if (HTTP_Request2::METHOD_HEAD == $this->request->getMethod() || + (HTTP_Request2::METHOD_CONNECT == $this->request->getMethod() && + 200 <= $response->getStatus() && 300 > $response->getStatus()) || + in_array($response->getStatus(), array(204, 304)) + ) { + return $response; + } + + $chunked = 'chunked' == $response->getHeader('transfer-encoding'); + $length = $response->getHeader('content-length'); + $hasBody = false; + if ($chunked || null === $length || 0 < intval($length)) { + // RFC 2616, section 4.4: + // 3. ... If a message is received with both a + // Transfer-Encoding header field and a Content-Length header field, + // the latter MUST be ignored. + $toRead = ($chunked || null === $length)? null: $length; + $this->chunkLength = 0; + + while (!feof($this->socket) && (is_null($toRead) || 0 < $toRead)) { + if ($chunked) { + $data = $this->readChunked($bufferSize); + } elseif (is_null($toRead)) { + $data = $this->fread($bufferSize); + } else { + $data = $this->fread(min($toRead, $bufferSize)); + $toRead -= strlen($data); + } + if ('' == $data && (!$this->chunkLength || feof($this->socket))) { + break; + } + + $hasBody = true; + if ($this->request->getConfig('store_body')) { + $response->appendBody($data); + } + if (!in_array($response->getHeader('content-encoding'), array('identity', null))) { + $this->request->setLastEvent('receivedEncodedBodyPart', $data); + } else { + $this->request->setLastEvent('receivedBodyPart', $data); + } + } + } + + if ($hasBody) { + $this->request->setLastEvent('receivedBody', $response); + } + return $response; + } + + /** + * Reads until either the end of the socket or a newline, whichever comes first + * + * Strips the trailing newline from the returned data, handles global + * request timeout. Method idea borrowed from Net_Socket PEAR package. + * + * @param int buffer size to use for reading + * @return Available data up to the newline (not including newline) + * @throws HTTP_Request2_Exception In case of timeout + */ + protected function readLine($bufferSize) + { + $line = ''; + while (!feof($this->socket)) { + if ($this->timeout) { + stream_set_timeout($this->socket, max($this->timeout - time(), 1)); + } + $line .= @fgets($this->socket, $bufferSize); + $info = stream_get_meta_data($this->socket); + if ($info['timed_out'] || $this->timeout && time() > $this->timeout) { + throw new HTTP_Request2_Exception( + 'Request timed out after ' . + $this->request->getConfig('timeout') . ' second(s)' + ); + } + if (substr($line, -1) == "\n") { + return rtrim($line, "\r\n"); + } + } + return $line; + } + + /** + * Wrapper around fread(), handles global request timeout + * + * @param int Reads up to this number of bytes + * @return Data read from socket + * @throws HTTP_Request2_Exception In case of timeout + */ + protected function fread($length) + { + if ($this->timeout) { + stream_set_timeout($this->socket, max($this->timeout - time(), 1)); + } + $data = fread($this->socket, $length); + $info = stream_get_meta_data($this->socket); + if ($info['timed_out'] || $this->timeout && time() > $this->timeout) { + throw new HTTP_Request2_Exception( + 'Request timed out after ' . + $this->request->getConfig('timeout') . ' second(s)' + ); + } + return $data; + } + + /** + * Reads a part of response body encoded with chunked Transfer-Encoding + * + * @param int buffer size to use for reading + * @return string + * @throws HTTP_Request2_Exception + */ + protected function readChunked($bufferSize) + { + // at start of the next chunk? + if (0 == $this->chunkLength) { + $line = $this->readLine($bufferSize); + if (!preg_match('/^([0-9a-f]+)/i', $line, $matches)) { + throw new HTTP_Request2_Exception( + "Cannot decode chunked response, invalid chunk length '{$line}'" + ); + } else { + $this->chunkLength = hexdec($matches[1]); + // Chunk with zero length indicates the end + if (0 == $this->chunkLength) { + $this->readLine($bufferSize); + return ''; + } + } + } + $data = $this->fread(min($this->chunkLength, $bufferSize)); + $this->chunkLength -= strlen($data); + if (0 == $this->chunkLength) { + $this->readLine($bufferSize); // Trailing CRLF + } + return $data; + } +} + ?> \ No newline at end of file diff --git a/extlib/MIME/Type.php b/extlib/MIME/Type.php index c335f8d92..8653362d3 100644 --- a/extlib/MIME/Type.php +++ b/extlib/MIME/Type.php @@ -478,7 +478,7 @@ class MIME_Type // Don't return an empty string if (!$type || !strlen($type)) { - return PEAR::raiseError("Sorry, couldn't determine file type."); + return PEAR::raiseError("Sorry. Could not determine file type."); } // Strip parameters if present & requested @@ -510,7 +510,7 @@ class MIME_Type $fileCmd = PEAR::getStaticProperty('MIME_Type', 'fileCmd'); if (!$cmd->which($fileCmd)) { unset($cmd); - return PEAR::raiseError("Can't find file command \"{$fileCmd}\""); + return PEAR::raiseError("Cannot find file command \"{$fileCmd}\""); } $cmd->pushCommand($fileCmd, "-bi " . escapeshellarg($file)); diff --git a/extlib/MIME/Type/Extension.php b/extlib/MIME/Type/Extension.php index 1987e2a10..2ffdee9a9 100644 --- a/extlib/MIME/Type/Extension.php +++ b/extlib/MIME/Type/Extension.php @@ -265,7 +265,7 @@ class MIME_Type_Extension } if (!isset($this->extensionToType[$extension])) { - return PEAR::raiseError("Sorry, couldn't determine file type."); + return PEAR::raiseError("Sorry. Could not determine file type."); } return $this->extensionToType[$extension]; @@ -288,7 +288,7 @@ class MIME_Type_Extension $extension = array_search($type, $this->extensionToType); if ($extension === false) { - return PEAR::raiseError("Sorry, couldn't determine extension."); + return PEAR::raiseError("Sorry. Could not determine extension."); } return $extension; } diff --git a/extlib/Mail/mail.php b/extlib/Mail/mail.php index b13d69565..112ff940c 100644 --- a/extlib/Mail/mail.php +++ b/extlib/Mail/mail.php @@ -51,7 +51,7 @@ class Mail_mail extends Mail { } /* Because the mail() function may pass headers as command - * line arguments, we can't guarantee the use of the standard + * line arguments, we cannot guarantee the use of the standard * "\r\n" separator. Instead, we use the system's native line * separator. */ if (defined('PHP_EOL')) { diff --git a/extlib/Mail/sendmail.php b/extlib/Mail/sendmail.php index cd248e61d..aea52081a 100644 --- a/extlib/Mail/sendmail.php +++ b/extlib/Mail/sendmail.php @@ -67,7 +67,7 @@ class Mail_sendmail extends Mail { /* * Because we need to pass message headers to the sendmail program on - * the commandline, we can't guarantee the use of the standard "\r\n" + * the commandline, we cannot guarantee the use of the standard "\r\n" * separator. Instead, we use the system's native line separator. */ if (defined('PHP_EOL')) { diff --git a/extlib/Net/LDAP2/Entry.php b/extlib/Net/LDAP2/Entry.php index 66de96678..5531bfa13 100644 --- a/extlib/Net/LDAP2/Entry.php +++ b/extlib/Net/LDAP2/Entry.php @@ -665,7 +665,7 @@ class Net_LDAP2_Entry extends PEAR * To force replace mode instead of add, you can set $force to true. * * @param array $attr Attributes to replace - * @param bool $force Force replacing mode in case we can't read the attr value but are allowed to replace it + * @param bool $force Force replacing mode in case we cannot read the attr value but are allowed to replace it * * @access public * @return true|Net_LDAP2_Error diff --git a/extlib/Net/LDAP2/Filter.php b/extlib/Net/LDAP2/Filter.php index 0723edab2..bd13d1ee4 100644 --- a/extlib/Net/LDAP2/Filter.php +++ b/extlib/Net/LDAP2/Filter.php @@ -439,7 +439,7 @@ class Net_LDAP2_Filter extends PEAR * * This method is only for compatibility to the perl interface. * However, the original method was called "print" but due to PHP language restrictions, - * we can't have a print() method. + * we cannot have a print() method. * * @param resource $FH (optional) A filehandle resource * diff --git a/extlib/System/Command.php b/extlib/System/Command.php index f5c3ec6b9..d2001a975 100644 --- a/extlib/System/Command.php +++ b/extlib/System/Command.php @@ -376,7 +376,7 @@ class System_Command { return $this->_initError; } - // if the command is empty or if the last element was a control operator, we can't continue + // if the command is empty or if the last element was a control operator, we cannot continue if (is_null($this->previousElement) || $this->commandStatus == -1 || in_array($this->previousElement, $this->controlOperators)) { return PEAR::raiseError(null, SYSTEM_COMMAND_INVALID_COMMAND, null, E_USER_WARNING, $this->systemCommand, 'System_Command_Error', true); } diff --git a/extlib/markdown.php b/extlib/markdown.php index 8179b568b..1bb1b6ce4 100644 --- a/extlib/markdown.php +++ b/extlib/markdown.php @@ -1348,7 +1348,7 @@ class Markdown_Parser { // { // list(, $div_open, , $div_content, $div_close) = $matches; // -// # We can't call Markdown(), because that resets the hash; +// # We cannot call Markdown(), because that resets the hash; // # that initialization code should be pulled into its own sub, though. // $div_content = $this->hashHTMLBlocks($div_content); // diff --git a/install.php b/install.php index e7f7cf318..78a4b8763 100644 --- a/install.php +++ b/install.php @@ -391,7 +391,7 @@ function showLibs() libraries instead, as they tend to provide security updates faster, and may offer improved performance.

On Debian based distributions, such as Ubuntu, use a package manager (such as "aptitude", "apt-get", and "synaptic") to install the package listed.

On RPM based distributions, such as Red Hat, Fedora, CentOS, Scientific Linux, Yellow Dog Linux and Oracle Enterprise Linux, use a package manager (such as "yum", "apt-rpm", and "up2date") to install the package listed.

-

On servers without a package manager (such as Windows), or if the library is not packaged for your distribution, you can use PHP's PEAR to install the library. Simply run "pear install <name>".

+

On servers without a package manager (such as Windows), or if the library is not packaged for your distribution, you can use PHP PEAR to install the library. Simply run "pear install <name>".

Absent Libraries

    @@ -570,7 +570,7 @@ STR; $res = writeConf($sitename, $server, $path, $fancy, $db); if (!$res) { - updateStatus("Can't write config file.", true); + updateStatus("Cannot write config file.", true); showForm(); return; } @@ -616,7 +616,7 @@ function Pgsql_Db_installer($host, $database, $username, $password) $res = runDbScript(INSTALLDIR.'/db/statusnet_pg.sql', $conn, 'pgsql'); if ($res === false) { - updateStatus("Can't run database script.", true); + updateStatus("Cannot run database script.", true); showForm(); return false; } @@ -627,7 +627,7 @@ function Pgsql_Db_installer($host, $database, $username, $password) updateStatus(sprintf("Adding %s data to database...", $name)); $res = runDbScript(INSTALLDIR.'/db/'.$scr.'.sql', $conn, 'pgsql'); if ($res === false) { - updateStatus(sprintf("Can't run %d script.", $name), true); + updateStatus(sprintf("Cannot run %d script.", $name), true); showForm(); return false; } @@ -652,21 +652,21 @@ function Mysql_Db_installer($host, $database, $username, $password) $conn = mysql_connect($host, $username, $password); if (!$conn) { - updateStatus("Can't connect to server '$host' as '$username'.", true); + updateStatus("Cannot connect to server '$host' as '$username'.", true); showForm(); return false; } updateStatus("Changing to database..."); $res = mysql_select_db($database, $conn); if (!$res) { - updateStatus("Can't change to database.", true); + updateStatus("Cannot change to database.", true); showForm(); return false; } updateStatus("Running database script..."); $res = runDbScript(INSTALLDIR.'/db/statusnet.sql', $conn); if ($res === false) { - updateStatus("Can't run database script.", true); + updateStatus("Cannot run database script.", true); showForm(); return false; } @@ -677,7 +677,7 @@ function Mysql_Db_installer($host, $database, $username, $password) updateStatus(sprintf("Adding %s data to database...", $name)); $res = runDbScript(INSTALLDIR.'/db/'.$scr.'.sql', $conn); if ($res === false) { - updateStatus(sprintf("Can't run %d script.", $name), true); + updateStatus(sprintf("Cannot run %d script.", $name), true); showForm(); return false; } diff --git a/lib/attachmentlist.php b/lib/attachmentlist.php index 51ceca857..60095dace 100644 --- a/lib/attachmentlist.php +++ b/lib/attachmentlist.php @@ -71,7 +71,7 @@ class AttachmentList extends Widget /** * show the list of notices * - * "Uses up" the stream by looping through it. So, probably can't + * "Uses up" the stream by looping through it. So, probably cannot * be called twice on the same list. * * @return int count of notices listed. diff --git a/lib/noticelist.php b/lib/noticelist.php index 8b3015cc3..385da37e9 100644 --- a/lib/noticelist.php +++ b/lib/noticelist.php @@ -75,7 +75,7 @@ class NoticeList extends Widget /** * show the list of notices * - * "Uses up" the stream by looping through it. So, probably can't + * "Uses up" the stream by looping through it. So, probably cannot * be called twice on the same list. * * @return int count of notices listed. diff --git a/lib/profilelist.php b/lib/profilelist.php index bbb722701..f3eb66658 100644 --- a/lib/profilelist.php +++ b/lib/profilelist.php @@ -269,7 +269,7 @@ class ProfileListItem extends Widget $usf = new UnsubscribeForm($this->out, $this->profile); $usf->show(); } else { - // Is it a local user? can't remote sub from a list + // Is it a local user? cannot remote sub from a list // XXX: make that possible! $other = User::staticGet('id', $this->profile->id); if (!empty($other)) { diff --git a/lib/serverexception.php b/lib/serverexception.php index 7dc9765ad..6b2d55a0b 100644 --- a/lib/serverexception.php +++ b/lib/serverexception.php @@ -34,7 +34,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { /** * Class for server exceptions * - * Subclass of PHP Exception for server errors. The user typically can't fix these. + * Subclass of PHP Exception for server errors. The user typically cannot fix these. * * @category Exception * @package StatusNet diff --git a/lib/settingsaction.php b/lib/settingsaction.php index c3669868d..4193ea521 100644 --- a/lib/settingsaction.php +++ b/lib/settingsaction.php @@ -72,7 +72,7 @@ class SettingsAction extends CurrentUserDesignAction $this->clientError(_('Not logged in.')); return; } else if (!common_is_real_login()) { - // Cookie theft means that automatic logins can't + // Cookie theft means that automatic logins cannot // change important settings or see private info, and // _all_ our settings are important common_set_returnto($this->selfUrl()); diff --git a/lib/util.php b/lib/util.php index a4865c46c..dde3fb48f 100644 --- a/lib/util.php +++ b/lib/util.php @@ -576,7 +576,7 @@ function common_linkify($url) { } elseif (is_string($longurl_data)) { $longurl = $longurl_data; } else { - throw new ServerException("Can't linkify url '$url'"); + throw new ServerException("Cannot linkify url '$url'"); } } $attrs = array('href' => $canon, 'title' => $longurl, 'rel' => 'external'); diff --git a/lib/xmppqueuehandler.php b/lib/xmppqueuehandler.php index f28fc9088..8acdcafe7 100644 --- a/lib/xmppqueuehandler.php +++ b/lib/xmppqueuehandler.php @@ -43,7 +43,7 @@ class XmppQueueHandler extends QueueHandler $this->conn = jabber_connect($this->_id.$this->transport()); if (empty($this->conn)) { - $this->log(LOG_ERR, "Couldn't connect to server."); + $this->log(LOG_ERR, "Could not connect to server."); return false; } diff --git a/locale/statusnet.po b/locale/statusnet.po index 4331b906e..3ea314f34 100644 --- a/locale/statusnet.po +++ b/locale/statusnet.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-11-08 11:53+0000\n" +"POT-Creation-Date: 2009-11-08 22:12+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -16,7310 +16,4442 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../actions/noticesearchrss.php:64 actions/noticesearchrss.php:68 -#: actions/noticesearchrss.php:88 actions/noticesearchrss.php:89 -#, php-format -msgid " Search Stream for \"%s\"" +#: actions/all.php:63 actions/public.php:97 actions/replies.php:92 +#: actions/showfavorites.php:137 actions/tag.php:51 +msgid "No such page" msgstr "" -#: ../actions/finishopenidlogin.php:82 ../actions/register.php:191 -#: actions/finishopenidlogin.php:88 actions/register.php:205 -#: actions/finishopenidlogin.php:110 actions/finishopenidlogin.php:109 -msgid "" -" except this private data: password, email address, IM address, phone number." +#: actions/all.php:74 actions/allrss.php:68 actions/avatarbynickname.php:75 +#: actions/favoritesrss.php:74 actions/foaf.php:40 actions/foaf.php:58 +#: actions/remotesubscribe.php:145 actions/replies.php:73 +#: actions/repliesrss.php:38 actions/showfavorites.php:105 +#: actions/userbyid.php:74 actions/usergroups.php:91 actions/userrss.php:38 +#: actions/xrds.php:71 lib/command.php:163 lib/command.php:311 +#: lib/command.php:364 lib/command.php:411 lib/command.php:466 +#: lib/galleryaction.php:59 lib/mailbox.php:82 lib/profileaction.php:77 +#: lib/subs.php:34 lib/subs.php:112 +msgid "No such user." msgstr "" -#: ../actions/showstream.php:400 ../lib/stream.php:109 -#: actions/showstream.php:418 lib/mailbox.php:164 lib/stream.php:76 -msgid " from " +#: actions/all.php:84 +#, php-format +msgid "%s and friends, page %d" msgstr "" -#: ../actions/twitapistatuses.php:478 actions/twitapistatuses.php:412 -#: actions/twitapistatuses.php:347 actions/twitapistatuses.php:363 +#: actions/all.php:86 actions/all.php:167 actions/allrss.php:115 +#: actions/apitimelinefriends.php:114 lib/personalgroupnav.php:100 #, php-format -msgid "%1$s / Updates replying to %2$s" +msgid "%s and friends" msgstr "" -#: ../actions/invite.php:168 actions/invite.php:176 actions/invite.php:211 -#: actions/invite.php:218 actions/invite.php:220 actions/invite.php:226 +#: actions/all.php:99 #, php-format -msgid "%1$s has invited you to join them on %2$s" +msgid "Feed for friends of %s (RSS 1.0)" msgstr "" -#: ../actions/invite.php:170 actions/invite.php:220 actions/invite.php:222 -#: actions/invite.php:228 +#: actions/all.php:107 #, php-format -msgid "" -"%1$s has invited you to join them on %2$s (%3$s).\n" -"\n" -"%2$s is a micro-blogging service that lets you keep up-to-date with people " -"you know and people who interest you.\n" -"\n" -"You can also share news about yourself, your thoughts, or your life online " -"with people who know about you. It's also great for meeting new people who " -"share your interests.\n" -"\n" -"%1$s said:\n" -"\n" -"%4$s\n" -"\n" -"You can see %1$s's profile page on %2$s here:\n" -"\n" -"%5$s\n" -"\n" -"If you'd like to try the service, click on the link below to accept the " -"invitation.\n" -"\n" -"%6$s\n" -"\n" -"If not, you can ignore this message. Thanks for your patience and your " -"time.\n" -"\n" -"Sincerely, %2$s\n" +msgid "Feed for friends of %s (RSS 2.0)" msgstr "" -#: ../lib/mail.php:124 lib/mail.php:124 lib/mail.php:126 lib/mail.php:241 -#: lib/mail.php:236 lib/mail.php:235 +#: actions/all.php:115 #, php-format -msgid "%1$s is now listening to your notices on %2$s." +msgid "Feed for friends of %s (Atom)" msgstr "" -#: ../lib/mail.php:126 +#: actions/all.php:127 #, php-format msgid "" -"%1$s is now listening to your notices on %2$s.\n" -"\n" -"\t%3$s\n" -"\n" -"Faithfully yours,\n" -"%4$s.\n" +"This is the timeline for %s and friends but no one has posted anything yet." msgstr "" -#: ../actions/twitapistatuses.php:482 actions/twitapistatuses.php:415 -#: actions/twitapistatuses.php:350 actions/twitapistatuses.php:367 -#: actions/twitapistatuses.php:328 actions/apitimelinementions.php:126 +#: actions/all.php:132 #, php-format -msgid "%1$s updates that reply to updates from %2$s / %3$s." +msgid "" +"Try subscribing to more users, [join a group](%%action.groups%%) or post " +"something yourself." msgstr "" -#: ../actions/shownotice.php:45 actions/shownotice.php:45 -#: actions/shownotice.php:161 actions/shownotice.php:174 actions/oembed.php:86 -#: actions/shownotice.php:180 +#: actions/all.php:134 #, php-format -msgid "%1$s's status on %2$s" +msgid "" +"You can try to [nudge %s](../%s) from his profile or [post something to his " +"or her attention](%%%%action.newnotice%%%%?status_textarea=%s)." msgstr "" -#: ../actions/invite.php:84 ../actions/invite.php:92 actions/invite.php:91 -#: actions/invite.php:99 actions/invite.php:123 actions/invite.php:131 -#: actions/invite.php:125 actions/invite.php:133 actions/invite.php:139 +#: actions/all.php:137 actions/replies.php:209 actions/showstream.php:202 #, php-format -msgid "%s (%s)" +msgid "" +"Why not [register an account](%%%%action.register%%%%) and then nudge %s or " +"post a notice to his or her attention." msgstr "" -#: ../actions/publicrss.php:62 actions/publicrss.php:48 -#: actions/publicrss.php:90 actions/publicrss.php:89 -#, php-format -msgid "%s Public Stream" +#: actions/all.php:165 +msgid "You and friends" msgstr "" -#: ../actions/all.php:47 ../actions/allrss.php:60 -#: ../actions/twitapistatuses.php:238 ../lib/stream.php:51 actions/all.php:47 -#: actions/allrss.php:60 actions/twitapistatuses.php:155 lib/personal.php:51 -#: actions/all.php:65 actions/allrss.php:103 actions/facebookhome.php:164 -#: actions/twitapistatuses.php:126 lib/personalgroupnav.php:99 -#: actions/all.php:68 actions/all.php:114 actions/allrss.php:106 -#: actions/facebookhome.php:163 actions/twitapistatuses.php:130 -#: actions/all.php:50 actions/all.php:127 actions/allrss.php:114 -#: actions/facebookhome.php:158 actions/twitapistatuses.php:89 -#: lib/personalgroupnav.php:100 actions/all.php:86 actions/all.php:167 -#: actions/allrss.php:115 actions/apitimelinefriends.php:114 +#: actions/allrss.php:119 actions/apitimelinefriends.php:121 #, php-format -msgid "%s and friends" +msgid "Updates from %1$s and friends on %2$s!" msgstr "" -#: ../actions/twitapistatuses.php:49 actions/twitapistatuses.php:49 -#: actions/twitapistatuses.php:33 actions/twitapistatuses.php:32 -#: actions/twitapistatuses.php:37 actions/apitimelinepublic.php:106 -#: actions/publicrss.php:103 -#, php-format -msgid "%s public timeline" +#: actions/apiaccountratelimitstatus.php:70 actions/apidirectmessage.php:156 +#: actions/apifavoritecreate.php:99 actions/apifavoritedestroy.php:100 +#: actions/apifriendshipscreate.php:100 actions/apifriendshipsdestroy.php:100 +#: actions/apifriendshipsshow.php:129 actions/apigroupcreate.php:184 +#: actions/apigroupismember.php:114 actions/apigroupjoin.php:155 +#: actions/apigroupleave.php:141 actions/apigrouplistall.php:120 +#: actions/apigrouplist.php:132 actions/apigroupmembership.php:101 +#: actions/apigroupshow.php:105 actions/apihelptest.php:88 +#: actions/apistatusesdestroy.php:102 actions/apistatusesshow.php:108 +#: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 +#: actions/apisubscriptions.php:111 actions/apitimelinefavorites.php:144 +#: actions/apitimelinefriends.php:154 actions/apitimelinegroup.php:141 +#: actions/apitimelinementions.php:149 actions/apitimelinepublic.php:130 +#: actions/apitimelinetag.php:139 actions/apitimelineuser.php:163 +#: actions/apiusershow.php:101 +msgid "API method not found!" msgstr "" -#: ../lib/mail.php:206 lib/mail.php:212 lib/mail.php:411 lib/mail.php:412 -#, php-format -msgid "%s status" +#: actions/apiaccountupdateprofileimage.php:84 actions/apiblockcreate.php:89 +#: actions/apiblockdestroy.php:88 actions/apidirectmessagenew.php:117 +#: actions/apifavoritecreate.php:90 actions/apifavoritedestroy.php:91 +#: actions/apifriendshipscreate.php:91 actions/apifriendshipsdestroy.php:91 +#: actions/apigroupcreate.php:104 actions/apigroupjoin.php:91 +#: actions/apigroupleave.php:91 actions/apistatusesupdate.php:109 +msgid "This method requires a POST." msgstr "" -#: ../actions/twitapistatuses.php:338 actions/twitapistatuses.php:265 -#: actions/twitapistatuses.php:199 actions/twitapistatuses.php:209 -#: actions/twitapigroups.php:69 actions/twitapistatuses.php:154 -#: actions/apitimelinegroup.php:102 actions/apitimelineuser.php:117 -#: actions/grouprss.php:131 actions/userrss.php:90 +#: actions/apiaccountupdateprofileimage.php:97 +#: actions/apistatusesupdate.php:122 actions/avatarsettings.php:254 +#: actions/newnotice.php:94 lib/designsettings.php:283 #, php-format -msgid "%s timeline" +msgid "" +"The server was unable to handle that much POST data (%s bytes) due to its " +"current configuration." msgstr "" -#: ../actions/twitapistatuses.php:52 actions/twitapistatuses.php:52 -#: actions/twitapistatuses.php:36 actions/twitapistatuses.php:38 -#: actions/twitapistatuses.php:41 actions/apitimelinepublic.php:110 -#: actions/publicrss.php:105 -#, php-format -msgid "%s updates from everyone!" +#: actions/apiaccountupdateprofileimage.php:105 actions/apiblockcreate.php:97 +#: actions/apiblockdestroy.php:96 actions/apidirectmessagenew.php:75 +#: actions/apidirectmessage.php:77 actions/apigroupcreate.php:112 +#: actions/apigroupismember.php:90 actions/apigroupjoin.php:99 +#: actions/apigroupleave.php:99 actions/apigrouplist.php:90 +#: actions/apistatusesupdate.php:139 actions/apisubscriptions.php:87 +#: actions/apitimelinefavorites.php:70 actions/apitimelinefriends.php:79 +#: actions/apitimelinementions.php:79 actions/apitimelineuser.php:81 +msgid "No such user!" msgstr "" -#: ../actions/register.php:213 actions/register.php:497 -#: actions/register.php:545 actions/register.php:555 actions/register.php:561 -msgid "" -"(You should receive a message by email momentarily, with instructions on how " -"to confirm your email address.)" +#: actions/apiaccountupdateprofileimage.php:130 actions/apiusershow.php:108 +#: actions/avatarbynickname.php:80 actions/foaf.php:65 actions/replies.php:80 +#: actions/usergroups.php:98 lib/galleryaction.php:66 lib/profileaction.php:84 +msgid "User has no profile." msgstr "" -#: ../lib/util.php:257 lib/util.php:273 lib/action.php:605 lib/action.php:702 -#: lib/action.php:752 lib/action.php:767 -#, php-format -msgid "" -"**%%site.name%%** is a microblogging service brought to you by [%%site." -"broughtby%%](%%site.broughtbyurl%%). " +#: actions/apiblockcreate.php:108 +msgid "Block user failed." msgstr "" -#: ../lib/util.php:259 lib/util.php:275 lib/action.php:607 lib/action.php:704 -#: lib/action.php:754 lib/action.php:769 -#, php-format -msgid "**%%site.name%%** is a microblogging service. " +#: actions/apiblockdestroy.php:107 +msgid "Unblock user failed." msgstr "" -#: ../actions/finishopenidlogin.php:73 ../actions/profilesettings.php:43 -#: actions/finishopenidlogin.php:79 actions/profilesettings.php:76 -#: actions/finishopenidlogin.php:101 actions/profilesettings.php:100 -#: lib/groupeditform.php:139 actions/finishopenidlogin.php:100 -#: lib/groupeditform.php:154 actions/profilesettings.php:108 -msgid "1-64 lowercase letters or numbers, no punctuation or spaces" +#: actions/apidirectmessagenew.php:126 +msgid "No message text!" msgstr "" -#: ../actions/register.php:152 actions/register.php:166 -#: actions/register.php:368 actions/register.php:414 actions/register.php:418 -#: actions/register.php:424 -msgid "1-64 lowercase letters or numbers, no punctuation or spaces. Required." +#: actions/apidirectmessagenew.php:135 actions/newmessage.php:150 +#, php-format +msgid "That's too long. Max message size is %d chars." msgstr "" -#: ../actions/password.php:42 actions/profilesettings.php:181 -#: actions/passwordsettings.php:102 actions/passwordsettings.php:108 -msgid "6 or more characters" +#: actions/apidirectmessagenew.php:146 +msgid "Recipient user not found." msgstr "" -#: ../actions/recoverpassword.php:180 actions/recoverpassword.php:186 -#: actions/recoverpassword.php:220 actions/recoverpassword.php:233 -#: actions/recoverpassword.php:236 -msgid "6 or more characters, and don't forget it!" +#: actions/apidirectmessagenew.php:150 +msgid "Can't send direct messages to users who aren't your friend." msgstr "" -#: ../actions/register.php:154 actions/register.php:168 -#: actions/register.php:373 actions/register.php:419 actions/register.php:423 -#: actions/register.php:429 -msgid "6 or more characters. Required." +#: actions/apidirectmessage.php:89 +#, php-format +msgid "Direct messages from %s" msgstr "" -#: ../actions/imsettings.php:197 actions/imsettings.php:205 -#: actions/imsettings.php:321 actions/imsettings.php:327 +#: actions/apidirectmessage.php:93 #, php-format -msgid "" -"A confirmation code was sent to the IM address you added. You must approve %" -"s for sending messages to you." +msgid "All the direct messages sent from %s" msgstr "" -#: ../actions/emailsettings.php:213 actions/emailsettings.php:231 -#: actions/emailsettings.php:350 actions/emailsettings.php:358 -msgid "" -"A confirmation code was sent to the email address you added. Check your " -"inbox (and spam box!) for the code and instructions on how to use it." +#: actions/apidirectmessage.php:101 +#, php-format +msgid "Direct messages to %s" msgstr "" -#: ../actions/smssettings.php:216 actions/smssettings.php:224 -msgid "" -"A confirmation code was sent to the phone number you added. Check your inbox " -"(and spam box!) for the code and instructions on how to use it." -msgstr "" - -#: ../actions/twitapiaccount.php:49 ../actions/twitapihelp.php:45 -#: ../actions/twitapistatuses.php:88 ../actions/twitapistatuses.php:259 -#: ../actions/twitapistatuses.php:370 ../actions/twitapistatuses.php:532 -#: ../actions/twitapiusers.php:122 actions/twitapiaccount.php:49 -#: actions/twitapidirect_messages.php:104 actions/twitapifavorites.php:111 -#: actions/twitapifavorites.php:120 actions/twitapifriendships.php:156 -#: actions/twitapihelp.php:46 actions/twitapistatuses.php:93 -#: actions/twitapistatuses.php:176 actions/twitapistatuses.php:288 -#: actions/twitapistatuses.php:298 actions/twitapistatuses.php:454 -#: actions/twitapistatuses.php:463 actions/twitapistatuses.php:504 -#: actions/twitapiusers.php:55 actions/twitapiaccount.php:37 -#: actions/twitapidirect_messages.php:111 actions/twitapifavorites.php:85 -#: actions/twitapifavorites.php:102 actions/twitapifriendships.php:121 -#: actions/twitapihelp.php:44 actions/twitapistatusnet.php:82 -#: actions/twitapistatusnet.php:151 actions/twitapistatuses.php:79 -#: actions/twitapistatuses.php:147 actions/twitapistatuses.php:228 -#: actions/twitapistatuses.php:239 actions/twitapistatuses.php:392 -#: actions/twitapistatuses.php:402 actions/twitapistatuses.php:429 -#: actions/twitapiusers.php:32 actions/twitapidirect_messages.php:120 -#: actions/twitapifavorites.php:91 actions/twitapifavorites.php:108 -#: actions/twitapistatuses.php:82 actions/twitapistatuses.php:159 -#: actions/twitapistatuses.php:246 actions/twitapistatuses.php:257 -#: actions/twitapistatuses.php:416 actions/twitapistatuses.php:426 -#: actions/twitapistatuses.php:453 actions/twitapidirect_messages.php:113 -#: actions/twitapifavorites.php:92 actions/twitapifavorites.php:109 -#: actions/twitapifavorites.php:160 actions/twitapifriendships.php:128 -#: actions/twitapifriendships.php:168 actions/twitapigroups.php:110 -#: actions/twitapistatuses.php:68 actions/twitapistatuses.php:134 -#: actions/twitapistatuses.php:201 actions/twitapistatuses.php:211 -#: actions/twitapistatuses.php:357 actions/twitapistatuses.php:372 -#: actions/twitapistatuses.php:409 actions/twitapitags.php:110 -#: actions/twitapiusers.php:34 actions/apiaccountratelimitstatus.php:70 -#: actions/apidirectmessage.php:156 actions/apifavoritecreate.php:99 -#: actions/apifavoritedestroy.php:100 actions/apifriendshipscreate.php:100 -#: actions/apifriendshipsdestroy.php:100 actions/apifriendshipsshow.php:129 -#: actions/apigroupcreate.php:184 actions/apigroupismember.php:114 -#: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 -#: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:101 actions/apigroupshow.php:105 -#: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 -#: actions/apistatusesshow.php:108 actions/apistatusnetconfig.php:133 -#: actions/apistatusnetversion.php:93 actions/apisubscriptions.php:111 -#: actions/apitimelinefavorites.php:144 actions/apitimelinefriends.php:154 -#: actions/apitimelinegroup.php:141 actions/apitimelinementions.php:149 -#: actions/apitimelinepublic.php:130 actions/apitimelinetag.php:139 -#: actions/apitimelineuser.php:163 actions/apiusershow.php:101 -msgid "API method not found!" +#: actions/apidirectmessage.php:105 +#, php-format +msgid "All the direct messages sent to %s" msgstr "" -#: ../actions/twitapiaccount.php:57 ../actions/twitapiaccount.php:113 -#: ../actions/twitapiaccount.php:119 ../actions/twitapiblocks.php:28 -#: ../actions/twitapiblocks.php:34 ../actions/twitapidirect_messages.php:43 -#: ../actions/twitapidirect_messages.php:49 -#: ../actions/twitapidirect_messages.php:56 -#: ../actions/twitapidirect_messages.php:62 ../actions/twitapifavorites.php:41 -#: ../actions/twitapifavorites.php:47 ../actions/twitapifavorites.php:53 -#: ../actions/twitapihelp.php:52 ../actions/twitapinotifications.php:29 -#: ../actions/twitapinotifications.php:35 ../actions/twitapistatuses.php:768 -#: actions/twitapiaccount.php:56 actions/twitapiaccount.php:109 -#: actions/twitapiaccount.php:114 actions/twitapiblocks.php:28 -#: actions/twitapiblocks.php:33 actions/twitapidirect_messages.php:170 -#: actions/twitapifavorites.php:168 actions/twitapihelp.php:53 -#: actions/twitapinotifications.php:29 actions/twitapinotifications.php:34 -#: actions/twitapistatuses.php:690 actions/twitapiaccount.php:45 -#: actions/twitapiaccount.php:97 actions/twitapiaccount.php:103 -#: actions/twitapidirect_messages.php:184 actions/twitapifavorites.php:143 -#: actions/twitapihelp.php:52 actions/twitapistatusnet.php:172 -#: actions/twitapinotifications.php:31 actions/twitapinotifications.php:37 -#: actions/twitapistatuses.php:562 actions/twitapiaccount.php:46 -#: actions/twitapiaccount.php:98 actions/twitapiaccount.php:104 -#: actions/twitapidirect_messages.php:193 actions/twitapifavorites.php:149 -#: actions/twitapistatuses.php:625 actions/twitapitrends.php:87 -#: actions/twitapiaccount.php:48 actions/twitapidirect_messages.php:189 -#: actions/twitapihelp.php:54 actions/twitapistatuses.php:582 -msgid "API method under construction." +#: actions/apifavoritecreate.php:108 actions/apifavoritedestroy.php:109 +#: actions/apistatusesdestroy.php:113 +msgid "No status found with that ID." msgstr "" -#: ../lib/util.php:324 lib/util.php:340 lib/action.php:568 lib/action.php:661 -#: lib/action.php:706 lib/action.php:721 -msgid "About" +#: actions/apifavoritecreate.php:119 +msgid "This status is already a favorite!" msgstr "" -#: ../actions/userauthorization.php:119 actions/userauthorization.php:126 -#: actions/userauthorization.php:143 actions/userauthorization.php:178 -#: actions/userauthorization.php:209 -msgid "Accept" +#: actions/apifavoritecreate.php:130 actions/favor.php:84 lib/command.php:176 +msgid "Could not create favorite." msgstr "" -#: ../actions/emailsettings.php:62 ../actions/imsettings.php:63 -#: ../actions/openidsettings.php:57 ../actions/smssettings.php:71 -#: actions/emailsettings.php:63 actions/imsettings.php:64 -#: actions/openidsettings.php:58 actions/smssettings.php:71 -#: actions/twittersettings.php:85 actions/emailsettings.php:120 -#: actions/imsettings.php:127 actions/openidsettings.php:111 -#: actions/smssettings.php:133 actions/twittersettings.php:163 -#: actions/twittersettings.php:166 actions/twittersettings.php:182 -#: actions/emailsettings.php:126 actions/imsettings.php:133 -#: actions/smssettings.php:145 -msgid "Add" +#: actions/apifavoritedestroy.php:122 +msgid "That status is not a favorite!" msgstr "" -#: ../actions/openidsettings.php:43 actions/openidsettings.php:44 -#: actions/openidsettings.php:93 -msgid "Add OpenID" +#: actions/apifavoritedestroy.php:134 actions/disfavor.php:87 +msgid "Could not delete favorite." msgstr "" -#: ../lib/settingsaction.php:97 lib/settingsaction.php:91 -#: lib/accountsettingsaction.php:117 -msgid "Add or remove OpenIDs" +#: actions/apifriendshipscreate.php:109 +msgid "Could not follow user: User not found." msgstr "" -#: ../actions/emailsettings.php:38 ../actions/imsettings.php:39 -#: ../actions/smssettings.php:39 actions/emailsettings.php:39 -#: actions/imsettings.php:40 actions/smssettings.php:39 -#: actions/emailsettings.php:94 actions/imsettings.php:94 -#: actions/smssettings.php:92 actions/emailsettings.php:100 -#: actions/imsettings.php:100 actions/smssettings.php:104 -msgid "Address" +#: actions/apifriendshipscreate.php:118 +#, php-format +msgid "Could not follow user: %s is already on your list." msgstr "" -#: ../actions/invite.php:131 actions/invite.php:139 actions/invite.php:176 -#: actions/invite.php:181 actions/invite.php:183 actions/invite.php:189 -msgid "Addresses of friends to invite (one per line)" +#: actions/apifriendshipsdestroy.php:109 +msgid "Could not unfollow user: User not found." msgstr "" -#: ../actions/showstream.php:273 actions/showstream.php:288 -#: actions/showstream.php:422 lib/profileaction.php:126 -msgid "All subscriptions" +#: actions/apifriendshipsdestroy.php:120 +msgid "You cannot unfollow yourself!" msgstr "" -#: ../actions/publicrss.php:64 actions/publicrss.php:50 -#: actions/publicrss.php:92 actions/publicrss.php:91 -#, php-format -msgid "All updates for %s" +#: actions/apifriendshipsexists.php:94 +msgid "Two user ids or screen_names must be supplied." msgstr "" -#: ../actions/noticesearchrss.php:66 actions/noticesearchrss.php:70 -#: actions/noticesearchrss.php:90 actions/noticesearchrss.php:91 -#, php-format -msgid "All updates matching search term \"%s\"" +#: actions/apifriendshipsshow.php:135 +msgid "Could not determine source user." msgstr "" -#: ../actions/finishopenidlogin.php:29 ../actions/login.php:31 -#: ../actions/openidlogin.php:29 ../actions/register.php:30 -#: actions/finishopenidlogin.php:29 actions/login.php:31 -#: actions/openidlogin.php:29 actions/register.php:30 -#: actions/finishopenidlogin.php:34 actions/login.php:77 -#: actions/openidlogin.php:30 actions/register.php:92 actions/register.php:131 -#: actions/login.php:79 actions/register.php:137 -msgid "Already logged in." +#: actions/apifriendshipsshow.php:143 +msgid "Could not find target user." msgstr "" -#: ../lib/subs.php:42 lib/subs.php:42 lib/subs.php:49 lib/subs.php:48 -msgid "Already subscribed!." +#: actions/apigroupcreate.php:136 actions/newgroup.php:204 +msgid "Could not create group." msgstr "" -#: ../actions/deletenotice.php:54 actions/deletenotice.php:55 -#: actions/deletenotice.php:113 actions/deletenotice.php:114 -#: actions/deletenotice.php:144 -msgid "Are you sure you want to delete this notice?" +#: actions/apigroupcreate.php:147 actions/editgroup.php:259 +#: actions/newgroup.php:210 +msgid "Could not create aliases." msgstr "" -#: ../actions/userauthorization.php:77 actions/userauthorization.php:83 -#: actions/userauthorization.php:81 actions/userauthorization.php:76 -#: actions/userauthorization.php:105 -msgid "Authorize subscription" +#: actions/apigroupcreate.php:166 actions/newgroup.php:224 +msgid "Could not set group membership." msgstr "" -#: ../actions/login.php:104 ../actions/register.php:178 -#: actions/register.php:192 actions/login.php:218 actions/openidlogin.php:117 -#: actions/register.php:416 actions/register.php:463 actions/login.php:226 -#: actions/register.php:473 actions/login.php:253 actions/register.php:479 -msgid "Automatically login in the future; not for shared computers!" +#: actions/apigroupcreate.php:212 actions/editgroup.php:182 +#: actions/newgroup.php:126 actions/profilesettings.php:208 +#: actions/register.php:205 +msgid "Nickname must have only lowercase letters and numbers and no spaces." msgstr "" -#: ../actions/profilesettings.php:65 actions/profilesettings.php:98 -#: actions/profilesettings.php:144 actions/profilesettings.php:145 -#: actions/profilesettings.php:160 -msgid "" -"Automatically subscribe to whoever subscribes to me (best for non-humans)" +#: actions/apigroupcreate.php:221 actions/editgroup.php:186 +#: actions/newgroup.php:130 actions/profilesettings.php:231 +#: actions/register.php:208 +msgid "Nickname already in use. Try another one." msgstr "" -#: ../actions/avatar.php:32 ../lib/settingsaction.php:90 -#: actions/profilesettings.php:34 actions/avatarsettings.php:65 -#: actions/showgroup.php:209 lib/accountsettingsaction.php:107 -#: actions/avatarsettings.php:67 actions/showgroup.php:211 -#: actions/showgroup.php:216 actions/showgroup.php:221 -#: lib/accountsettingsaction.php:111 -msgid "Avatar" +#: actions/apigroupcreate.php:228 actions/editgroup.php:189 +#: actions/newgroup.php:133 actions/profilesettings.php:211 +#: actions/register.php:210 +msgid "Not a valid nickname." msgstr "" -#: ../actions/avatar.php:113 actions/profilesettings.php:350 -#: actions/avatarsettings.php:395 actions/avatarsettings.php:346 -#: actions/avatarsettings.php:360 -msgid "Avatar updated." +#: actions/apigroupcreate.php:244 actions/editgroup.php:195 +#: actions/newgroup.php:139 actions/profilesettings.php:215 +#: actions/register.php:217 +msgid "Homepage is not a valid URL." msgstr "" -#: ../actions/imsettings.php:55 actions/imsettings.php:56 -#: actions/imsettings.php:108 actions/imsettings.php:114 -#, php-format -msgid "" -"Awaiting confirmation on this address. Check your Jabber/GTalk account for a " -"message with further instructions. (Did you add %s to your buddy list?)" +#: actions/apigroupcreate.php:253 actions/editgroup.php:198 +#: actions/newgroup.php:142 actions/profilesettings.php:218 +#: actions/register.php:220 +msgid "Full name is too long (max 255 chars)." msgstr "" -#: ../actions/emailsettings.php:54 actions/emailsettings.php:55 -#: actions/emailsettings.php:107 actions/emailsettings.php:113 -msgid "" -"Awaiting confirmation on this address. Check your inbox (and spam box!) for " -"a message with further instructions." +#: actions/apigroupcreate.php:261 +#, php-format +msgid "Description is too long (max %d chars)." msgstr "" -#: ../actions/smssettings.php:58 actions/smssettings.php:58 -#: actions/smssettings.php:111 actions/smssettings.php:123 -msgid "Awaiting confirmation on this phone number." +#: actions/apigroupcreate.php:272 actions/editgroup.php:204 +#: actions/newgroup.php:148 actions/profilesettings.php:225 +#: actions/register.php:227 +msgid "Location is too long (max 255 chars)." msgstr "" -#: ../lib/util.php:1318 lib/util.php:1452 -msgid "Before »" +#: actions/apigroupcreate.php:291 actions/editgroup.php:215 +#: actions/newgroup.php:159 +#, php-format +msgid "Too many aliases! Maximum %d." msgstr "" -#: ../actions/profilesettings.php:49 ../actions/register.php:170 -#: actions/profilesettings.php:82 actions/register.php:184 -#: actions/profilesettings.php:112 actions/register.php:402 -#: actions/register.php:448 actions/profilesettings.php:127 -#: actions/register.php:459 actions/register.php:465 -msgid "Bio" +#: actions/apigroupcreate.php:312 actions/editgroup.php:224 +#: actions/newgroup.php:168 +#, php-format +msgid "Invalid alias: \"%s\"" msgstr "" -#: ../actions/profilesettings.php:101 ../actions/register.php:82 -#: ../actions/updateprofile.php:103 actions/profilesettings.php:216 -#: actions/register.php:89 actions/updateprofile.php:104 -#: actions/profilesettings.php:205 actions/register.php:174 -#: actions/updateprofile.php:107 actions/updateprofile.php:109 -#: actions/profilesettings.php:206 actions/register.php:211 -msgid "Bio is too long (max 140 chars)." +#: actions/apigroupcreate.php:321 actions/editgroup.php:228 +#: actions/newgroup.php:172 +#, php-format +msgid "Alias \"%s\" already in use. Try another one." msgstr "" -#: ../lib/deleteaction.php:41 lib/deleteaction.php:41 lib/deleteaction.php:69 -#: actions/deletenotice.php:71 -msgid "Can't delete this notice." +#: actions/apigroupcreate.php:334 actions/editgroup.php:234 +#: actions/newgroup.php:178 +msgid "Alias can't be the same as nickname." msgstr "" -#: ../actions/updateprofile.php:119 actions/updateprofile.php:120 -#: actions/updateprofile.php:123 actions/updateprofile.php:125 -#, php-format -msgid "Can't read avatar URL '%s'" +#: actions/apigroupjoin.php:110 +msgid "You are already a member of that group." msgstr "" -#: ../actions/password.php:85 ../actions/recoverpassword.php:300 -#: actions/profilesettings.php:404 actions/recoverpassword.php:313 -#: actions/passwordsettings.php:169 actions/recoverpassword.php:347 -#: actions/passwordsettings.php:174 actions/recoverpassword.php:365 -#: actions/passwordsettings.php:180 actions/recoverpassword.php:368 -#: actions/passwordsettings.php:185 -msgid "Can't save new password." +#: actions/apigroupjoin.php:119 actions/joingroup.php:95 lib/command.php:221 +msgid "You have been blocked from that group by the admin." msgstr "" -#: ../actions/emailsettings.php:57 ../actions/imsettings.php:58 -#: ../actions/smssettings.php:62 actions/emailsettings.php:58 -#: actions/imsettings.php:59 actions/smssettings.php:62 -#: actions/emailsettings.php:111 actions/imsettings.php:114 -#: actions/smssettings.php:114 actions/emailsettings.php:117 -#: actions/imsettings.php:120 actions/smssettings.php:126 -msgid "Cancel" +#: actions/apigroupjoin.php:138 +#, php-format +msgid "Could not join user %s to group %s." msgstr "" -#: ../lib/openid.php:121 lib/openid.php:121 lib/openid.php:130 -#: lib/openid.php:133 -msgid "Cannot instantiate OpenID consumer object." +#: actions/apigroupleave.php:114 +msgid "You are not a member of this group." msgstr "" -#: ../actions/imsettings.php:163 actions/imsettings.php:171 -#: actions/imsettings.php:286 actions/imsettings.php:292 -msgid "Cannot normalize that Jabber ID" +#: actions/apigroupleave.php:124 +#, php-format +msgid "Could not remove user %s to group %s." msgstr "" -#: ../actions/emailsettings.php:181 actions/emailsettings.php:199 -#: actions/emailsettings.php:311 actions/emailsettings.php:318 -#: actions/emailsettings.php:326 -msgid "Cannot normalize that email address" +#: actions/apigrouplistall.php:90 actions/usergroups.php:62 +#, php-format +msgid "%s groups" msgstr "" -#: ../actions/password.php:45 actions/profilesettings.php:184 -#: actions/passwordsettings.php:110 actions/passwordsettings.php:116 -msgid "Change" +#: actions/apigrouplistall.php:94 +#, php-format +msgid "groups on %s" msgstr "" -#: ../lib/settingsaction.php:88 lib/settingsaction.php:88 -#: lib/accountsettingsaction.php:114 lib/accountsettingsaction.php:118 -msgid "Change email handling" +#: actions/apigrouplist.php:95 +#, php-format +msgid "%s's groups" msgstr "" -#: ../actions/password.php:32 actions/profilesettings.php:36 -#: actions/passwordsettings.php:58 -msgid "Change password" +#: actions/apigrouplist.php:103 +#, php-format +msgid "Groups %s is a member of on %s." msgstr "" -#: ../lib/settingsaction.php:94 lib/accountsettingsaction.php:111 -#: lib/accountsettingsaction.php:115 -msgid "Change your password" -msgstr "" - -#: ../lib/settingsaction.php:85 lib/settingsaction.php:85 -#: lib/accountsettingsaction.php:105 lib/accountsettingsaction.php:109 -msgid "Change your profile settings" +#: actions/apistatusesdestroy.php:107 +msgid "This method requires a POST or DELETE." msgstr "" -#: ../actions/password.php:43 ../actions/recoverpassword.php:181 -#: ../actions/register.php:155 ../actions/smssettings.php:65 -#: actions/profilesettings.php:182 actions/recoverpassword.php:187 -#: actions/register.php:169 actions/smssettings.php:65 -#: actions/passwordsettings.php:105 actions/recoverpassword.php:221 -#: actions/register.php:376 actions/smssettings.php:122 -#: actions/recoverpassword.php:236 actions/register.php:422 -#: actions/passwordsettings.php:111 actions/recoverpassword.php:239 -#: actions/register.php:426 actions/smssettings.php:134 -#: actions/register.php:432 -msgid "Confirm" +#: actions/apistatusesdestroy.php:130 +msgid "You may not delete another user's status." msgstr "" -#: ../actions/confirmaddress.php:90 actions/confirmaddress.php:90 -#: actions/confirmaddress.php:144 -msgid "Confirm Address" +#: actions/apistatusesshow.php:138 +msgid "Status deleted." msgstr "" -#: ../actions/emailsettings.php:238 ../actions/imsettings.php:222 -#: ../actions/smssettings.php:245 actions/emailsettings.php:256 -#: actions/imsettings.php:230 actions/smssettings.php:253 -#: actions/emailsettings.php:379 actions/imsettings.php:361 -#: actions/smssettings.php:374 actions/emailsettings.php:386 -#: actions/emailsettings.php:394 actions/imsettings.php:367 -#: actions/smssettings.php:386 -msgid "Confirmation cancelled." +#: actions/apistatusesshow.php:144 +msgid "No status with that ID found." msgstr "" -#: ../actions/smssettings.php:63 actions/smssettings.php:63 -#: actions/smssettings.php:118 actions/smssettings.php:130 -msgid "Confirmation code" +#: actions/apistatusesupdate.php:152 actions/newnotice.php:155 +#: scripts/maildaemon.php:71 +#, php-format +msgid "That's too long. Max notice size is %d chars." msgstr "" -#: ../actions/confirmaddress.php:38 actions/confirmaddress.php:38 -#: actions/confirmaddress.php:80 -msgid "Confirmation code not found." +#: actions/apistatusesupdate.php:193 +msgid "Not found" msgstr "" -#: ../actions/register.php:202 actions/register.php:473 -#: actions/register.php:521 actions/register.php:531 actions/register.php:537 +#: actions/apistatusesupdate.php:216 actions/newnotice.php:178 #, php-format -msgid "" -"Congratulations, %s! And welcome to %%%%site.name%%%%. From here, you may " -"want to...\n" -"\n" -"* Go to [your profile](%s) and post your first message.\n" -"* Add a [Jabber/GTalk address](%%%%action.imsettings%%%%) so you can send " -"notices through instant messages.\n" -"* [Search for people](%%%%action.peoplesearch%%%%) that you may know or that " -"share your interests. \n" -"* Update your [profile settings](%%%%action.profilesettings%%%%) to tell " -"others more about you. \n" -"* Read over the [online docs](%%%%doc.help%%%%) for features you may have " -"missed. \n" -"\n" -"Thanks for signing up and we hope you enjoy using this service." -msgstr "" - -#: ../actions/finishopenidlogin.php:91 actions/finishopenidlogin.php:97 -#: actions/finishopenidlogin.php:119 lib/action.php:330 lib/action.php:403 -#: lib/action.php:406 actions/finishopenidlogin.php:118 lib/action.php:422 -#: lib/action.php:425 lib/action.php:435 -msgid "Connect" +msgid "Max notice size is %d chars, including attachment URL." msgstr "" -#: ../actions/finishopenidlogin.php:86 actions/finishopenidlogin.php:92 -#: actions/finishopenidlogin.php:114 actions/finishopenidlogin.php:113 -msgid "Connect existing account" +#: actions/apisubscriptions.php:231 actions/apisubscriptions.php:261 +msgid "Unsupported format." msgstr "" -#: ../lib/util.php:332 lib/util.php:348 lib/action.php:576 lib/action.php:669 -#: lib/action.php:719 lib/action.php:734 -msgid "Contact" +#: actions/apitimelinefavorites.php:107 +#, php-format +msgid "%s / Favorites from %s" msgstr "" -#: ../lib/openid.php:178 lib/openid.php:178 lib/openid.php:187 -#: lib/openid.php:190 +#: actions/apitimelinefavorites.php:119 #, php-format -msgid "Could not create OpenID form: %s" +msgid "%s updates favorited by %s / %s." msgstr "" -#: ../actions/twitapifriendships.php:60 ../actions/twitapifriendships.php:76 -#: actions/twitapifriendships.php:60 actions/twitapifriendships.php:76 -#: actions/twitapifriendships.php:48 actions/twitapifriendships.php:64 -#: actions/twitapifriendships.php:51 actions/twitapifriendships.php:68 -#: actions/apifriendshipscreate.php:118 +#: actions/apitimelinegroup.php:102 actions/apitimelineuser.php:117 +#: actions/grouprss.php:131 actions/userrss.php:90 #, php-format -msgid "Could not follow user: %s is already on your list." +msgid "%s timeline" msgstr "" -#: ../actions/twitapifriendships.php:53 actions/twitapifriendships.php:53 -#: actions/twitapifriendships.php:41 actions/twitapifriendships.php:43 -#: actions/apifriendshipscreate.php:109 -msgid "Could not follow user: User not found." +#: actions/apitimelinegroup.php:110 actions/apitimelineuser.php:125 +#: actions/userrss.php:92 +#, php-format +msgid "Updates from %1$s on %2$s!" msgstr "" -#: ../lib/openid.php:160 lib/openid.php:160 lib/openid.php:169 -#: lib/openid.php:172 +#: actions/apitimelinementions.php:116 #, php-format -msgid "Could not redirect to server: %s" +msgid "%1$s / Updates mentioning %2$s" msgstr "" -#: ../actions/updateprofile.php:162 actions/updateprofile.php:163 -#: actions/updateprofile.php:166 actions/updateprofile.php:176 -msgid "Could not save avatar info" +#: actions/apitimelinementions.php:126 +#, php-format +msgid "%1$s updates that reply to updates from %2$s / %3$s." msgstr "" -#: ../actions/updateprofile.php:155 actions/updateprofile.php:156 -#: actions/updateprofile.php:159 actions/updateprofile.php:163 -msgid "Could not save new profile info" +#: actions/apitimelinepublic.php:106 actions/publicrss.php:103 +#, php-format +msgid "%s public timeline" msgstr "" -#: ../lib/subs.php:54 lib/subs.php:61 lib/subs.php:72 lib/subs.php:75 -msgid "Could not subscribe other to you." +#: actions/apitimelinepublic.php:110 actions/publicrss.php:105 +#, php-format +msgid "%s updates from everyone!" msgstr "" -#: ../lib/subs.php:46 lib/subs.php:46 lib/subs.php:57 lib/subs.php:56 -msgid "Could not subscribe." +#: actions/apitimelinetag.php:101 actions/tag.php:66 +#, php-format +msgid "Notices tagged with %s" msgstr "" -#: ../actions/recoverpassword.php:102 actions/recoverpassword.php:105 -#: actions/recoverpassword.php:111 -msgid "Could not update user with confirmed email address." +#: actions/apitimelinetag.php:107 actions/tagrss.php:64 +#, php-format +msgid "Updates tagged with %1$s on %2$s!" msgstr "" -#: ../actions/finishremotesubscribe.php:99 -#: actions/finishremotesubscribe.php:101 actions/finishremotesubscribe.php:114 -msgid "Couldn't convert request tokens to access tokens." +#: actions/apiusershow.php:96 +msgid "Not found." msgstr "" -#: ../actions/confirmaddress.php:84 ../actions/emailsettings.php:234 -#: ../actions/imsettings.php:218 ../actions/smssettings.php:241 -#: actions/confirmaddress.php:84 actions/emailsettings.php:252 -#: actions/imsettings.php:226 actions/smssettings.php:249 -#: actions/confirmaddress.php:126 actions/emailsettings.php:375 -#: actions/imsettings.php:357 actions/smssettings.php:370 -#: actions/emailsettings.php:382 actions/emailsettings.php:390 -#: actions/imsettings.php:363 actions/smssettings.php:382 -msgid "Couldn't delete email confirmation." +#: actions/attachment.php:73 +msgid "No such attachment." msgstr "" -#: ../lib/subs.php:103 lib/subs.php:116 lib/subs.php:134 lib/subs.php:136 -msgid "Couldn't delete subscription." +#: actions/avatarbynickname.php:59 actions/leavegroup.php:76 +msgid "No nickname." msgstr "" -#: ../actions/twitapistatuses.php:93 actions/twitapistatuses.php:98 -#: actions/twitapistatuses.php:84 actions/twitapistatuses.php:87 -msgid "Couldn't find any statuses." +#: actions/avatarbynickname.php:64 +msgid "No size." msgstr "" -#: ../actions/remotesubscribe.php:127 actions/remotesubscribe.php:136 -#: actions/remotesubscribe.php:178 -msgid "Couldn't get a request token." +#: actions/avatarbynickname.php:69 +msgid "Invalid size." msgstr "" -#: ../actions/emailsettings.php:205 ../actions/imsettings.php:187 -#: ../actions/smssettings.php:206 actions/emailsettings.php:223 -#: actions/imsettings.php:195 actions/smssettings.php:214 -#: actions/emailsettings.php:337 actions/imsettings.php:311 -#: actions/smssettings.php:325 actions/emailsettings.php:344 -#: actions/emailsettings.php:352 actions/imsettings.php:317 -#: actions/smssettings.php:337 -msgid "Couldn't insert confirmation code." +#: actions/avatarsettings.php:67 actions/showgroup.php:221 +#: lib/accountsettingsaction.php:111 +msgid "Avatar" msgstr "" -#: ../actions/finishremotesubscribe.php:180 -#: actions/finishremotesubscribe.php:182 actions/finishremotesubscribe.php:218 -#: lib/oauthstore.php:487 -msgid "Couldn't insert new subscription." +#: actions/avatarsettings.php:78 +#, php-format +msgid "You can upload your personal avatar. The maximum file size is %s." msgstr "" -#: ../actions/profilesettings.php:184 ../actions/twitapiaccount.php:96 -#: actions/profilesettings.php:299 actions/twitapiaccount.php:94 -#: actions/profilesettings.php:302 actions/twitapiaccount.php:81 -#: actions/twitapiaccount.php:82 actions/profilesettings.php:328 -msgid "Couldn't save profile." +#: actions/avatarsettings.php:106 actions/avatarsettings.php:182 +#: actions/grouplogo.php:178 actions/remotesubscribe.php:191 +#: actions/userauthorization.php:72 actions/userrss.php:103 +msgid "User without matching profile" msgstr "" -#: ../actions/profilesettings.php:161 actions/profilesettings.php:276 -#: actions/profilesettings.php:279 actions/profilesettings.php:295 -msgid "Couldn't update user for autosubscribe." +#: actions/avatarsettings.php:119 actions/avatarsettings.php:194 +#: actions/grouplogo.php:251 +msgid "Avatar settings" msgstr "" -#: ../actions/emailsettings.php:280 ../actions/emailsettings.php:294 -#: actions/emailsettings.php:298 actions/emailsettings.php:312 -#: actions/emailsettings.php:440 actions/emailsettings.php:462 -#: actions/emailsettings.php:447 actions/emailsettings.php:469 -#: actions/smssettings.php:515 actions/smssettings.php:539 -#: actions/smssettings.php:516 actions/smssettings.php:540 -#: actions/emailsettings.php:455 actions/emailsettings.php:477 -#: actions/smssettings.php:528 actions/smssettings.php:552 -msgid "Couldn't update user record." +#: actions/avatarsettings.php:126 actions/avatarsettings.php:202 +#: actions/grouplogo.php:199 actions/grouplogo.php:259 +msgid "Original" msgstr "" -#: ../actions/confirmaddress.php:72 ../actions/emailsettings.php:156 -#: ../actions/emailsettings.php:259 ../actions/imsettings.php:138 -#: ../actions/imsettings.php:243 ../actions/profilesettings.php:141 -#: ../actions/smssettings.php:157 ../actions/smssettings.php:269 -#: actions/confirmaddress.php:72 actions/emailsettings.php:174 -#: actions/emailsettings.php:277 actions/imsettings.php:146 -#: actions/imsettings.php:251 actions/profilesettings.php:256 -#: actions/smssettings.php:165 actions/smssettings.php:277 -#: actions/confirmaddress.php:114 actions/emailsettings.php:280 -#: actions/emailsettings.php:411 actions/imsettings.php:252 -#: actions/imsettings.php:395 actions/othersettings.php:162 -#: actions/profilesettings.php:259 actions/smssettings.php:266 -#: actions/smssettings.php:408 actions/emailsettings.php:287 -#: actions/emailsettings.php:418 actions/othersettings.php:167 -#: actions/profilesettings.php:260 actions/emailsettings.php:295 -#: actions/emailsettings.php:426 actions/imsettings.php:258 -#: actions/imsettings.php:401 actions/othersettings.php:174 -#: actions/profilesettings.php:276 actions/smssettings.php:278 -#: actions/smssettings.php:420 -msgid "Couldn't update user." +#: actions/avatarsettings.php:141 actions/avatarsettings.php:214 +#: actions/grouplogo.php:210 actions/grouplogo.php:271 +msgid "Preview" msgstr "" -#: ../actions/finishopenidlogin.php:84 actions/finishopenidlogin.php:90 -#: actions/finishopenidlogin.php:112 actions/finishopenidlogin.php:111 -msgid "Create" +#: actions/avatarsettings.php:148 lib/noticelist.php:522 +msgid "Delete" msgstr "" -#: ../actions/finishopenidlogin.php:70 actions/finishopenidlogin.php:76 -#: actions/finishopenidlogin.php:98 actions/finishopenidlogin.php:97 -msgid "Create a new user with this nickname." +#: actions/avatarsettings.php:165 actions/grouplogo.php:233 +msgid "Upload" msgstr "" -#: ../actions/finishopenidlogin.php:68 actions/finishopenidlogin.php:74 -#: actions/finishopenidlogin.php:96 actions/finishopenidlogin.php:95 -msgid "Create new account" +#: actions/avatarsettings.php:228 actions/grouplogo.php:286 +msgid "Crop" msgstr "" -#: ../actions/finishopenidlogin.php:191 actions/finishopenidlogin.php:197 -#: actions/finishopenidlogin.php:231 actions/finishopenidlogin.php:247 -msgid "Creating new account for OpenID that already has a user." +#: actions/avatarsettings.php:265 actions/block.php:64 actions/disfavor.php:74 +#: actions/emailsettings.php:237 actions/favor.php:75 +#: actions/groupblock.php:66 actions/grouplogo.php:309 +#: actions/groupunblock.php:66 actions/imsettings.php:206 +#: actions/invite.php:56 actions/login.php:131 actions/makeadmin.php:66 +#: actions/newmessage.php:135 actions/newnotice.php:103 actions/nudge.php:80 +#: actions/othersettings.php:145 actions/passwordsettings.php:137 +#: actions/profilesettings.php:187 actions/recoverpassword.php:337 +#: actions/register.php:165 actions/remotesubscribe.php:77 +#: actions/smssettings.php:228 actions/subedit.php:38 actions/subscribe.php:46 +#: actions/tagother.php:166 actions/unblock.php:65 actions/unsubscribe.php:69 +#: actions/userauthorization.php:52 lib/designsettings.php:294 +msgid "There was a problem with your session token. Try again, please." msgstr "" -#: ../actions/imsettings.php:45 actions/imsettings.php:46 -#: actions/imsettings.php:100 actions/imsettings.php:106 -msgid "Current confirmed Jabber/GTalk address." +#: actions/avatarsettings.php:277 actions/emailsettings.php:255 +#: actions/grouplogo.php:319 actions/imsettings.php:220 +#: actions/recoverpassword.php:44 actions/smssettings.php:248 +#: lib/designsettings.php:304 +msgid "Unexpected form submission." msgstr "" -#: ../actions/smssettings.php:46 actions/smssettings.php:46 -#: actions/smssettings.php:100 actions/smssettings.php:112 -msgid "Current confirmed SMS-enabled phone number." +#: actions/avatarsettings.php:322 +msgid "Pick a square area of the image to be your avatar" msgstr "" -#: ../actions/emailsettings.php:44 actions/emailsettings.php:45 -#: actions/emailsettings.php:99 actions/emailsettings.php:105 -msgid "Current confirmed email address." +#: actions/avatarsettings.php:337 actions/grouplogo.php:377 +msgid "Lost our file data." msgstr "" -#: ../classes/Notice.php:72 classes/Notice.php:86 classes/Notice.php:91 -#: classes/Notice.php:114 classes/Notice.php:124 classes/Notice.php:164 -#, php-format -msgid "DB error inserting hashtag: %s" +#: actions/avatarsettings.php:360 +msgid "Avatar updated." msgstr "" -#: ../lib/util.php:1061 lib/util.php:1110 classes/Notice.php:698 -#: classes/Notice.php:757 classes/Notice.php:1042 classes/Notice.php:1117 -#: classes/Notice.php:1120 -#, php-format -msgid "DB error inserting reply: %s" +#: actions/avatarsettings.php:363 +msgid "Failed updating avatar." msgstr "" -#: ../actions/deletenotice.php:41 actions/deletenotice.php:41 -#: actions/deletenotice.php:79 actions/deletenotice.php:111 -#: actions/deletenotice.php:109 actions/deletenotice.php:141 -msgid "Delete notice" +#: actions/avatarsettings.php:387 +msgid "Avatar deleted." msgstr "" -#: ../actions/profilesettings.php:51 ../actions/register.php:172 -#: actions/profilesettings.php:84 actions/register.php:186 -#: actions/profilesettings.php:114 actions/register.php:404 -#: actions/register.php:450 -msgid "Describe yourself and your interests in 140 chars" +#: actions/blockedfromgroup.php:73 actions/editgroup.php:84 +#: actions/groupdesignsettings.php:84 actions/grouplogo.php:86 +#: actions/groupmembers.php:76 actions/grouprss.php:91 +#: actions/joingroup.php:76 actions/showgroup.php:121 +msgid "No nickname" msgstr "" -#: ../actions/register.php:158 ../actions/register.php:161 -#: ../lib/settingsaction.php:87 actions/register.php:172 -#: actions/register.php:175 lib/settingsaction.php:87 actions/register.php:381 -#: actions/register.php:385 lib/accountsettingsaction.php:113 -#: actions/register.php:427 actions/register.php:431 actions/register.php:435 -#: lib/accountsettingsaction.php:117 actions/register.php:437 -#: actions/register.php:441 -msgid "Email" +#: actions/blockedfromgroup.php:80 actions/editgroup.php:96 +#: actions/groupbyid.php:83 actions/groupdesignsettings.php:97 +#: actions/grouplogo.php:99 actions/groupmembers.php:83 +#: actions/grouprss.php:98 actions/joingroup.php:83 actions/showgroup.php:137 +msgid "No such group" msgstr "" -#: ../actions/emailsettings.php:59 actions/emailsettings.php:60 -#: actions/emailsettings.php:115 actions/emailsettings.php:121 -msgid "Email Address" +#: actions/blockedfromgroup.php:90 +#, php-format +msgid "%s blocked profiles" msgstr "" -#: ../actions/emailsettings.php:32 actions/emailsettings.php:32 -#: actions/emailsettings.php:60 -msgid "Email Settings" +#: actions/blockedfromgroup.php:93 +#, php-format +msgid "%s blocked profiles, page %d" msgstr "" -#: ../actions/register.php:73 actions/register.php:80 actions/register.php:163 -#: actions/register.php:200 actions/register.php:206 actions/register.php:212 -msgid "Email address already exists." +#: actions/blockedfromgroup.php:108 +msgid "A list of the users blocked from joining this group." msgstr "" -#: ../lib/mail.php:90 lib/mail.php:90 lib/mail.php:173 lib/mail.php:172 -msgid "Email address confirmation" +#: actions/blockedfromgroup.php:281 +msgid "Unblock user from group" msgstr "" -#: ../actions/emailsettings.php:61 actions/emailsettings.php:62 -#: actions/emailsettings.php:117 actions/emailsettings.php:123 -msgid "Email address, like \"UserName@example.org\"" +#: actions/blockedfromgroup.php:313 lib/unblockform.php:150 +msgid "Unblock" msgstr "" -#: ../actions/invite.php:129 actions/invite.php:137 actions/invite.php:174 -#: actions/invite.php:179 actions/invite.php:181 actions/invite.php:187 -msgid "Email addresses" +#: actions/blockedfromgroup.php:313 lib/unblockform.php:120 +#: lib/unblockform.php:150 +msgid "Unblock this user" msgstr "" -#: ../actions/recoverpassword.php:191 actions/recoverpassword.php:197 -#: actions/recoverpassword.php:231 actions/recoverpassword.php:249 -#: actions/recoverpassword.php:252 -msgid "Enter a nickname or email address." +#: actions/block.php:59 actions/deletenotice.php:67 actions/disfavor.php:61 +#: actions/favor.php:62 actions/groupblock.php:61 actions/groupunblock.php:61 +#: actions/logout.php:69 actions/makeadmin.php:61 actions/newmessage.php:87 +#: actions/newnotice.php:89 actions/nudge.php:63 actions/subedit.php:31 +#: actions/subscribe.php:30 actions/unblock.php:60 actions/unsubscribe.php:52 +#: lib/settingsaction.php:72 +msgid "Not logged in." msgstr "" -#: ../actions/smssettings.php:64 actions/smssettings.php:64 -#: actions/smssettings.php:119 actions/smssettings.php:131 -msgid "Enter the code you received on your phone." +#: actions/block.php:69 actions/groupblock.php:71 actions/groupunblock.php:71 +#: actions/makeadmin.php:71 actions/subedit.php:46 actions/unblock.php:70 +msgid "No profile specified." msgstr "" -#: ../actions/userauthorization.php:137 actions/userauthorization.php:144 -#: actions/userauthorization.php:161 actions/userauthorization.php:200 -msgid "Error authorizing token" +#: actions/block.php:74 actions/groupblock.php:76 actions/groupunblock.php:76 +#: actions/makeadmin.php:76 actions/subedit.php:53 actions/tagother.php:46 +#: actions/unblock.php:75 +msgid "No profile with that ID." msgstr "" -#: ../actions/finishopenidlogin.php:253 actions/finishopenidlogin.php:259 -#: actions/finishopenidlogin.php:297 actions/finishopenidlogin.php:302 -#: actions/finishopenidlogin.php:325 -msgid "Error connecting user to OpenID." +#: actions/block.php:111 actions/block.php:134 +msgid "Block user" msgstr "" -#: ../actions/finishaddopenid.php:78 actions/finishaddopenid.php:78 -#: actions/finishaddopenid.php:126 -msgid "Error connecting user." +#: actions/block.php:136 +msgid "" +"Are you sure you want to block this user? Afterwards, they will be " +"unsubscribed from you, unable to subscribe to you in the future, and you " +"will not be notified of any @-replies from them." msgstr "" -#: ../actions/finishremotesubscribe.php:151 -#: actions/finishremotesubscribe.php:153 actions/finishremotesubscribe.php:166 -#: lib/oauthstore.php:291 -msgid "Error inserting avatar" +#: actions/block.php:149 actions/deletenotice.php:145 +#: actions/groupblock.php:176 +msgid "No" msgstr "" -#: ../actions/finishremotesubscribe.php:143 -#: actions/finishremotesubscribe.php:145 actions/finishremotesubscribe.php:158 -#: lib/oauthstore.php:283 -msgid "Error inserting new profile" +#: actions/block.php:149 +msgid "Do not block this user from this group" msgstr "" -#: ../actions/finishremotesubscribe.php:167 -#: actions/finishremotesubscribe.php:169 actions/finishremotesubscribe.php:182 -#: lib/oauthstore.php:311 -msgid "Error inserting remote profile" +#: actions/block.php:150 actions/deletenotice.php:146 +#: actions/groupblock.php:177 +msgid "Yes" msgstr "" -#: ../actions/recoverpassword.php:240 actions/recoverpassword.php:246 -#: actions/recoverpassword.php:280 actions/recoverpassword.php:298 -#: actions/recoverpassword.php:301 -msgid "Error saving address confirmation." +#: actions/block.php:150 +msgid "Block this user from this group" msgstr "" -#: ../actions/userauthorization.php:140 actions/userauthorization.php:147 -#: actions/userauthorization.php:164 actions/userauthorization.php:203 -msgid "Error saving remote profile" +#: actions/block.php:165 +msgid "You have already blocked this user." msgstr "" -#: ../lib/openid.php:226 lib/openid.php:226 lib/openid.php:235 -#: lib/openid.php:238 -msgid "Error saving the profile." +#: actions/block.php:170 +msgid "Failed to save block information." msgstr "" -#: ../lib/openid.php:237 lib/openid.php:237 lib/openid.php:246 -#: lib/openid.php:249 -msgid "Error saving the user." +#: actions/bookmarklet.php:50 +msgid "Post to " msgstr "" -#: ../actions/password.php:80 actions/profilesettings.php:399 -#: actions/passwordsettings.php:164 actions/passwordsettings.php:169 -#: actions/passwordsettings.php:175 actions/passwordsettings.php:180 -msgid "Error saving user; invalid." +#: actions/confirmaddress.php:75 +msgid "No confirmation code." msgstr "" -#: ../actions/login.php:47 ../actions/login.php:73 -#: ../actions/recoverpassword.php:307 ../actions/register.php:98 -#: actions/login.php:47 actions/login.php:73 actions/recoverpassword.php:320 -#: actions/register.php:108 actions/login.php:112 actions/login.php:138 -#: actions/recoverpassword.php:354 actions/register.php:198 -#: actions/login.php:120 actions/recoverpassword.php:372 -#: actions/register.php:235 actions/login.php:122 -#: actions/recoverpassword.php:375 actions/register.php:242 -#: actions/login.php:149 actions/register.php:248 -msgid "Error setting user." +#: actions/confirmaddress.php:80 +msgid "Confirmation code not found." msgstr "" -#: ../actions/finishaddopenid.php:83 actions/finishaddopenid.php:83 -#: actions/finishaddopenid.php:131 -msgid "Error updating profile" +#: actions/confirmaddress.php:85 +msgid "That confirmation code is not for you!" msgstr "" -#: ../actions/finishremotesubscribe.php:161 -#: actions/finishremotesubscribe.php:163 actions/finishremotesubscribe.php:176 -#: actions/finishremotesubscribe.php:133 lib/oauthstore.php:306 -msgid "Error updating remote profile" +#: actions/confirmaddress.php:90 +#, php-format +msgid "Unrecognized address type %s" msgstr "" -#: ../actions/recoverpassword.php:80 actions/recoverpassword.php:80 -#: actions/recoverpassword.php:86 -msgid "Error with confirmation code." +#: actions/confirmaddress.php:94 +msgid "That address has already been confirmed." msgstr "" -#: ../actions/finishopenidlogin.php:89 actions/finishopenidlogin.php:95 -#: actions/finishopenidlogin.php:117 actions/finishopenidlogin.php:116 -msgid "Existing nickname" +#: actions/confirmaddress.php:114 actions/emailsettings.php:295 +#: actions/emailsettings.php:426 actions/imsettings.php:258 +#: actions/imsettings.php:401 actions/othersettings.php:174 +#: actions/profilesettings.php:276 actions/smssettings.php:278 +#: actions/smssettings.php:420 +msgid "Couldn't update user." msgstr "" -#: ../lib/util.php:326 lib/util.php:342 lib/action.php:570 lib/action.php:663 -#: lib/action.php:708 lib/action.php:723 -msgid "FAQ" +#: actions/confirmaddress.php:126 actions/emailsettings.php:390 +#: actions/imsettings.php:363 actions/smssettings.php:382 +msgid "Couldn't delete email confirmation." msgstr "" -#: ../actions/avatar.php:115 actions/profilesettings.php:352 -#: actions/avatarsettings.php:397 actions/avatarsettings.php:349 -#: actions/avatarsettings.php:363 -msgid "Failed updating avatar." +#: actions/confirmaddress.php:144 +msgid "Confirm Address" msgstr "" -#: ../actions/all.php:61 ../actions/allrss.php:64 actions/all.php:61 -#: actions/allrss.php:64 actions/all.php:75 actions/allrss.php:107 -#: actions/allrss.php:110 actions/allrss.php:118 +#: actions/confirmaddress.php:159 #, php-format -msgid "Feed for friends of %s" +msgid "The address \"%s\" has been confirmed for your account." msgstr "" -#: ../actions/replies.php:65 ../actions/repliesrss.php:80 -#: actions/replies.php:65 actions/repliesrss.php:66 actions/replies.php:134 -#: actions/repliesrss.php:71 actions/replies.php:136 actions/replies.php:135 -#, php-format -msgid "Feed for replies to %s" +#: actions/conversation.php:99 +msgid "Conversation" msgstr "" -#: ../actions/tag.php:55 actions/tag.php:55 actions/tag.php:61 -#: actions/tag.php:68 -#, php-format -msgid "Feed for tag %s" +#: actions/conversation.php:154 lib/mailbox.php:116 lib/noticelist.php:87 +#: lib/profileaction.php:206 +msgid "Notices" msgstr "" -#: ../lib/searchaction.php:105 lib/searchaction.php:105 -#: lib/searchgroupnav.php:83 -msgid "Find content of notices" +#: actions/deletenotice.php:52 actions/shownotice.php:92 +msgid "No such notice." msgstr "" -#: ../lib/searchaction.php:101 lib/searchaction.php:101 -#: lib/searchgroupnav.php:81 -msgid "Find people on this site" +#: actions/deletenotice.php:71 +msgid "Can't delete this notice." msgstr "" -#: ../actions/login.php:122 actions/login.php:247 actions/login.php:255 -#: actions/login.php:282 +#: actions/deletenotice.php:103 msgid "" -"For security reasons, please re-enter your user name and password before " -"changing your settings." +"You are about to permanently delete a notice. Once this is done, it cannot " +"be undone." msgstr "" -#: ../actions/profilesettings.php:44 ../actions/register.php:164 -#: actions/profilesettings.php:77 actions/register.php:178 -#: actions/profilesettings.php:103 actions/register.php:391 -#: actions/showgroup.php:235 actions/showstream.php:262 -#: actions/tagother.php:105 lib/groupeditform.php:142 -#: actions/showgroup.php:237 actions/showstream.php:255 -#: actions/tagother.php:104 actions/register.php:437 actions/showgroup.php:242 -#: actions/showstream.php:220 lib/groupeditform.php:157 -#: actions/profilesettings.php:111 actions/register.php:441 -#: actions/showgroup.php:247 actions/showstream.php:267 -#: actions/register.php:447 lib/userprofile.php:149 -msgid "Full name" +#: actions/deletenotice.php:109 actions/deletenotice.php:141 +msgid "Delete notice" msgstr "" -#: ../actions/profilesettings.php:98 ../actions/register.php:79 -#: ../actions/updateprofile.php:93 actions/profilesettings.php:213 -#: actions/register.php:86 actions/updateprofile.php:94 -#: actions/editgroup.php:195 actions/newgroup.php:146 -#: actions/profilesettings.php:202 actions/register.php:171 -#: actions/updateprofile.php:97 actions/updateprofile.php:99 -#: actions/editgroup.php:197 actions/newgroup.php:147 -#: actions/profilesettings.php:203 actions/register.php:208 -#: actions/apigroupcreate.php:253 actions/editgroup.php:198 -#: actions/newgroup.php:142 actions/profilesettings.php:218 -#: actions/register.php:214 actions/register.php:220 -msgid "Full name is too long (max 255 chars)." +#: actions/deletenotice.php:144 +msgid "Are you sure you want to delete this notice?" msgstr "" -#: ../lib/util.php:322 lib/util.php:338 lib/action.php:344 lib/action.php:566 -#: lib/action.php:421 lib/action.php:659 lib/action.php:446 lib/action.php:704 -#: lib/action.php:456 lib/action.php:719 -msgid "Help" +#: actions/deletenotice.php:145 +msgid "Do not delete this notice" msgstr "" -#: ../lib/util.php:298 lib/util.php:314 lib/action.php:322 -#: lib/facebookaction.php:200 lib/action.php:393 lib/facebookaction.php:213 -#: lib/action.php:417 lib/action.php:430 -msgid "Home" +#: actions/deletenotice.php:146 lib/noticelist.php:522 +msgid "Delete this notice" msgstr "" -#: ../actions/profilesettings.php:46 ../actions/register.php:167 -#: actions/profilesettings.php:79 actions/register.php:181 -#: actions/profilesettings.php:107 actions/register.php:396 -#: lib/groupeditform.php:146 actions/register.php:442 -#: lib/groupeditform.php:161 actions/profilesettings.php:115 -#: actions/register.php:446 actions/register.php:452 -msgid "Homepage" +#: actions/deletenotice.php:157 +msgid "There was a problem with your session token. Try again, please." msgstr "" -#: ../actions/profilesettings.php:95 ../actions/register.php:76 -#: actions/profilesettings.php:210 actions/register.php:83 -#: actions/editgroup.php:192 actions/newgroup.php:143 -#: actions/profilesettings.php:199 actions/register.php:168 -#: actions/editgroup.php:194 actions/newgroup.php:144 -#: actions/profilesettings.php:200 actions/register.php:205 -#: actions/apigroupcreate.php:244 actions/editgroup.php:195 -#: actions/newgroup.php:139 actions/profilesettings.php:215 -#: actions/register.php:211 actions/register.php:217 -msgid "Homepage is not a valid URL." +#: actions/disfavor.php:81 +msgid "This notice is not a favorite!" msgstr "" -#: ../actions/emailsettings.php:91 actions/emailsettings.php:98 -#: actions/emailsettings.php:173 actions/emailsettings.php:178 -#: actions/emailsettings.php:185 -msgid "I want to post notices by email." +#: actions/disfavor.php:94 +msgid "Add to favorites" msgstr "" -#: ../lib/settingsaction.php:102 lib/settingsaction.php:96 -#: lib/connectsettingsaction.php:104 lib/connectsettingsaction.php:110 -msgid "IM" +#: actions/doc.php:69 +msgid "No such document." msgstr "" -#: ../actions/imsettings.php:60 actions/imsettings.php:61 -#: actions/imsettings.php:118 actions/imsettings.php:124 -msgid "IM Address" +#: actions/editgroup.php:56 +#, php-format +msgid "Edit %s group" msgstr "" -#: ../actions/imsettings.php:33 actions/imsettings.php:33 -#: actions/imsettings.php:59 -msgid "IM Settings" +#: actions/editgroup.php:68 actions/grouplogo.php:70 actions/newgroup.php:65 +msgid "You must be logged in to create a group." msgstr "" -#: ../actions/finishopenidlogin.php:88 actions/finishopenidlogin.php:94 -#: actions/finishopenidlogin.php:116 actions/finishopenidlogin.php:115 -msgid "" -"If you already have an account, login with your username and password to " -"connect it to your OpenID." +#: actions/editgroup.php:103 actions/editgroup.php:168 +#: actions/groupdesignsettings.php:104 actions/grouplogo.php:106 +msgid "You must be an admin to edit the group" msgstr "" -#: ../actions/openidsettings.php:45 actions/openidsettings.php:96 -msgid "" -"If you want to add an OpenID to your account, enter it in the box below and " -"click \"Add\"." +#: actions/editgroup.php:154 +msgid "Use this form to edit the group." msgstr "" -#: ../actions/emailsettings.php:67 ../actions/smssettings.php:76 -#: actions/emailsettings.php:68 actions/smssettings.php:76 -#: actions/emailsettings.php:127 actions/smssettings.php:140 -#: actions/emailsettings.php:133 actions/smssettings.php:152 -msgid "Incoming email" +#: actions/editgroup.php:201 actions/newgroup.php:145 +#, php-format +msgid "description is too long (max %d chars)." msgstr "" -#: ../actions/emailsettings.php:283 actions/emailsettings.php:301 -#: actions/emailsettings.php:443 actions/emailsettings.php:450 -#: actions/smssettings.php:518 actions/smssettings.php:519 -#: actions/emailsettings.php:458 actions/smssettings.php:531 -msgid "Incoming email address removed." +#: actions/editgroup.php:253 +msgid "Could not update group." msgstr "" -#: ../actions/password.php:69 actions/profilesettings.php:388 -#: actions/passwordsettings.php:153 actions/passwordsettings.php:158 -#: actions/passwordsettings.php:164 -msgid "Incorrect old password" +#: actions/editgroup.php:269 +msgid "Options saved." msgstr "" -#: ../actions/login.php:67 actions/login.php:67 actions/facebookhome.php:131 -#: actions/login.php:132 actions/facebookhome.php:130 actions/login.php:114 -#: actions/facebookhome.php:129 actions/login.php:116 actions/login.php:143 -msgid "Incorrect username or password." +#: actions/emailsettings.php:60 +msgid "Email Settings" msgstr "" -#: ../actions/recoverpassword.php:265 actions/recoverpassword.php:304 -#: actions/recoverpassword.php:322 actions/recoverpassword.php:325 -msgid "" -"Instructions for recovering your password have been sent to the email " -"address registered to your account." +#: actions/emailsettings.php:71 +#, php-format +msgid "Manage how you get email from %%site.name%%." msgstr "" -#: ../actions/updateprofile.php:114 actions/updateprofile.php:115 -#: actions/updateprofile.php:118 actions/updateprofile.php:120 -#, php-format -msgid "Invalid avatar URL '%s'" +#: actions/emailsettings.php:100 +msgid "Address" msgstr "" -#: ../actions/invite.php:55 actions/invite.php:62 actions/invite.php:70 -#: actions/invite.php:72 -#, php-format -msgid "Invalid email address: %s" +#: actions/emailsettings.php:105 +msgid "Current confirmed email address." msgstr "" -#: ../actions/updateprofile.php:98 actions/updateprofile.php:99 -#: actions/updateprofile.php:102 actions/updateprofile.php:104 -#, php-format -msgid "Invalid homepage '%s'" +#: actions/emailsettings.php:107 actions/emailsettings.php:140 +#: actions/imsettings.php:108 actions/smssettings.php:115 +#: actions/smssettings.php:158 +msgid "Remove" msgstr "" -#: ../actions/updateprofile.php:82 actions/updateprofile.php:83 -#: actions/updateprofile.php:86 actions/updateprofile.php:88 -#, php-format -msgid "Invalid license URL '%s'" +#: actions/emailsettings.php:113 +msgid "" +"Awaiting confirmation on this address. Check your inbox (and spam box!) for " +"a message with further instructions." msgstr "" -#: ../actions/postnotice.php:61 actions/postnotice.php:62 -#: actions/postnotice.php:66 actions/postnotice.php:84 -msgid "Invalid notice content" +#: actions/emailsettings.php:117 actions/imsettings.php:120 +#: actions/smssettings.php:126 +msgid "Cancel" msgstr "" -#: ../actions/postnotice.php:67 actions/postnotice.php:68 -#: actions/postnotice.php:72 -msgid "Invalid notice uri" +#: actions/emailsettings.php:121 +msgid "Email Address" msgstr "" -#: ../actions/postnotice.php:72 actions/postnotice.php:73 -#: actions/postnotice.php:77 -msgid "Invalid notice url" +#: actions/emailsettings.php:123 +msgid "Email address, like \"UserName@example.org\"" msgstr "" -#: ../actions/updateprofile.php:87 actions/updateprofile.php:88 -#: actions/updateprofile.php:91 actions/updateprofile.php:93 -#, php-format -msgid "Invalid profile URL '%s'." +#: actions/emailsettings.php:126 actions/imsettings.php:133 +#: actions/smssettings.php:145 +msgid "Add" msgstr "" -#: ../actions/remotesubscribe.php:96 actions/remotesubscribe.php:105 -#: actions/remotesubscribe.php:135 actions/remotesubscribe.php:159 -msgid "Invalid profile URL (bad format)" +#: actions/emailsettings.php:133 actions/smssettings.php:152 +msgid "Incoming email" msgstr "" -#: ../actions/finishremotesubscribe.php:77 -#: actions/finishremotesubscribe.php:79 actions/finishremotesubscribe.php:80 -msgid "Invalid profile URL returned by server." +#: actions/emailsettings.php:138 actions/smssettings.php:157 +msgid "Send email to this address to post new notices." msgstr "" -#: ../actions/avatarbynickname.php:37 actions/avatarbynickname.php:37 -#: actions/avatarbynickname.php:69 -msgid "Invalid size." +#: actions/emailsettings.php:145 actions/smssettings.php:162 +msgid "Make a new email address for posting to; cancels the old one." msgstr "" -#: ../actions/finishopenidlogin.php:235 ../actions/register.php:93 -#: ../actions/register.php:111 actions/finishopenidlogin.php:241 -#: actions/register.php:103 actions/register.php:121 -#: actions/finishopenidlogin.php:279 actions/register.php:193 -#: actions/register.php:211 actions/finishopenidlogin.php:284 -#: actions/finishopenidlogin.php:307 actions/register.php:230 -#: actions/register.php:251 actions/register.php:237 actions/register.php:258 -#: actions/register.php:243 actions/register.php:264 -msgid "Invalid username or password." +#: actions/emailsettings.php:148 actions/smssettings.php:164 +msgid "New" msgstr "" -#: ../actions/invite.php:79 actions/invite.php:86 actions/invite.php:102 -#: actions/invite.php:104 actions/invite.php:110 -msgid "Invitation(s) sent" +#: actions/emailsettings.php:153 actions/imsettings.php:139 +#: actions/smssettings.php:169 +msgid "Preferences" msgstr "" -#: ../actions/invite.php:97 actions/invite.php:104 actions/invite.php:136 -#: actions/invite.php:138 actions/invite.php:144 -msgid "Invitation(s) sent to the following people:" +#: actions/emailsettings.php:158 +msgid "Send me notices of new subscriptions through email." msgstr "" -#: ../lib/util.php:306 lib/util.php:322 lib/facebookaction.php:207 -#: lib/subgroupnav.php:103 lib/facebookaction.php:220 lib/action.php:429 -#: lib/facebookaction.php:221 lib/subgroupnav.php:105 lib/action.php:439 -msgid "Invite" +#: actions/emailsettings.php:163 +msgid "Send me email when someone adds my notice as a favorite." msgstr "" -#: ../actions/invite.php:123 actions/invite.php:130 actions/invite.php:104 -#: actions/invite.php:106 actions/invite.php:112 -msgid "Invite new users" +#: actions/emailsettings.php:169 +msgid "Send me email when someone sends me a private message." msgstr "" -#: ../lib/util.php:261 lib/util.php:277 lib/action.php:609 lib/action.php:706 -#: lib/action.php:756 lib/action.php:771 -#, php-format -msgid "" -"It runs the [StatusNet](http://status.net/) microblogging software, version %" -"s, available under the [GNU Affero General Public License](http://www.fsf." -"org/licensing/licenses/agpl-3.0.html)." +#: actions/emailsettings.php:174 +msgid "Send me email when someone sends me an \"@-reply\"." msgstr "" -#: ../actions/imsettings.php:173 actions/imsettings.php:181 -#: actions/imsettings.php:296 actions/imsettings.php:302 -msgid "Jabber ID already belongs to another user." +#: actions/emailsettings.php:179 +msgid "Allow friends to nudge me and send me an email." msgstr "" -#: ../actions/imsettings.php:62 actions/imsettings.php:63 -#: actions/imsettings.php:120 actions/imsettings.php:126 -#, php-format -msgid "" -"Jabber or GTalk address, like \"UserName@example.org\". First, make sure to " -"add %s to your buddy list in your IM client or on GTalk." +#: actions/emailsettings.php:185 +msgid "I want to post notices by email." msgstr "" -#: ../actions/profilesettings.php:57 actions/profilesettings.php:90 -#: actions/profilesettings.php:128 actions/profilesettings.php:129 -#: actions/profilesettings.php:144 -msgid "Language" +#: actions/emailsettings.php:191 +msgid "Publish a MicroID for my email address." msgstr "" -#: ../actions/profilesettings.php:113 actions/profilesettings.php:228 -#: actions/profilesettings.php:217 actions/profilesettings.php:218 -#: actions/profilesettings.php:234 -msgid "Language is too long (max 50 chars)." +#: actions/emailsettings.php:195 actions/imsettings.php:163 +#: actions/othersettings.php:126 actions/profilesettings.php:167 +#: actions/smssettings.php:181 actions/subscriptions.php:203 +#: actions/tagother.php:154 lib/designsettings.php:256 +#: lib/groupeditform.php:202 +msgid "Save" msgstr "" -#: ../actions/profilesettings.php:52 ../actions/register.php:173 -#: actions/profilesettings.php:85 actions/register.php:187 -#: actions/profilesettings.php:117 actions/register.php:408 -#: actions/showgroup.php:244 actions/showstream.php:271 -#: actions/tagother.php:113 lib/groupeditform.php:156 lib/grouplist.php:126 -#: lib/profilelist.php:125 actions/showgroup.php:246 -#: actions/showstream.php:264 actions/tagother.php:112 lib/profilelist.php:123 -#: actions/register.php:454 actions/showgroup.php:251 -#: actions/showstream.php:229 actions/userauthorization.php:128 -#: lib/groupeditform.php:171 lib/profilelist.php:185 -#: actions/profilesettings.php:132 actions/register.php:464 -#: actions/showgroup.php:256 actions/showstream.php:282 -#: actions/userauthorization.php:158 lib/groupeditform.php:177 -#: lib/profilelist.php:218 actions/register.php:470 lib/userprofile.php:164 -msgid "Location" +#: actions/emailsettings.php:301 actions/imsettings.php:264 +#: actions/othersettings.php:180 actions/smssettings.php:284 +msgid "Preferences saved." msgstr "" -#: ../actions/profilesettings.php:104 ../actions/register.php:85 -#: ../actions/updateprofile.php:108 actions/profilesettings.php:219 -#: actions/register.php:92 actions/updateprofile.php:109 -#: actions/editgroup.php:201 actions/newgroup.php:152 -#: actions/profilesettings.php:208 actions/register.php:177 -#: actions/updateprofile.php:112 actions/updateprofile.php:114 -#: actions/editgroup.php:203 actions/newgroup.php:153 -#: actions/profilesettings.php:209 actions/register.php:214 -#: actions/apigroupcreate.php:272 actions/editgroup.php:204 -#: actions/newgroup.php:148 actions/profilesettings.php:225 -#: actions/register.php:221 actions/register.php:227 -msgid "Location is too long (max 255 chars)." +#: actions/emailsettings.php:319 +msgid "No email address." msgstr "" -#: ../actions/login.php:97 ../actions/login.php:106 -#: ../actions/openidlogin.php:68 ../lib/util.php:310 actions/login.php:97 -#: actions/login.php:106 actions/openidlogin.php:77 lib/util.php:326 -#: actions/facebooklogin.php:93 actions/login.php:186 actions/login.php:239 -#: actions/openidlogin.php:112 lib/action.php:335 lib/facebookaction.php:288 -#: lib/facebookaction.php:315 lib/logingroupnav.php:75 actions/login.php:169 -#: actions/login.php:222 actions/openidlogin.php:121 lib/action.php:412 -#: lib/facebookaction.php:293 lib/facebookaction.php:319 lib/action.php:443 -#: lib/facebookaction.php:295 lib/facebookaction.php:321 actions/login.php:177 -#: actions/login.php:230 lib/action.php:453 lib/logingroupnav.php:79 -#: actions/login.php:204 actions/login.php:257 -#, php-format -msgid "Login" +#: actions/emailsettings.php:326 +msgid "Cannot normalize that email address" msgstr "" -#: ../actions/openidlogin.php:44 actions/openidlogin.php:52 -#: actions/openidlogin.php:62 actions/openidlogin.php:70 -#, php-format -msgid "Login with an [OpenID](%%doc.openid%%) account." +#: actions/emailsettings.php:330 +msgid "Not a valid email address" msgstr "" -#: ../actions/login.php:126 actions/login.php:251 -#, php-format -msgid "" -"Login with your username and password. Don't have a username yet? [Register]" -"(%%action.register%%) a new account, or try [OpenID](%%action.openidlogin%" -"%). " +#: actions/emailsettings.php:333 +msgid "That is already your email address." msgstr "" -#: ../lib/util.php:308 lib/util.php:324 lib/action.php:332 lib/action.php:409 -#: lib/action.php:435 lib/action.php:445 -msgid "Logout" +#: actions/emailsettings.php:336 +msgid "That email address already belongs to another user." msgstr "" -#: ../actions/register.php:166 actions/register.php:180 -#: actions/register.php:393 actions/register.php:439 actions/register.php:443 -#: actions/register.php:449 -msgid "Longer name, preferably your \"real\" name" +#: actions/emailsettings.php:352 actions/imsettings.php:317 +#: actions/smssettings.php:337 +msgid "Couldn't insert confirmation code." msgstr "" -#: ../actions/login.php:110 actions/login.php:110 actions/login.php:245 -#: lib/facebookaction.php:320 actions/login.php:228 lib/facebookaction.php:325 -#: lib/facebookaction.php:327 actions/login.php:236 actions/login.php:263 -msgid "Lost or forgotten password?" +#: actions/emailsettings.php:358 +msgid "" +"A confirmation code was sent to the email address you added. Check your " +"inbox (and spam box!) for the code and instructions on how to use it." msgstr "" -#: ../actions/emailsettings.php:80 ../actions/smssettings.php:89 -#: actions/emailsettings.php:81 actions/smssettings.php:89 -#: actions/emailsettings.php:139 actions/smssettings.php:150 -#: actions/emailsettings.php:145 actions/smssettings.php:162 -msgid "Make a new email address for posting to; cancels the old one." +#: actions/emailsettings.php:378 actions/imsettings.php:351 +#: actions/smssettings.php:370 +msgid "No pending confirmation to cancel." msgstr "" -#: ../actions/emailsettings.php:27 actions/emailsettings.php:27 -#: actions/emailsettings.php:71 -#, php-format -msgid "Manage how you get email from %%site.name%%." +#: actions/emailsettings.php:382 actions/imsettings.php:355 +msgid "That is the wrong IM address." msgstr "" -#: ../actions/showstream.php:300 actions/showstream.php:315 -#: actions/showstream.php:480 lib/profileaction.php:182 -msgid "Member since" +#: actions/emailsettings.php:394 actions/imsettings.php:367 +#: actions/smssettings.php:386 +msgid "Confirmation cancelled." msgstr "" -#: ../actions/userrss.php:70 actions/userrss.php:67 actions/userrss.php:72 -#: actions/userrss.php:93 -#, php-format -msgid "Microblog by %s" +#: actions/emailsettings.php:412 +msgid "That is not your email address." msgstr "" -#: ../actions/smssettings.php:304 actions/smssettings.php:464 -#: actions/smssettings.php:476 -#, php-format -msgid "" -"Mobile carrier for your phone. If you know a carrier that accepts SMS over " -"email but isn't listed here, send email to let us know at %s." +#: actions/emailsettings.php:431 actions/imsettings.php:408 +#: actions/smssettings.php:425 +msgid "The address was removed." msgstr "" -#: ../actions/finishopenidlogin.php:79 ../actions/register.php:188 -#: actions/finishopenidlogin.php:85 actions/register.php:202 -#: actions/finishopenidlogin.php:107 actions/register.php:429 -#: actions/register.php:430 actions/finishopenidlogin.php:106 -#: actions/register.php:477 actions/register.php:487 actions/register.php:493 -msgid "My text and files are available under " +#: actions/emailsettings.php:445 actions/smssettings.php:518 +msgid "No incoming email address." msgstr "" -#: ../actions/emailsettings.php:82 ../actions/smssettings.php:91 -#: actions/emailsettings.php:83 actions/smssettings.php:91 -#: actions/emailsettings.php:142 actions/smssettings.php:152 -#: actions/emailsettings.php:148 actions/smssettings.php:164 -msgid "New" +#: actions/emailsettings.php:455 actions/emailsettings.php:477 +#: actions/smssettings.php:528 actions/smssettings.php:552 +msgid "Couldn't update user record." msgstr "" -#: ../lib/mail.php:144 lib/mail.php:144 lib/mail.php:286 lib/mail.php:285 -#, php-format -msgid "New email address for posting to %s" +#: actions/emailsettings.php:458 actions/smssettings.php:531 +msgid "Incoming email address removed." msgstr "" -#: ../actions/emailsettings.php:297 actions/emailsettings.php:315 -#: actions/emailsettings.php:465 actions/emailsettings.php:472 -#: actions/smssettings.php:542 actions/smssettings.php:543 #: actions/emailsettings.php:480 actions/smssettings.php:555 msgid "New incoming email address added." msgstr "" -#: ../actions/finishopenidlogin.php:71 actions/finishopenidlogin.php:77 -#: actions/finishopenidlogin.php:99 actions/finishopenidlogin.php:98 -msgid "New nickname" +#: actions/favorited.php:65 lib/popularnoticesection.php:87 +#: lib/publicgroupnav.php:93 +msgid "Popular notices" msgstr "" -#: ../actions/newnotice.php:87 actions/newnotice.php:96 -#: actions/newnotice.php:68 actions/newnotice.php:69 -msgid "New notice" +#: actions/favorited.php:67 +#, php-format +msgid "Popular notices, page %d" msgstr "" -#: ../actions/password.php:41 ../actions/recoverpassword.php:179 -#: actions/profilesettings.php:180 actions/recoverpassword.php:185 -#: actions/passwordsettings.php:101 actions/recoverpassword.php:219 -#: actions/recoverpassword.php:232 actions/passwordsettings.php:107 -#: actions/recoverpassword.php:235 -msgid "New password" +#: actions/favorited.php:79 +msgid "The most popular notices on the site right now." msgstr "" -#: ../actions/recoverpassword.php:314 actions/recoverpassword.php:361 -#: actions/recoverpassword.php:379 actions/recoverpassword.php:382 -msgid "New password successfully saved. You are now logged in." +#: actions/favorited.php:150 +msgid "Favorite notices appear on this page but no one has favorited one yet." msgstr "" -#: ../actions/login.php:101 ../actions/profilesettings.php:41 -#: ../actions/register.php:151 actions/login.php:101 -#: actions/profilesettings.php:74 actions/register.php:165 -#: actions/login.php:228 actions/profilesettings.php:98 -#: actions/register.php:367 actions/showgroup.php:224 -#: actions/showstream.php:251 actions/tagother.php:95 -#: lib/facebookaction.php:308 lib/groupeditform.php:137 actions/login.php:211 -#: actions/showgroup.php:226 actions/showstream.php:244 -#: actions/tagother.php:94 lib/facebookaction.php:312 actions/register.php:413 -#: actions/showgroup.php:231 actions/showstream.php:209 -#: lib/facebookaction.php:314 lib/groupeditform.php:152 actions/login.php:219 -#: actions/profilesettings.php:106 actions/register.php:417 -#: actions/showgroup.php:236 actions/showstream.php:249 actions/login.php:246 -#: actions/register.php:423 lib/userprofile.php:131 -msgid "Nickname" +#: actions/favorited.php:153 +msgid "" +"Be the first to add a notice to your favorites by clicking the fave button " +"next to any notice you like." msgstr "" -#: ../actions/finishopenidlogin.php:175 ../actions/profilesettings.php:110 -#: ../actions/register.php:69 actions/finishopenidlogin.php:181 -#: actions/profilesettings.php:225 actions/register.php:76 -#: actions/editgroup.php:183 actions/finishopenidlogin.php:215 -#: actions/newgroup.php:134 actions/profilesettings.php:214 -#: actions/register.php:159 actions/editgroup.php:185 -#: actions/finishopenidlogin.php:231 actions/newgroup.php:135 -#: actions/profilesettings.php:215 actions/register.php:196 -#: actions/apigroupcreate.php:221 actions/editgroup.php:186 -#: actions/newgroup.php:130 actions/profilesettings.php:231 -#: actions/register.php:202 actions/register.php:208 -msgid "Nickname already in use. Try another one." +#: actions/favorited.php:156 +#, php-format +msgid "" +"Why not [register an account](%%action.register%%) and be the first to add a " +"notice to your favorites!" msgstr "" -#: ../actions/finishopenidlogin.php:165 ../actions/profilesettings.php:88 -#: ../actions/register.php:67 ../actions/updateprofile.php:77 -#: actions/finishopenidlogin.php:171 actions/profilesettings.php:203 -#: actions/register.php:74 actions/updateprofile.php:78 -#: actions/finishopenidlogin.php:205 actions/profilesettings.php:192 -#: actions/updateprofile.php:81 actions/editgroup.php:179 -#: actions/newgroup.php:130 actions/register.php:156 -#: actions/updateprofile.php:83 actions/editgroup.php:181 -#: actions/finishopenidlogin.php:221 actions/newgroup.php:131 -#: actions/profilesettings.php:193 actions/register.php:193 -#: actions/apigroupcreate.php:212 actions/editgroup.php:182 -#: actions/newgroup.php:126 actions/profilesettings.php:208 -#: actions/register.php:199 actions/register.php:205 -msgid "Nickname must have only lowercase letters and numbers and no spaces." +#: actions/favoritesrss.php:111 actions/showfavorites.php:77 +#: lib/personalgroupnav.php:115 +#, php-format +msgid "%s's favorite notices" msgstr "" -#: ../actions/finishopenidlogin.php:170 actions/finishopenidlogin.php:176 -#: actions/finishopenidlogin.php:210 actions/finishopenidlogin.php:226 -msgid "Nickname not allowed." +#: actions/favoritesrss.php:115 +#, php-format +msgid "Updates favored by %1$s on %2$s!" msgstr "" -#: ../actions/remotesubscribe.php:72 actions/remotesubscribe.php:81 -#: actions/remotesubscribe.php:106 actions/remotesubscribe.php:130 -msgid "Nickname of the user you want to follow" +#: actions/favor.php:79 +msgid "This notice is already a favorite!" msgstr "" -#: ../actions/recoverpassword.php:162 actions/recoverpassword.php:167 -#: actions/recoverpassword.php:186 actions/recoverpassword.php:191 -msgid "Nickname or email" +#: actions/favor.php:92 lib/disfavorform.php:140 +msgid "Disfavor favorite" msgstr "" -#: ../actions/deletenotice.php:59 actions/deletenotice.php:60 -#: actions/block.php:147 actions/deletenotice.php:118 -#: actions/deletenotice.php:116 actions/block.php:149 -#: actions/deletenotice.php:115 actions/groupblock.php:176 -#: actions/deletenotice.php:145 -msgid "No" +#: actions/featured.php:69 lib/featureduserssection.php:87 +#: lib/publicgroupnav.php:89 +msgid "Featured users" msgstr "" -#: ../actions/imsettings.php:156 actions/imsettings.php:164 -#: actions/imsettings.php:279 actions/imsettings.php:285 -msgid "No Jabber ID." +#: actions/featured.php:71 +#, php-format +msgid "Featured users, page %d" msgstr "" -#: ../actions/userauthorization.php:129 actions/userauthorization.php:136 -#: actions/userauthorization.php:153 actions/userauthorization.php:192 -#: actions/userauthorization.php:225 -msgid "No authorization request!" +#: actions/featured.php:99 +#, php-format +msgid "A selection of some of the great users on %s" msgstr "" -#: ../actions/smssettings.php:181 actions/smssettings.php:189 -#: actions/smssettings.php:299 actions/smssettings.php:311 -msgid "No carrier selected." +#: actions/file.php:34 +msgid "No notice id" msgstr "" -#: ../actions/smssettings.php:316 actions/smssettings.php:324 -#: actions/smssettings.php:486 actions/smssettings.php:498 -msgid "No code entered" +#: actions/file.php:38 +msgid "No notice" msgstr "" -#: ../actions/confirmaddress.php:33 actions/confirmaddress.php:33 -#: actions/confirmaddress.php:75 -msgid "No confirmation code." +#: actions/file.php:42 +msgid "No attachments" msgstr "" -#: ../actions/newnotice.php:44 actions/newmessage.php:53 -#: actions/newnotice.php:44 classes/Command.php:197 actions/newmessage.php:109 -#: actions/newnotice.php:126 classes/Command.php:223 -#: actions/newmessage.php:142 actions/newnotice.php:131 lib/command.php:223 -#: actions/newnotice.php:162 lib/command.php:216 actions/newmessage.php:144 -#: actions/newnotice.php:136 lib/command.php:351 lib/command.php:424 -msgid "No content!" +#: actions/file.php:51 +msgid "No uploaded attachments" msgstr "" -#: ../actions/emailsettings.php:174 actions/emailsettings.php:192 -#: actions/emailsettings.php:304 actions/emailsettings.php:311 -#: actions/emailsettings.php:319 -msgid "No email address." +#: actions/finishremotesubscribe.php:69 +msgid "Not expecting this response!" msgstr "" -#: ../actions/userbyid.php:32 actions/userbyid.php:32 actions/userbyid.php:70 -msgid "No id." +#: actions/finishremotesubscribe.php:80 +msgid "User being listened to does not exist." msgstr "" -#: ../actions/emailsettings.php:271 actions/emailsettings.php:289 -#: actions/emailsettings.php:430 actions/emailsettings.php:437 -#: actions/smssettings.php:505 actions/smssettings.php:506 -#: actions/emailsettings.php:445 actions/smssettings.php:518 -msgid "No incoming email address." +#: actions/finishremotesubscribe.php:87 actions/remotesubscribe.php:59 +msgid "You can use the local subscription!" msgstr "" -#: ../actions/finishremotesubscribe.php:65 -#: actions/finishremotesubscribe.php:67 actions/finishremotesubscribe.php:68 -msgid "No nickname provided by remote server." +#: actions/finishremotesubscribe.php:96 +msgid "That user has blocked you from subscribing." msgstr "" -#: ../actions/avatarbynickname.php:27 actions/avatarbynickname.php:27 -#: actions/avatarbynickname.php:59 actions/leavegroup.php:81 -#: actions/leavegroup.php:76 -msgid "No nickname." -msgstr "" +#: actions/finishremotesubscribe.php:106 +msgid "You are not authorized." +msgstr "" -#: ../actions/emailsettings.php:222 ../actions/imsettings.php:206 -#: ../actions/smssettings.php:229 actions/emailsettings.php:240 -#: actions/imsettings.php:214 actions/smssettings.php:237 -#: actions/emailsettings.php:363 actions/imsettings.php:345 -#: actions/smssettings.php:358 actions/emailsettings.php:370 -#: actions/emailsettings.php:378 actions/imsettings.php:351 -#: actions/smssettings.php:370 -msgid "No pending confirmation to cancel." +#: actions/finishremotesubscribe.php:109 +msgid "Could not convert request token to access token." msgstr "" -#: ../actions/smssettings.php:176 actions/smssettings.php:184 -#: actions/smssettings.php:294 actions/smssettings.php:306 -msgid "No phone number." +#: actions/finishremotesubscribe.php:114 +msgid "Remote service uses unknown version of OMB protocol." msgstr "" -#: ../actions/finishremotesubscribe.php:72 -#: actions/finishremotesubscribe.php:74 actions/finishremotesubscribe.php:75 -msgid "No profile URL returned by server." +#: actions/finishremotesubscribe.php:133 lib/oauthstore.php:306 +msgid "Error updating remote profile" msgstr "" -#: ../actions/recoverpassword.php:226 actions/recoverpassword.php:232 -#: actions/recoverpassword.php:266 actions/recoverpassword.php:284 -#: actions/recoverpassword.php:287 -msgid "No registered email address for that user." +#: actions/foafgroup.php:44 actions/foafgroup.php:62 actions/groupblock.php:86 +#: actions/groupunblock.php:86 actions/leavegroup.php:83 +#: actions/makeadmin.php:86 lib/command.php:212 lib/command.php:263 +msgid "No such group." msgstr "" -#: ../actions/userauthorization.php:49 actions/userauthorization.php:55 -#: actions/userauthorization.php:57 -msgid "No request found!" +#: actions/getfile.php:75 +msgid "No such file." msgstr "" -#: ../actions/noticesearch.php:64 ../actions/peoplesearch.php:64 -#: actions/noticesearch.php:69 actions/peoplesearch.php:69 -#: actions/groupsearch.php:81 actions/noticesearch.php:104 -#: actions/peoplesearch.php:85 actions/noticesearch.php:117 -msgid "No results" +#: actions/getfile.php:79 +msgid "Cannot read file." msgstr "" -#: ../actions/avatarbynickname.php:32 actions/avatarbynickname.php:32 -#: actions/avatarbynickname.php:64 -msgid "No size." +#: actions/groupblock.php:81 actions/groupunblock.php:81 +#: actions/makeadmin.php:81 +msgid "No group specified." msgstr "" -#: ../actions/twitapistatuses.php:595 actions/twitapifavorites.php:136 -#: actions/twitapistatuses.php:520 actions/twitapifavorites.php:112 -#: actions/twitapistatuses.php:446 actions/twitapifavorites.php:118 -#: actions/twitapistatuses.php:470 actions/twitapifavorites.php:169 -#: actions/twitapistatuses.php:426 actions/apifavoritecreate.php:108 -#: actions/apifavoritedestroy.php:109 actions/apistatusesdestroy.php:113 -msgid "No status found with that ID." +#: actions/groupblock.php:91 +msgid "Only an admin can block group members." msgstr "" -#: ../actions/twitapistatuses.php:555 actions/twitapistatuses.php:478 -#: actions/twitapistatuses.php:418 actions/twitapistatuses.php:442 -#: actions/twitapistatuses.php:399 actions/apistatusesshow.php:144 -msgid "No status with that ID found." +#: actions/groupblock.php:95 +msgid "User is already blocked from group." msgstr "" -#: ../actions/openidsettings.php:135 actions/openidsettings.php:144 -#: actions/openidsettings.php:222 -msgid "No such OpenID." +#: actions/groupblock.php:100 +msgid "User is not a member of group." msgstr "" -#: ../actions/doc.php:29 actions/doc.php:29 actions/doc.php:64 -#: actions/doc.php:69 -msgid "No such document." +#: actions/groupblock.php:136 actions/groupmembers.php:314 +msgid "Block user from group" msgstr "" -#: ../actions/shownotice.php:32 ../actions/shownotice.php:83 -#: ../lib/deleteaction.php:30 actions/shownotice.php:32 -#: actions/shownotice.php:83 lib/deleteaction.php:30 actions/shownotice.php:87 -#: lib/deleteaction.php:51 actions/deletenotice.php:52 -#: actions/shownotice.php:92 -msgid "No such notice." +#: actions/groupblock.php:155 +#, php-format +msgid "" +"Are you sure you want to block user \"%s\" from the group \"%s\"? They will " +"be removed from the group, unable to post, and unable to subscribe to the " +"group in the future." msgstr "" -#: ../actions/recoverpassword.php:56 actions/recoverpassword.php:56 -#: actions/recoverpassword.php:62 -msgid "No such recovery code." +#: actions/groupblock.php:193 +msgid "Database error blocking user from group." msgstr "" -#: ../actions/postnotice.php:56 actions/postnotice.php:57 -#: actions/postnotice.php:60 -msgid "No such subscription" -msgstr "" - -#: ../actions/all.php:34 ../actions/allrss.php:35 -#: ../actions/avatarbynickname.php:43 ../actions/foaf.php:40 -#: ../actions/remotesubscribe.php:84 ../actions/remotesubscribe.php:91 -#: ../actions/replies.php:57 ../actions/repliesrss.php:35 -#: ../actions/showstream.php:110 ../actions/userbyid.php:36 -#: ../actions/userrss.php:35 ../actions/xrds.php:35 ../lib/gallery.php:57 -#: ../lib/subs.php:33 ../lib/subs.php:82 actions/all.php:34 -#: actions/allrss.php:35 actions/avatarbynickname.php:43 -#: actions/favoritesrss.php:35 actions/foaf.php:40 actions/ical.php:31 -#: actions/remotesubscribe.php:93 actions/remotesubscribe.php:100 -#: actions/replies.php:57 actions/repliesrss.php:35 -#: actions/showfavorites.php:34 actions/showstream.php:110 -#: actions/userbyid.php:36 actions/userrss.php:35 actions/xrds.php:35 -#: classes/Command.php:120 classes/Command.php:162 classes/Command.php:203 -#: classes/Command.php:237 lib/gallery.php:62 lib/mailbox.php:36 -#: lib/subs.php:33 lib/subs.php:95 actions/all.php:53 actions/allrss.php:66 -#: actions/avatarbynickname.php:75 actions/favoritesrss.php:64 -#: actions/foaf.php:41 actions/remotesubscribe.php:123 -#: actions/remotesubscribe.php:130 actions/replies.php:73 -#: actions/repliesrss.php:38 actions/showfavorites.php:105 -#: actions/showstream.php:100 actions/userbyid.php:74 -#: actions/usergroups.php:92 actions/userrss.php:38 actions/xrds.php:73 -#: classes/Command.php:140 classes/Command.php:185 classes/Command.php:234 -#: classes/Command.php:271 lib/galleryaction.php:60 lib/mailbox.php:82 -#: lib/subs.php:34 lib/subs.php:109 actions/all.php:56 actions/allrss.php:68 -#: actions/favoritesrss.php:74 lib/command.php:140 lib/command.php:185 -#: lib/command.php:234 lib/command.php:271 lib/mailbox.php:84 -#: actions/all.php:38 actions/foaf.php:58 actions/replies.php:72 -#: actions/usergroups.php:91 actions/userrss.php:39 lib/command.php:133 -#: lib/command.php:178 lib/command.php:227 lib/command.php:264 -#: lib/galleryaction.php:59 lib/profileaction.php:77 lib/subs.php:112 -#: actions/all.php:74 actions/remotesubscribe.php:145 actions/xrds.php:71 -#: lib/command.php:163 lib/command.php:311 lib/command.php:364 -#: lib/command.php:411 lib/command.php:466 -msgid "No such user." +#: actions/groupbyid.php:74 +msgid "No ID" msgstr "" -#: ../actions/recoverpassword.php:211 actions/recoverpassword.php:217 -#: actions/recoverpassword.php:251 actions/recoverpassword.php:269 -#: actions/recoverpassword.php:272 -msgid "No user with that email address or username." +#: actions/groupdesignsettings.php:68 +msgid "You must be logged in to edit a group." msgstr "" -#: ../lib/gallery.php:80 lib/gallery.php:85 -msgid "Nobody to show!" +#: actions/groupdesignsettings.php:141 +msgid "Group design" msgstr "" -#: ../actions/recoverpassword.php:60 actions/recoverpassword.php:60 -#: actions/recoverpassword.php:66 -msgid "Not a recovery code." +#: actions/groupdesignsettings.php:152 +msgid "" +"Customize the way your group looks with a background image and a colour " +"palette of your choice." msgstr "" -#: ../scripts/maildaemon.php:50 scripts/maildaemon.php:50 -#: scripts/maildaemon.php:53 scripts/maildaemon.php:52 -msgid "Not a registered user." +#: actions/groupdesignsettings.php:262 actions/userdesignsettings.php:186 +#: lib/designsettings.php:434 lib/designsettings.php:464 +msgid "Couldn't update your design." msgstr "" -#: ../lib/twitterapi.php:226 ../lib/twitterapi.php:247 -#: ../lib/twitterapi.php:332 lib/twitterapi.php:391 lib/twitterapi.php:418 -#: lib/twitterapi.php:502 lib/twitterapi.php:448 lib/twitterapi.php:476 -#: lib/twitterapi.php:566 lib/twitterapi.php:483 lib/twitterapi.php:511 -#: lib/twitterapi.php:601 lib/twitterapi.php:620 lib/twitterapi.php:648 -#: lib/twitterapi.php:741 actions/oembed.php:181 actions/oembed.php:200 -#: lib/api.php:954 lib/api.php:982 lib/api.php:1092 lib/api.php:963 -#: lib/api.php:991 lib/api.php:1101 -msgid "Not a supported data format." +#: actions/groupdesignsettings.php:286 actions/groupdesignsettings.php:296 +#: actions/userdesignsettings.php:210 actions/userdesignsettings.php:220 +#: actions/userdesignsettings.php:263 actions/userdesignsettings.php:273 +msgid "Unable to save your design settings!" msgstr "" -#: ../actions/imsettings.php:167 actions/imsettings.php:175 -#: actions/imsettings.php:290 actions/imsettings.php:296 -msgid "Not a valid Jabber ID" +#: actions/groupdesignsettings.php:307 actions/userdesignsettings.php:231 +msgid "Design preferences saved." msgstr "" -#: ../lib/openid.php:131 lib/openid.php:131 lib/openid.php:140 -#: lib/openid.php:143 -msgid "Not a valid OpenID." +#: actions/grouplogo.php:139 actions/grouplogo.php:192 +msgid "Group logo" msgstr "" -#: ../actions/emailsettings.php:185 actions/emailsettings.php:203 -#: actions/emailsettings.php:315 actions/emailsettings.php:322 -#: actions/emailsettings.php:330 -msgid "Not a valid email address" +#: actions/grouplogo.php:150 +#, php-format +msgid "" +"You can upload a logo image for your group. The maximum file size is %s." msgstr "" -#: ../actions/register.php:63 actions/register.php:70 actions/register.php:152 -#: actions/register.php:189 actions/register.php:195 actions/register.php:201 -msgid "Not a valid email address." +#: actions/grouplogo.php:362 +msgid "Pick a square area of the image to be the logo." msgstr "" -#: ../actions/profilesettings.php:91 ../actions/register.php:71 -#: actions/profilesettings.php:206 actions/register.php:78 -#: actions/editgroup.php:186 actions/newgroup.php:137 -#: actions/profilesettings.php:195 actions/register.php:161 -#: actions/editgroup.php:188 actions/newgroup.php:138 -#: actions/profilesettings.php:196 actions/register.php:198 -#: actions/apigroupcreate.php:228 actions/editgroup.php:189 -#: actions/newgroup.php:133 actions/profilesettings.php:211 -#: actions/register.php:204 actions/register.php:210 -msgid "Not a valid nickname." +#: actions/grouplogo.php:396 +msgid "Logo updated." msgstr "" -#: ../actions/remotesubscribe.php:120 actions/remotesubscribe.php:129 -#: actions/remotesubscribe.php:159 -msgid "Not a valid profile URL (incorrect services)." +#: actions/grouplogo.php:398 +msgid "Failed updating logo." msgstr "" -#: ../actions/remotesubscribe.php:113 actions/remotesubscribe.php:122 -#: actions/remotesubscribe.php:152 -msgid "Not a valid profile URL (no XRDS defined)." +#: actions/groupmembers.php:93 lib/groupnav.php:91 +#, php-format +msgid "%s group members" msgstr "" -#: ../actions/remotesubscribe.php:104 actions/remotesubscribe.php:113 -#: actions/remotesubscribe.php:143 -msgid "Not a valid profile URL (no YADIS document)." +#: actions/groupmembers.php:96 +#, php-format +msgid "%s group members, page %d" msgstr "" -#: ../actions/avatar.php:95 actions/profilesettings.php:332 -#: lib/imagefile.php:87 lib/imagefile.php:90 lib/imagefile.php:91 -#: lib/imagefile.php:96 -msgid "Not an image or corrupt file." +#: actions/groupmembers.php:111 +msgid "A list of the users in this group." msgstr "" -#: ../actions/finishremotesubscribe.php:51 -#: actions/finishremotesubscribe.php:53 actions/finishremotesubscribe.php:54 -msgid "Not authorized." +#: actions/groupmembers.php:175 lib/groupnav.php:106 +msgid "Admin" msgstr "" -#: ../actions/finishremotesubscribe.php:38 -#: actions/finishremotesubscribe.php:38 actions/finishremotesubscribe.php:40 -#: actions/finishremotesubscribe.php:69 -msgid "Not expecting this response!" +#: actions/groupmembers.php:346 lib/blockform.php:153 +msgid "Block" msgstr "" -#: ../actions/twitapistatuses.php:422 actions/twitapistatuses.php:361 -#: actions/twitapistatuses.php:309 actions/twitapistatuses.php:327 -#: actions/twitapistatuses.php:284 actions/apistatusesupdate.php:186 -#: actions/apistatusesupdate.php:193 -msgid "Not found" +#: actions/groupmembers.php:346 lib/blockform.php:123 lib/blockform.php:153 +msgid "Block this user" msgstr "" -#: ../actions/finishaddopenid.php:29 ../actions/logout.php:33 -#: ../actions/newnotice.php:29 ../actions/subscribe.php:28 -#: ../actions/unsubscribe.php:25 ../lib/deleteaction.php:38 -#: ../lib/settingsaction.php:27 actions/disfavor.php:29 actions/favor.php:30 -#: actions/finishaddopenid.php:29 actions/logout.php:33 -#: actions/newmessage.php:28 actions/newnotice.php:29 actions/subscribe.php:28 -#: actions/unsubscribe.php:25 lib/deleteaction.php:38 -#: lib/settingsaction.php:27 actions/block.php:59 actions/disfavor.php:61 -#: actions/favor.php:64 actions/finishaddopenid.php:67 actions/logout.php:71 -#: actions/newmessage.php:83 actions/newnotice.php:90 actions/nudge.php:63 -#: actions/subedit.php:31 actions/subscribe.php:30 actions/unblock.php:60 -#: actions/unsubscribe.php:27 lib/deleteaction.php:66 -#: lib/settingsaction.php:72 actions/newmessage.php:87 actions/favor.php:62 -#: actions/groupblock.php:61 actions/groupunblock.php:61 -#: actions/makeadmin.php:61 actions/newnotice.php:88 -#: actions/deletenotice.php:67 actions/logout.php:69 actions/newnotice.php:89 -#: actions/unsubscribe.php:52 -msgid "Not logged in." +#: actions/groupmembers.php:441 +msgid "Make user an admin of the group" msgstr "" -#: ../lib/subs.php:91 lib/subs.php:104 lib/subs.php:122 lib/subs.php:124 -msgid "Not subscribed!." +#: actions/groupmembers.php:473 +msgid "Make Admin" msgstr "" -#: ../actions/opensearch.php:35 actions/opensearch.php:35 -#: actions/opensearch.php:67 -msgid "Notice Search" +#: actions/groupmembers.php:473 +msgid "Make this user an admin" +msgstr "" + +#: actions/grouprss.php:133 +#, php-format +msgid "Updates from members of %1$s on %2$s!" msgstr "" -#: ../actions/showstream.php:82 actions/showstream.php:82 -#: actions/showstream.php:180 actions/showstream.php:187 -#: actions/showstream.php:192 +#: actions/groupsearch.php:52 #, php-format -msgid "Notice feed for %s" +msgid "" +"Search for groups on %%site.name%% by their name, location, or description. " +"Separate the terms by spaces; they must be 3 characters or more." msgstr "" -#: ../actions/shownotice.php:39 actions/shownotice.php:39 -#: actions/shownotice.php:94 actions/oembed.php:79 actions/shownotice.php:100 -msgid "Notice has no profile" +#: actions/groupsearch.php:58 +msgid "Group search" msgstr "" -#: ../actions/showstream.php:316 actions/showstream.php:331 -#: actions/showstream.php:504 lib/facebookaction.php:477 lib/mailbox.php:116 -#: lib/noticelist.php:87 lib/facebookaction.php:581 lib/mailbox.php:118 -#: actions/conversation.php:149 lib/facebookaction.php:572 -#: lib/profileaction.php:206 actions/conversation.php:154 -msgid "Notices" +#: actions/groupsearch.php:79 actions/noticesearch.php:117 +#: actions/peoplesearch.php:83 +msgid "No results." msgstr "" -#: ../actions/tag.php:35 ../actions/tag.php:81 actions/tag.php:35 -#: actions/tag.php:81 actions/tag.php:41 actions/tag.php:49 actions/tag.php:57 -#: actions/twitapitags.php:69 actions/apitimelinetag.php:101 -#: actions/tag.php:66 +#: actions/groupsearch.php:82 #, php-format -msgid "Notices tagged with %s" +msgid "" +"If you can't find the group you're looking for, you can [create it](%%action." +"newgroup%%) yourself." msgstr "" -#: ../actions/password.php:39 actions/profilesettings.php:178 -#: actions/passwordsettings.php:97 actions/passwordsettings.php:103 -msgid "Old password" +#: actions/groupsearch.php:85 +#, php-format +msgid "" +"Why not [register an account](%%action.register%%) and [create the group](%%" +"action.newgroup%%) yourself!" msgstr "" -#: ../lib/settingsaction.php:96 ../lib/util.php:314 lib/settingsaction.php:90 -#: lib/util.php:330 lib/accountsettingsaction.php:116 lib/action.php:341 -#: lib/logingroupnav.php:81 lib/action.php:418 -msgid "OpenID" +#: actions/groups.php:62 lib/profileaction.php:220 lib/publicgroupnav.php:81 +#: lib/subgroupnav.php:98 +msgid "Groups" msgstr "" -#: ../actions/finishopenidlogin.php:61 actions/finishopenidlogin.php:66 -#: actions/finishopenidlogin.php:73 actions/finishopenidlogin.php:72 -msgid "OpenID Account Setup" +#: actions/groups.php:64 +#, php-format +msgid "Groups, page %d" msgstr "" -#: ../lib/openid.php:180 lib/openid.php:180 lib/openid.php:266 -#: lib/openid.php:269 -msgid "OpenID Auto-Submit" +#: actions/groups.php:90 +#, php-format +msgid "" +"%%%%site.name%%%% groups let you find and talk with users of similar " +"interests. After you join a group you can send messages to all other members " +"using the syntax \"!groupname\". Are you not seeing any groups you like? Try " +"[searching for one](%%%%action.groupsearch%%%%) or [start your own](%%%%" +"action.newgroup%%%%)!" msgstr "" -#: ../actions/finishaddopenid.php:99 ../actions/finishopenidlogin.php:140 -#: ../actions/openidlogin.php:60 actions/finishaddopenid.php:99 -#: actions/finishopenidlogin.php:146 actions/openidlogin.php:68 -#: actions/finishaddopenid.php:170 actions/openidlogin.php:80 -#: actions/openidlogin.php:89 -msgid "OpenID Login" +#: actions/groups.php:108 actions/usergroups.php:124 lib/groupeditform.php:122 +msgid "Create a new group" msgstr "" -#: ../actions/openidlogin.php:65 ../actions/openidsettings.php:49 -#: actions/openidlogin.php:74 actions/openidsettings.php:50 -#: actions/openidlogin.php:102 actions/openidsettings.php:101 -#: actions/openidlogin.php:111 -msgid "OpenID URL" +#: actions/groupunblock.php:91 +msgid "Only an admin can unblock group members." msgstr "" -#: ../actions/finishaddopenid.php:42 ../actions/finishopenidlogin.php:103 -#: actions/finishaddopenid.php:42 actions/finishopenidlogin.php:109 -#: actions/finishaddopenid.php:88 actions/finishopenidlogin.php:130 -#: actions/finishopenidlogin.php:129 -msgid "OpenID authentication cancelled." +#: actions/groupunblock.php:95 +msgid "User is not blocked from group." msgstr "" -#: ../actions/finishaddopenid.php:46 ../actions/finishopenidlogin.php:107 -#: actions/finishaddopenid.php:46 actions/finishopenidlogin.php:113 -#: actions/finishaddopenid.php:92 actions/finishopenidlogin.php:134 -#: actions/finishopenidlogin.php:133 -#, php-format -msgid "OpenID authentication failed: %s" +#: actions/groupunblock.php:128 actions/unblock.php:108 +msgid "Error removing the block." msgstr "" -#: ../lib/openid.php:133 lib/openid.php:133 lib/openid.php:142 -#: lib/openid.php:145 -#, php-format -msgid "OpenID failure: %s" +#: actions/imsettings.php:59 +msgid "IM Settings" msgstr "" -#: ../actions/openidsettings.php:144 actions/openidsettings.php:153 -#: actions/openidsettings.php:231 -msgid "OpenID removed." +#: actions/imsettings.php:70 +#, php-format +msgid "" +"You can send and receive notices through Jabber/GTalk [instant messages](%%" +"doc.im%%). Configure your instant messages address and settings below." msgstr "" -#: ../actions/openidsettings.php:37 actions/openidsettings.php:37 -#: actions/openidsettings.php:59 -msgid "OpenID settings" +#: actions/imsettings.php:89 +msgid "IM is not available." msgstr "" -#: ../actions/invite.php:135 actions/invite.php:143 actions/invite.php:180 -#: actions/invite.php:186 actions/invite.php:188 actions/invite.php:194 -msgid "Optionally add a personal message to the invitation." +#: actions/imsettings.php:100 +msgid "IM address" msgstr "" -#: ../actions/avatar.php:84 actions/profilesettings.php:321 -#: lib/imagefile.php:75 lib/imagefile.php:79 lib/imagefile.php:80 -msgid "Partial upload." +#: actions/imsettings.php:106 +msgid "Current confirmed Jabber/GTalk address." msgstr "" -#: ../actions/finishopenidlogin.php:90 ../actions/login.php:102 -#: ../actions/register.php:153 ../lib/settingsaction.php:93 -#: actions/finishopenidlogin.php:96 actions/login.php:102 -#: actions/register.php:167 actions/finishopenidlogin.php:118 -#: actions/login.php:231 actions/register.php:372 -#: lib/accountsettingsaction.php:110 lib/facebookaction.php:311 -#: actions/login.php:214 lib/facebookaction.php:315 -#: actions/finishopenidlogin.php:117 actions/register.php:418 -#: lib/facebookaction.php:317 actions/login.php:222 actions/register.php:422 -#: lib/accountsettingsaction.php:114 actions/login.php:249 -#: actions/register.php:428 -msgid "Password" +#: actions/imsettings.php:114 +#, php-format +msgid "" +"Awaiting confirmation on this IM address. Check your Jabber/GTalk account " +"for a message with further instructions. (Did you add %s to your buddy list?)" msgstr "" -#: ../actions/recoverpassword.php:288 actions/recoverpassword.php:301 -#: actions/recoverpassword.php:335 actions/recoverpassword.php:353 -#: actions/recoverpassword.php:356 -msgid "Password and confirmation do not match." +#: actions/imsettings.php:124 +msgid "IM Address" msgstr "" -#: ../actions/recoverpassword.php:284 actions/recoverpassword.php:297 -#: actions/recoverpassword.php:331 actions/recoverpassword.php:349 -#: actions/recoverpassword.php:352 -msgid "Password must be 6 chars or more." +#: actions/imsettings.php:126 +#, php-format +msgid "" +"Jabber or GTalk address, like \"UserName@example.org\". First, make sure to " +"add %s to your buddy list in your IM client or on GTalk." msgstr "" -#: ../actions/recoverpassword.php:261 ../actions/recoverpassword.php:263 -#: actions/recoverpassword.php:267 actions/recoverpassword.php:269 -#: actions/recoverpassword.php:199 actions/recoverpassword.php:301 -#: actions/recoverpassword.php:207 actions/recoverpassword.php:319 -#: actions/recoverpassword.php:210 actions/recoverpassword.php:322 -msgid "Password recovery requested" +#: actions/imsettings.php:143 +msgid "Send me notices through Jabber/GTalk." msgstr "" -#: ../actions/password.php:89 ../actions/recoverpassword.php:313 -#: actions/profilesettings.php:408 actions/recoverpassword.php:326 -#: actions/passwordsettings.php:173 actions/recoverpassword.php:200 -#: actions/passwordsettings.php:178 actions/recoverpassword.php:208 -#: actions/passwordsettings.php:184 actions/recoverpassword.php:211 -#: actions/passwordsettings.php:191 -msgid "Password saved." +#: actions/imsettings.php:148 +msgid "Post a notice when my Jabber/GTalk status changes." msgstr "" -#: ../actions/password.php:61 ../actions/register.php:88 -#: actions/profilesettings.php:380 actions/register.php:98 -#: actions/passwordsettings.php:145 actions/register.php:183 -#: actions/passwordsettings.php:150 actions/register.php:220 -#: actions/passwordsettings.php:156 actions/register.php:227 -#: actions/register.php:233 -msgid "Passwords don't match." +#: actions/imsettings.php:153 +msgid "Send me replies through Jabber/GTalk from users I am not subscribed to." msgstr "" -#: ../lib/searchaction.php:100 lib/searchaction.php:100 -#: lib/searchgroupnav.php:80 -msgid "People" +#: actions/imsettings.php:159 +msgid "Publish a MicroID for my Jabber/GTalk address." msgstr "" -#: ../actions/opensearch.php:33 actions/opensearch.php:33 -#: actions/opensearch.php:64 -msgid "People Search" +#: actions/imsettings.php:285 +msgid "No Jabber ID." msgstr "" -#: ../actions/peoplesearch.php:33 actions/peoplesearch.php:33 -#: actions/peoplesearch.php:58 -msgid "People search" +#: actions/imsettings.php:292 +msgid "Cannot normalize that Jabber ID" msgstr "" -#: ../lib/stream.php:50 lib/personal.php:50 lib/personalgroupnav.php:98 -#: lib/personalgroupnav.php:99 -msgid "Personal" +#: actions/imsettings.php:296 +msgid "Not a valid Jabber ID" msgstr "" -#: ../actions/invite.php:133 actions/invite.php:141 actions/invite.php:178 -#: actions/invite.php:184 actions/invite.php:186 actions/invite.php:192 -msgid "Personal message" +#: actions/imsettings.php:299 +msgid "That is already your Jabber ID." msgstr "" -#: ../actions/smssettings.php:69 actions/smssettings.php:69 -#: actions/smssettings.php:128 actions/smssettings.php:140 -msgid "Phone number, no punctuation or spaces, with area code" +#: actions/imsettings.php:302 +msgid "Jabber ID already belongs to another user." msgstr "" -#: ../actions/userauthorization.php:78 +#: actions/imsettings.php:327 +#, php-format msgid "" -"Please check these details to make sure that you want to subscribe to this " -"user's notices. If you didn't just ask to subscribe to someone's notices, " -"click \"Cancel\"." +"A confirmation code was sent to the IM address you added. You must approve %" +"s for sending messages to you." msgstr "" -#: ../actions/imsettings.php:73 actions/imsettings.php:74 -#: actions/imsettings.php:142 actions/imsettings.php:148 -msgid "Post a notice when my Jabber/GTalk status changes." +#: actions/imsettings.php:387 +msgid "That is not your Jabber ID." msgstr "" -#: ../actions/emailsettings.php:85 ../actions/imsettings.php:67 -#: ../actions/smssettings.php:94 actions/emailsettings.php:86 -#: actions/imsettings.php:68 actions/smssettings.php:94 -#: actions/twittersettings.php:70 actions/emailsettings.php:147 -#: actions/imsettings.php:133 actions/smssettings.php:157 -#: actions/twittersettings.php:134 actions/twittersettings.php:137 -#: actions/emailsettings.php:153 actions/imsettings.php:139 -#: actions/smssettings.php:169 -msgid "Preferences" +#: actions/inbox.php:59 +#, php-format +msgid "Inbox for %s - page %d" msgstr "" -#: ../actions/emailsettings.php:162 ../actions/imsettings.php:144 -#: ../actions/smssettings.php:163 actions/emailsettings.php:180 -#: actions/imsettings.php:152 actions/smssettings.php:171 -#: actions/emailsettings.php:286 actions/imsettings.php:258 -#: actions/othersettings.php:168 actions/smssettings.php:272 -#: actions/emailsettings.php:293 actions/othersettings.php:173 -#: actions/emailsettings.php:301 actions/imsettings.php:264 -#: actions/othersettings.php:180 actions/smssettings.php:284 -msgid "Preferences saved." +#: actions/inbox.php:62 +#, php-format +msgid "Inbox for %s" msgstr "" -#: ../actions/profilesettings.php:57 actions/profilesettings.php:90 -#: actions/profilesettings.php:129 actions/profilesettings.php:130 -#: actions/profilesettings.php:145 -msgid "Preferred language" +#: actions/inbox.php:115 +msgid "This is your inbox, which lists your incoming private messages." msgstr "" -#: ../lib/util.php:328 lib/util.php:344 lib/action.php:572 lib/action.php:665 -#: lib/action.php:715 lib/action.php:730 -msgid "Privacy" +#: actions/invite.php:39 +msgid "Invites have been disabled." msgstr "" -#: ../classes/Notice.php:95 ../classes/Notice.php:106 classes/Notice.php:109 -#: classes/Notice.php:119 classes/Notice.php:145 classes/Notice.php:155 -#: classes/Notice.php:178 classes/Notice.php:188 classes/Notice.php:206 -#: classes/Notice.php:216 classes/Notice.php:232 classes/Notice.php:268 -#: classes/Notice.php:293 -msgid "Problem saving notice." +#: actions/invite.php:41 +#, php-format +msgid "You must be logged in to invite other users to use %s" msgstr "" -#: ../lib/settingsaction.php:84 ../lib/stream.php:60 lib/personal.php:60 -#: lib/settingsaction.php:84 lib/accountsettingsaction.php:104 -#: lib/personalgroupnav.php:108 lib/personalgroupnav.php:109 -#: lib/accountsettingsaction.php:108 -msgid "Profile" +#: actions/invite.php:72 +#, php-format +msgid "Invalid email address: %s" msgstr "" -#: ../actions/remotesubscribe.php:73 actions/remotesubscribe.php:82 -#: actions/remotesubscribe.php:109 actions/remotesubscribe.php:133 -msgid "Profile URL" +#: actions/invite.php:110 +msgid "Invitation(s) sent" msgstr "" -#: ../actions/profilesettings.php:34 actions/profilesettings.php:32 -#: actions/profilesettings.php:58 actions/profilesettings.php:60 -msgid "Profile settings" +#: actions/invite.php:112 +msgid "Invite new users" msgstr "" -#: ../actions/postnotice.php:51 ../actions/updateprofile.php:52 -#: actions/postnotice.php:52 actions/updateprofile.php:53 -#: actions/postnotice.php:55 actions/updateprofile.php:56 -#: actions/updateprofile.php:58 -msgid "Profile unknown" +#: actions/invite.php:128 +msgid "You are already subscribed to these users:" msgstr "" -#: ../actions/public.php:54 actions/public.php:54 actions/public.php:124 -msgid "Public Stream Feed" +#: actions/invite.php:131 actions/invite.php:139 +#, php-format +msgid "%s (%s)" msgstr "" -#: ../actions/public.php:33 actions/public.php:33 actions/public.php:109 -#: lib/publicgroupnav.php:77 actions/public.php:112 lib/publicgroupnav.php:79 -#: actions/public.php:120 actions/public.php:131 -msgid "Public timeline" +#: actions/invite.php:136 +msgid "These are already users and you were automatically subscribed to them:" msgstr "" -#: ../actions/imsettings.php:79 actions/imsettings.php:80 -#: actions/imsettings.php:153 actions/imsettings.php:159 -msgid "Publish a MicroID for my Jabber/GTalk address." +#: actions/invite.php:144 +msgid "Invitation(s) sent to the following e-mail addresses:" msgstr "" -#: ../actions/emailsettings.php:94 actions/emailsettings.php:101 -#: actions/emailsettings.php:178 actions/emailsettings.php:183 -#: actions/emailsettings.php:191 -msgid "Publish a MicroID for my email address." +#: actions/invite.php:150 +msgid "" +"You will be notified when your invitees accept the invitation and register " +"on the site. Thanks for growing the community!" msgstr "" -#: ../actions/tag.php:75 ../actions/tag.php:76 actions/tag.php:75 -#: actions/tag.php:76 -msgid "Recent Tags" +#: actions/invite.php:162 +msgid "" +"Use this form to invite your friends and colleagues to use this service." msgstr "" -#: ../actions/recoverpassword.php:166 actions/recoverpassword.php:171 -#: actions/recoverpassword.php:190 actions/recoverpassword.php:197 -#: actions/recoverpassword.php:199 actions/recoverpassword.php:200 -msgid "Recover" +#: actions/invite.php:187 +msgid "Email addresses" msgstr "" -#: ../actions/recoverpassword.php:156 actions/recoverpassword.php:161 -#: actions/recoverpassword.php:198 actions/recoverpassword.php:206 -#: actions/recoverpassword.php:209 -msgid "Recover password" +#: actions/invite.php:189 +msgid "Addresses of friends to invite (one per line)" msgstr "" -#: ../actions/recoverpassword.php:67 actions/recoverpassword.php:67 -#: actions/recoverpassword.php:73 -msgid "Recovery code for unknown user." +#: actions/invite.php:192 +msgid "Personal message" msgstr "" -#: ../actions/register.php:142 ../actions/register.php:193 ../lib/util.php:312 -#: actions/register.php:152 actions/register.php:207 lib/util.php:328 -#: actions/register.php:69 actions/register.php:436 lib/action.php:338 -#: lib/facebookaction.php:277 lib/logingroupnav.php:78 -#: actions/register.php:438 lib/action.php:415 lib/facebookaction.php:279 -#: actions/register.php:108 actions/register.php:486 lib/action.php:440 -#: lib/facebookaction.php:281 actions/register.php:496 lib/action.php:450 -#: lib/logingroupnav.php:85 actions/register.php:114 actions/register.php:502 -msgid "Register" +#: actions/invite.php:194 +msgid "Optionally add a personal message to the invitation." msgstr "" -#: ../actions/register.php:28 actions/register.php:28 -#: actions/finishopenidlogin.php:196 actions/register.php:90 -#: actions/finishopenidlogin.php:195 actions/finishopenidlogin.php:204 -#: actions/register.php:129 actions/register.php:135 -msgid "Registration not allowed." +#: actions/invite.php:197 lib/messageform.php:181 lib/noticeform.php:208 +msgid "Send" msgstr "" -#: ../actions/register.php:200 actions/register.php:214 -#: actions/register.php:67 actions/register.php:106 actions/register.php:112 -msgid "Registration successful" +#: actions/invite.php:226 +#, php-format +msgid "%1$s has invited you to join them on %2$s" msgstr "" -#: ../actions/userauthorization.php:120 actions/userauthorization.php:127 -#: actions/userauthorization.php:144 actions/userauthorization.php:179 -#: actions/userauthorization.php:211 -msgid "Reject" +#: actions/invite.php:228 +#, php-format +msgid "" +"%1$s has invited you to join them on %2$s (%3$s).\n" +"\n" +"%2$s is a micro-blogging service that lets you keep up-to-date with those " +"you know and those who interest you.\n" +"\n" +"You can also share news about yourself, your thoughts, or your life online " +"with users who know about you. It is also great for meeting others who share " +"your interests.\n" +"\n" +"%1$s said:\n" +"\n" +"%4$s\n" +"\n" +"You can see %1$s's profile page on %2$s here:\n" +"\n" +"%5$s\n" +"\n" +"If you'd like to try the service, click on the link below to accept the " +"invitation.\n" +"\n" +"%6$s\n" +"\n" +"If not, you can ignore this message. Thanks for your patience and your " +"time.\n" +"\n" +"Sincerely, %2$s\n" msgstr "" -#: ../actions/login.php:103 ../actions/register.php:176 actions/login.php:103 -#: actions/register.php:190 actions/login.php:234 actions/openidlogin.php:107 -#: actions/register.php:414 actions/login.php:217 actions/openidlogin.php:116 -#: actions/register.php:461 actions/login.php:225 actions/register.php:471 -#: actions/login.php:252 actions/register.php:477 -msgid "Remember me" +#: actions/joingroup.php:60 +msgid "You must be logged in to join a group." msgstr "" -#: ../actions/updateprofile.php:70 actions/updateprofile.php:71 -#: actions/updateprofile.php:74 actions/updateprofile.php:76 -msgid "Remote profile with no matching profile" +#: actions/joingroup.php:90 lib/command.php:217 +msgid "You are already a member of that group" msgstr "" -#: ../actions/remotesubscribe.php:65 actions/remotesubscribe.php:73 -#: actions/remotesubscribe.php:88 actions/remotesubscribe.php:112 -msgid "Remote subscribe" +#: actions/joingroup.php:128 lib/command.php:234 +#, php-format +msgid "Could not join user %s to group %s" msgstr "" -#: ../actions/emailsettings.php:47 ../actions/emailsettings.php:75 -#: ../actions/imsettings.php:48 ../actions/openidsettings.php:106 -#: ../actions/smssettings.php:50 ../actions/smssettings.php:84 -#: actions/emailsettings.php:48 actions/emailsettings.php:76 -#: actions/imsettings.php:49 actions/openidsettings.php:108 -#: actions/smssettings.php:50 actions/smssettings.php:84 -#: actions/twittersettings.php:59 actions/emailsettings.php:101 -#: actions/emailsettings.php:134 actions/imsettings.php:102 -#: actions/openidsettings.php:166 actions/smssettings.php:103 -#: actions/smssettings.php:146 actions/twittersettings.php:115 -#: actions/twittersettings.php:118 actions/emailsettings.php:107 -#: actions/emailsettings.php:140 actions/imsettings.php:108 -#: actions/smssettings.php:115 actions/smssettings.php:158 -msgid "Remove" +#: actions/joingroup.php:135 lib/command.php:239 +#, php-format +msgid "%s joined group %s" msgstr "" -#: ../actions/openidsettings.php:68 actions/openidsettings.php:69 -#: actions/openidsettings.php:123 -msgid "Remove OpenID" +#: actions/leavegroup.php:60 +msgid "You must be logged in to leave a group." msgstr "" -#: ../actions/openidsettings.php:73 actions/openidsettings.php:128 -msgid "" -"Removing your only OpenID would make it impossible to log in! If you need to " -"remove it, add another OpenID first." +#: actions/leavegroup.php:90 lib/command.php:268 +msgid "You are not a member of that group." msgstr "" -#: ../lib/stream.php:55 lib/personal.php:55 lib/personalgroupnav.php:103 -#: lib/personalgroupnav.php:104 -msgid "Replies" +#: actions/leavegroup.php:119 lib/command.php:278 +msgid "Could not find membership record." msgstr "" -#: ../actions/replies.php:47 ../actions/repliesrss.php:76 ../lib/stream.php:56 -#: actions/replies.php:47 actions/repliesrss.php:62 lib/personal.php:56 -#: actions/replies.php:116 actions/repliesrss.php:67 -#: lib/personalgroupnav.php:104 actions/replies.php:118 -#: actions/replies.php:117 lib/personalgroupnav.php:105 -#: actions/replies.php:125 actions/repliesrss.php:68 +#: actions/leavegroup.php:127 lib/command.php:284 #, php-format -msgid "Replies to %s" +msgid "Could not remove user %s to group %s" msgstr "" -#: ../actions/recoverpassword.php:183 actions/recoverpassword.php:189 -#: actions/recoverpassword.php:223 actions/recoverpassword.php:240 -#: actions/recoverpassword.php:243 -msgid "Reset" +#: actions/leavegroup.php:134 lib/command.php:289 +#, php-format +msgid "%s left group %s" msgstr "" -#: ../actions/recoverpassword.php:173 actions/recoverpassword.php:178 -#: actions/recoverpassword.php:197 actions/recoverpassword.php:205 -#: actions/recoverpassword.php:208 -msgid "Reset password" +#: actions/login.php:79 actions/register.php:137 +msgid "Already logged in." msgstr "" -#: ../lib/settingsaction.php:99 lib/settingsaction.php:93 -#: actions/subscriptions.php:123 lib/connectsettingsaction.php:107 -#: actions/subscriptions.php:125 actions/subscriptions.php:184 -#: actions/subscriptions.php:199 lib/connectsettingsaction.php:115 -msgid "SMS" +#: actions/login.php:110 actions/login.php:120 +msgid "Invalid or expired token." msgstr "" -#: ../actions/smssettings.php:67 actions/smssettings.php:67 -#: actions/smssettings.php:126 actions/smssettings.php:138 -msgid "SMS Phone number" +#: actions/login.php:143 +msgid "Incorrect username or password." msgstr "" -#: ../actions/smssettings.php:33 actions/smssettings.php:33 -#: actions/smssettings.php:58 -msgid "SMS Settings" +#: actions/login.php:149 actions/recoverpassword.php:375 +#: actions/register.php:248 +msgid "Error setting user." msgstr "" -#: ../lib/mail.php:219 lib/mail.php:225 lib/mail.php:437 lib/mail.php:438 -msgid "SMS confirmation" +#: actions/login.php:204 actions/login.php:257 lib/action.php:453 +#: lib/logingroupnav.php:79 +msgid "Login" msgstr "" -#: ../actions/recoverpassword.php:182 actions/recoverpassword.php:188 -#: actions/recoverpassword.php:222 actions/recoverpassword.php:237 -#: actions/recoverpassword.php:240 -msgid "Same as password above" +#: actions/login.php:243 +msgid "Login to site" msgstr "" -#: ../actions/register.php:156 actions/register.php:170 -#: actions/register.php:377 actions/register.php:423 actions/register.php:427 -#: actions/register.php:433 -msgid "Same as password above. Required." +#: actions/login.php:246 actions/profilesettings.php:106 +#: actions/register.php:423 actions/showgroup.php:236 actions/tagother.php:94 +#: lib/groupeditform.php:152 lib/userprofile.php:131 +msgid "Nickname" msgstr "" -#: ../actions/emailsettings.php:97 ../actions/imsettings.php:81 -#: ../actions/profilesettings.php:67 ../actions/smssettings.php:100 -#: actions/emailsettings.php:104 actions/imsettings.php:82 -#: actions/profilesettings.php:101 actions/smssettings.php:100 -#: actions/twittersettings.php:83 actions/emailsettings.php:182 -#: actions/facebooksettings.php:114 actions/imsettings.php:157 -#: actions/othersettings.php:117 actions/profilesettings.php:150 -#: actions/smssettings.php:169 actions/subscriptions.php:124 -#: actions/tagother.php:152 actions/twittersettings.php:161 -#: lib/groupeditform.php:171 actions/emailsettings.php:187 -#: actions/subscriptions.php:126 actions/tagother.php:154 -#: actions/twittersettings.php:164 actions/othersettings.php:119 -#: actions/profilesettings.php:152 actions/subscriptions.php:185 -#: actions/twittersettings.php:180 lib/designsettings.php:256 -#: lib/groupeditform.php:196 actions/emailsettings.php:195 -#: actions/imsettings.php:163 actions/othersettings.php:126 -#: actions/profilesettings.php:167 actions/smssettings.php:181 -#: actions/subscriptions.php:203 lib/groupeditform.php:202 -msgid "Save" +#: actions/login.php:249 actions/register.php:428 +#: lib/accountsettingsaction.php:114 +msgid "Password" msgstr "" -#: ../lib/searchaction.php:84 ../lib/util.php:300 lib/searchaction.php:84 -#: lib/util.php:316 lib/action.php:325 lib/action.php:396 lib/action.php:448 -#: lib/action.php:459 -msgid "Search" +#: actions/login.php:252 actions/register.php:477 +msgid "Remember me" +msgstr "" + +#: actions/login.php:253 actions/register.php:479 +msgid "Automatically login in the future; not for shared computers!" msgstr "" -#: ../actions/noticesearch.php:80 actions/noticesearch.php:85 -#: actions/noticesearch.php:127 -msgid "Search Stream Feed" +#: actions/login.php:263 +msgid "Lost or forgotten password?" msgstr "" -#: ../actions/noticesearch.php:30 actions/noticesearch.php:30 -#: actions/noticesearch.php:57 actions/noticesearch.php:68 -#, php-format +#: actions/login.php:282 msgid "" -"Search for notices on %%site.name%% by their contents. Separate search terms " -"by spaces; they must be 3 characters or more." +"For security reasons, please re-enter your user name and password before " +"changing your settings." msgstr "" -#: ../actions/peoplesearch.php:28 actions/peoplesearch.php:52 +#: actions/login.php:286 #, php-format msgid "" -"Search for people on %%site.name%% by their name, location, or interests. " -"Separate the terms by spaces; they must be 3 characters or more." +"Login with your username and password. Don't have a username yet? [Register]" +"(%%action.register%%) a new account." msgstr "" -#: ../actions/smssettings.php:296 actions/smssettings.php:304 -#: actions/smssettings.php:457 actions/smssettings.php:469 -msgid "Select a carrier" +#: actions/makeadmin.php:91 +msgid "Only an admin can make another user an admin." msgstr "" -#: ../actions/invite.php:137 ../lib/util.php:1172 actions/invite.php:145 -#: lib/util.php:1306 lib/util.php:1731 actions/invite.php:182 -#: lib/messageform.php:167 lib/noticeform.php:177 actions/invite.php:189 -#: lib/messageform.php:165 actions/invite.php:191 lib/messageform.php:157 -#: lib/noticeform.php:179 actions/invite.php:197 lib/messageform.php:181 -#: lib/noticeform.php:208 -msgid "Send" +#: actions/makeadmin.php:95 +#, php-format +msgid "%s is already an admin for group \"%s\"." msgstr "" -#: ../actions/emailsettings.php:73 ../actions/smssettings.php:82 -#: actions/emailsettings.php:74 actions/smssettings.php:82 -#: actions/emailsettings.php:132 actions/smssettings.php:145 -#: actions/emailsettings.php:138 actions/smssettings.php:157 -msgid "Send email to this address to post new notices." +#: actions/makeadmin.php:132 +#, php-format +msgid "Can't get membership record for %s in group %s" msgstr "" -#: ../actions/emailsettings.php:88 actions/emailsettings.php:89 -#: actions/emailsettings.php:152 actions/emailsettings.php:158 -msgid "Send me notices of new subscriptions through email." +#: actions/makeadmin.php:145 +#, php-format +msgid "Can't make %s an admin for group %s" msgstr "" -#: ../actions/imsettings.php:70 actions/imsettings.php:71 -#: actions/imsettings.php:137 actions/imsettings.php:143 -msgid "Send me notices through Jabber/GTalk." +#: actions/microsummary.php:62 actions/newmessage.php:116 +#: actions/remotesubscribe.php:154 +msgid "No such user" msgstr "" -#: ../actions/smssettings.php:97 actions/smssettings.php:97 -#: actions/smssettings.php:162 actions/smssettings.php:174 -msgid "" -"Send me notices through SMS; I understand I may incur exorbitant charges " -"from my carrier." +#: actions/microsummary.php:69 +msgid "No current status" msgstr "" -#: ../actions/imsettings.php:76 actions/imsettings.php:77 -#: actions/imsettings.php:147 actions/imsettings.php:153 -msgid "Send me replies through Jabber/GTalk from people I'm not subscribed to." +#: actions/newgroup.php:53 +msgid "New group" msgstr "" -#: ../lib/util.php:304 lib/util.php:320 lib/facebookaction.php:215 -#: lib/facebookaction.php:228 lib/facebookaction.php:230 -msgid "Settings" +#: actions/newgroup.php:110 +msgid "Use this form to create a new group." msgstr "" -#: ../actions/profilesettings.php:192 actions/profilesettings.php:307 -#: actions/profilesettings.php:319 actions/profilesettings.php:318 -#: actions/profilesettings.php:344 -msgid "Settings saved." +#: actions/newmessage.php:71 actions/newmessage.php:231 +msgid "New message" msgstr "" -#: ../actions/tag.php:60 actions/tag.php:60 -msgid "Showing most popular tags from the last week" +#: actions/newmessage.php:121 actions/newmessage.php:161 lib/command.php:367 +msgid "You can't send a message to this user." msgstr "" -#: ../actions/finishaddopenid.php:66 actions/finishaddopenid.php:66 -#: actions/finishaddopenid.php:114 -msgid "Someone else already has this OpenID." +#: actions/newmessage.php:144 actions/newnotice.php:136 lib/command.php:351 +#: lib/command.php:424 +msgid "No content!" msgstr "" -#: ../actions/finishopenidlogin.php:42 ../actions/openidsettings.php:126 -#: actions/finishopenidlogin.php:47 actions/openidsettings.php:135 -#: actions/finishopenidlogin.php:52 actions/openidsettings.php:202 -msgid "Something weird happened." +#: actions/newmessage.php:158 +msgid "No recipient specified." msgstr "" -#: ../scripts/maildaemon.php:58 scripts/maildaemon.php:58 -#: scripts/maildaemon.php:61 scripts/maildaemon.php:60 -msgid "Sorry, no incoming email allowed." +#: actions/newmessage.php:164 lib/command.php:370 +msgid "" +"Don't send a message to yourself; just say it to yourself quietly instead." msgstr "" -#: ../scripts/maildaemon.php:54 scripts/maildaemon.php:54 -#: scripts/maildaemon.php:57 scripts/maildaemon.php:56 -msgid "Sorry, that is not your incoming email address." +#: actions/newmessage.php:181 +msgid "Message sent" msgstr "" -#: ../lib/util.php:330 lib/util.php:346 lib/action.php:574 lib/action.php:667 -#: lib/action.php:717 lib/action.php:732 -msgid "Source" +#: actions/newmessage.php:185 lib/command.php:375 +#, php-format +msgid "Direct message to %s sent" msgstr "" -#: ../actions/showstream.php:296 actions/showstream.php:311 -#: actions/showstream.php:476 actions/showgroup.php:375 -#: actions/showgroup.php:421 lib/profileaction.php:173 -#: actions/showgroup.php:429 -msgid "Statistics" +#: actions/newmessage.php:210 actions/newnotice.php:233 lib/channel.php:170 +msgid "Ajax Error" msgstr "" -#: ../actions/finishopenidlogin.php:182 ../actions/finishopenidlogin.php:246 -#: actions/finishopenidlogin.php:188 actions/finishopenidlogin.php:252 -#: actions/finishopenidlogin.php:222 actions/finishopenidlogin.php:290 -#: actions/finishopenidlogin.php:295 actions/finishopenidlogin.php:238 -#: actions/finishopenidlogin.php:318 -msgid "Stored OpenID not found." +#: actions/newnotice.php:69 +msgid "New notice" msgstr "" -#: ../actions/remotesubscribe.php:75 ../actions/showstream.php:188 -#: ../actions/showstream.php:197 actions/remotesubscribe.php:84 -#: actions/showstream.php:197 actions/showstream.php:206 -#: actions/remotesubscribe.php:113 actions/showstream.php:376 -#: lib/subscribeform.php:139 actions/showstream.php:345 -#: actions/remotesubscribe.php:137 actions/showstream.php:439 -#: lib/userprofile.php:321 -msgid "Subscribe" +#: actions/newnotice.php:199 +msgid "Notice posted" msgstr "" -#: ../actions/showstream.php:313 ../actions/subscribers.php:27 -#: actions/showstream.php:328 actions/subscribers.php:27 -#: actions/showstream.php:436 actions/showstream.php:498 -#: lib/subgroupnav.php:88 lib/profileaction.php:140 lib/profileaction.php:200 -#: lib/subgroupnav.php:90 -msgid "Subscribers" +#: actions/noticesearch.php:68 +#, php-format +msgid "" +"Search for notices on %%site.name%% by their contents. Separate search terms " +"by spaces; they must be 3 characters or more." msgstr "" -#: ../actions/userauthorization.php:310 actions/userauthorization.php:322 -#: actions/userauthorization.php:338 actions/userauthorization.php:344 -#: actions/userauthorization.php:378 actions/userauthorization.php:247 -msgid "Subscription authorized" +#: actions/noticesearch.php:78 +msgid "Text search" msgstr "" -#: ../actions/userauthorization.php:320 actions/userauthorization.php:332 -#: actions/userauthorization.php:349 actions/userauthorization.php:355 -#: actions/userauthorization.php:389 actions/userauthorization.php:259 -msgid "Subscription rejected" +#: actions/noticesearch.php:91 +#, php-format +msgid "Search results for \"%s\" on %s" msgstr "" -#: ../actions/showstream.php:230 ../actions/showstream.php:307 -#: ../actions/subscriptions.php:27 actions/showstream.php:240 -#: actions/showstream.php:322 actions/subscriptions.php:27 -#: actions/showstream.php:407 actions/showstream.php:489 -#: lib/subgroupnav.php:80 lib/profileaction.php:109 lib/profileaction.php:191 -#: lib/subgroupnav.php:82 -msgid "Subscriptions" +#: actions/noticesearch.php:121 +#, php-format +msgid "" +"Be the first to [post on this topic](%%%%action.newnotice%%%%?" +"status_textarea=%s)!" msgstr "" -#: ../actions/avatar.php:87 actions/profilesettings.php:324 -#: lib/imagefile.php:78 lib/imagefile.php:82 lib/imagefile.php:83 -#: lib/imagefile.php:88 lib/mediafile.php:170 -msgid "System error uploading file." +#: actions/noticesearch.php:124 +#, php-format +msgid "" +"Why not [register an account](%%%%action.register%%%%) and be the first to " +"[post on this topic](%%%%action.newnotice%%%%?status_textarea=%s)!" msgstr "" -#: ../actions/tag.php:41 ../lib/util.php:301 actions/tag.php:41 -#: lib/util.php:317 actions/profilesettings.php:122 actions/showstream.php:297 -#: actions/tagother.php:147 actions/tagother.php:207 lib/profilelist.php:162 -#: lib/profilelist.php:164 actions/showstream.php:290 actions/tagother.php:149 -#: actions/tagother.php:209 lib/profilelist.php:160 -#: actions/profilesettings.php:123 actions/showstream.php:255 -#: lib/subscriptionlist.php:106 lib/subscriptionlist.php:108 -#: actions/profilesettings.php:138 actions/showstream.php:327 -#: lib/userprofile.php:209 -msgid "Tags" +#: actions/noticesearchrss.php:89 +#, php-format +msgid "Updates with \"%s\"" msgstr "" -#: ../lib/searchaction.php:104 lib/searchaction.php:104 -#: lib/designsettings.php:217 -msgid "Text" +#: actions/noticesearchrss.php:91 +#, php-format +msgid "Updates matching search term \"%1$s\" on %2$s!" msgstr "" -#: ../actions/noticesearch.php:34 actions/noticesearch.php:34 -#: actions/noticesearch.php:67 actions/noticesearch.php:78 -msgid "Text search" +#: actions/nudge.php:85 +msgid "" +"This user doesn't allow nudges or hasn't confirmed or set his email yet." msgstr "" -#: ../actions/openidsettings.php:140 actions/openidsettings.php:149 -#: actions/openidsettings.php:227 -msgid "That OpenID does not belong to you." +#: actions/nudge.php:94 +msgid "Nudge sent" msgstr "" -#: ../actions/confirmaddress.php:52 actions/confirmaddress.php:52 -#: actions/confirmaddress.php:94 -msgid "That address has already been confirmed." +#: actions/nudge.php:97 +msgid "Nudge sent!" msgstr "" -#: ../actions/confirmaddress.php:43 actions/confirmaddress.php:43 -#: actions/confirmaddress.php:85 -msgid "That confirmation code is not for you!" +#: actions/oembed.php:79 actions/shownotice.php:100 +msgid "Notice has no profile" msgstr "" -#: ../actions/emailsettings.php:191 actions/emailsettings.php:209 -#: actions/emailsettings.php:328 actions/emailsettings.php:336 -msgid "That email address already belongs to another user." +#: actions/oembed.php:86 actions/shownotice.php:180 +#, php-format +msgid "%1$s's status on %2$s" msgstr "" -#: ../actions/avatar.php:80 actions/profilesettings.php:317 -#: lib/imagefile.php:71 -msgid "That file is too big." +#: actions/oembed.php:157 +msgid "content type " msgstr "" -#: ../actions/imsettings.php:170 actions/imsettings.php:178 -#: actions/imsettings.php:293 actions/imsettings.php:299 -msgid "That is already your Jabber ID." +#: actions/oembed.php:160 +msgid "Only " msgstr "" -#: ../actions/emailsettings.php:188 actions/emailsettings.php:206 -#: actions/emailsettings.php:318 actions/emailsettings.php:325 -#: actions/emailsettings.php:333 -msgid "That is already your email address." +#: actions/oembed.php:181 actions/oembed.php:200 lib/api.php:963 +#: lib/api.php:991 lib/api.php:1101 +msgid "Not a supported data format." msgstr "" -#: ../actions/smssettings.php:188 actions/smssettings.php:196 -#: actions/smssettings.php:306 actions/smssettings.php:318 -msgid "That is already your phone number." +#: actions/opensearch.php:64 +msgid "User Search" msgstr "" -#: ../actions/imsettings.php:233 actions/imsettings.php:241 -#: actions/imsettings.php:381 actions/imsettings.php:387 -msgid "That is not your Jabber ID." +#: actions/opensearch.php:67 +msgid "Notice Search" msgstr "" -#: ../actions/emailsettings.php:249 actions/emailsettings.php:267 -#: actions/emailsettings.php:397 actions/emailsettings.php:404 -#: actions/emailsettings.php:412 -msgid "That is not your email address." +#: actions/othersettings.php:60 +msgid "Other Settings" msgstr "" -#: ../actions/smssettings.php:257 actions/smssettings.php:265 -#: actions/smssettings.php:393 actions/smssettings.php:405 -msgid "That is not your phone number." +#: actions/othersettings.php:71 +msgid "Manage various other options." msgstr "" -#: ../actions/emailsettings.php:226 ../actions/imsettings.php:210 -#: actions/emailsettings.php:244 actions/imsettings.php:218 -#: actions/emailsettings.php:367 actions/imsettings.php:349 -#: actions/emailsettings.php:374 actions/emailsettings.php:382 -#: actions/imsettings.php:355 -msgid "That is the wrong IM address." +#: actions/othersettings.php:117 +msgid "Shorten URLs with" msgstr "" -#: ../actions/smssettings.php:233 actions/smssettings.php:241 -#: actions/smssettings.php:362 actions/smssettings.php:374 -msgid "That is the wrong confirmation number." +#: actions/othersettings.php:118 +msgid "Automatic shortening service to use." msgstr "" -#: ../actions/smssettings.php:191 actions/smssettings.php:199 -#: actions/smssettings.php:309 actions/smssettings.php:321 -msgid "That phone number already belongs to another user." +#: actions/othersettings.php:122 +msgid "View profile designs" msgstr "" -#: ../actions/newnotice.php:49 ../actions/twitapistatuses.php:408 -#: actions/newnotice.php:49 actions/twitapistatuses.php:330 -#: actions/facebookhome.php:243 actions/twitapistatuses.php:276 -#: actions/newnotice.php:136 actions/twitapistatuses.php:294 -#: lib/facebookaction.php:485 actions/newnotice.php:166 -#: actions/twitapistatuses.php:251 lib/facebookaction.php:477 -#: scripts/maildaemon.php:70 -msgid "That's too long. Max notice size is 140 chars." +#: actions/othersettings.php:123 +msgid "Show or hide profile designs." msgstr "" -#: ../actions/twitapiaccount.php:74 actions/twitapiaccount.php:72 -#: actions/twitapiaccount.php:62 actions/twitapiaccount.php:63 -#: actions/twitapiaccount.php:66 -msgid "That's too long. Max notice size is 255 chars." +#: actions/othersettings.php:153 +msgid "URL shortening service is too long (max 50 chars)." msgstr "" -#: ../actions/confirmaddress.php:92 actions/confirmaddress.php:92 -#: actions/confirmaddress.php:159 +#: actions/outbox.php:58 #, php-format -msgid "The address \"%s\" has been confirmed for your account." +msgid "Outbox for %s - page %d" msgstr "" -#: ../actions/emailsettings.php:264 ../actions/imsettings.php:250 -#: ../actions/smssettings.php:274 actions/emailsettings.php:282 -#: actions/imsettings.php:258 actions/smssettings.php:282 -#: actions/emailsettings.php:416 actions/imsettings.php:402 -#: actions/smssettings.php:413 actions/emailsettings.php:423 -#: actions/emailsettings.php:431 actions/imsettings.php:408 -#: actions/smssettings.php:425 -msgid "The address was removed." +#: actions/outbox.php:61 +#, php-format +msgid "Outbox for %s" msgstr "" -#: ../actions/userauthorization.php:312 actions/userauthorization.php:346 -#: actions/userauthorization.php:380 -msgid "" -"The subscription has been authorized, but no callback URL was passed. Check " -"with the site's instructions for details on how to authorize the " -"subscription. Your subscription token is:" +#: actions/outbox.php:116 +msgid "This is your outbox, which lists private messages you have sent." msgstr "" -#: ../actions/userauthorization.php:322 actions/userauthorization.php:357 -#: actions/userauthorization.php:391 -msgid "" -"The subscription has been rejected, but no callback URL was passed. Check " -"with the site's instructions for details on how to fully reject the " -"subscription." +#: actions/passwordsettings.php:58 +msgid "Change password" msgstr "" -#: ../actions/subscribers.php:35 actions/subscribers.php:35 -#: actions/subscribers.php:67 -#, php-format -msgid "These are the people who listen to %s's notices." +#: actions/passwordsettings.php:69 +msgid "Change your password." msgstr "" -#: ../actions/subscribers.php:33 actions/subscribers.php:33 -#: actions/subscribers.php:63 -msgid "These are the people who listen to your notices." +#: actions/passwordsettings.php:95 actions/recoverpassword.php:231 +msgid "Password change" msgstr "" -#: ../actions/subscriptions.php:35 actions/subscriptions.php:35 -#: actions/subscriptions.php:69 -#, php-format -msgid "These are the people whose notices %s listens to." +#: actions/passwordsettings.php:103 +msgid "Old password" msgstr "" -#: ../actions/subscriptions.php:33 actions/subscriptions.php:33 -#: actions/subscriptions.php:65 -msgid "These are the people whose notices you listen to." +#: actions/passwordsettings.php:107 actions/recoverpassword.php:235 +msgid "New password" msgstr "" -#: ../actions/invite.php:89 actions/invite.php:96 actions/invite.php:128 -#: actions/invite.php:130 actions/invite.php:136 -msgid "" -"These people are already users and you were automatically subscribed to them:" +#: actions/passwordsettings.php:108 +msgid "6 or more characters" msgstr "" -#: ../actions/recoverpassword.php:88 actions/recoverpassword.php:97 -msgid "This confirmation code is too old. Please start again." +#: actions/passwordsettings.php:111 actions/recoverpassword.php:239 +#: actions/register.php:432 actions/smssettings.php:134 +msgid "Confirm" msgstr "" -#: ../lib/openid.php:195 lib/openid.php:206 -msgid "" -"This form should automatically submit itself. If not, click the submit " -"button to go to your OpenID provider." +#: actions/passwordsettings.php:112 +msgid "same as password above" msgstr "" -#: ../actions/finishopenidlogin.php:56 actions/finishopenidlogin.php:61 -#: actions/finishopenidlogin.php:67 actions/finishopenidlogin.php:66 -#, php-format -msgid "" -"This is the first time you've logged into %s so we must connect your OpenID " -"to a local account. You can either create a new account, or connect with " -"your existing account, if you have one." -msgstr "" - -#: ../actions/twitapifriendships.php:108 ../actions/twitapistatuses.php:586 -#: actions/twitapifavorites.php:127 actions/twitapifriendships.php:108 -#: actions/twitapistatuses.php:511 actions/twitapifavorites.php:97 -#: actions/twitapifriendships.php:85 actions/twitapistatuses.php:436 -#: actions/twitapifavorites.php:103 actions/twitapistatuses.php:460 -#: actions/twitapifavorites.php:154 actions/twitapifriendships.php:90 -#: actions/twitapistatuses.php:416 actions/apistatusesdestroy.php:107 -msgid "This method requires a POST or DELETE." +#: actions/passwordsettings.php:116 +msgid "Change" msgstr "" -#: ../actions/twitapiaccount.php:65 ../actions/twitapifriendships.php:44 -#: ../actions/twitapistatuses.php:381 actions/twitapiaccount.php:63 -#: actions/twitapidirect_messages.php:114 actions/twitapifriendships.php:44 -#: actions/twitapistatuses.php:303 actions/twitapiaccount.php:53 -#: actions/twitapidirect_messages.php:122 actions/twitapifriendships.php:32 -#: actions/twitapistatuses.php:244 actions/twitapiaccount.php:54 -#: actions/twitapidirect_messages.php:131 actions/twitapistatuses.php:262 -#: actions/twitapiaccount.php:56 actions/twitapidirect_messages.php:124 -#: actions/twitapifriendships.php:34 actions/twitapistatuses.php:216 -#: actions/apiblockcreate.php:89 actions/apiblockdestroy.php:88 -#: actions/apidirectmessagenew.php:117 actions/apifavoritecreate.php:90 -#: actions/apifavoritedestroy.php:91 actions/apifriendshipscreate.php:91 -#: actions/apifriendshipsdestroy.php:91 actions/apigroupcreate.php:104 -#: actions/apigroupjoin.php:91 actions/apigroupleave.php:91 -#: actions/apistatusesupdate.php:109 -#: actions/apiaccountupdateprofileimage.php:84 -msgid "This method requires a POST." +#: actions/passwordsettings.php:153 actions/register.php:230 +msgid "Password must be 6 or more characters." msgstr "" -#: ../lib/util.php:164 lib/util.php:246 lib/htmloutputter.php:104 -msgid "This page is not available in a media type you accept" +#: actions/passwordsettings.php:156 actions/register.php:233 +msgid "Passwords don't match." msgstr "" -#: ../actions/profilesettings.php:63 actions/profilesettings.php:96 -#: actions/profilesettings.php:138 actions/profilesettings.php:139 -#: actions/profilesettings.php:154 -msgid "Timezone" +#: actions/passwordsettings.php:164 +msgid "Incorrect old password" msgstr "" -#: ../actions/profilesettings.php:107 actions/profilesettings.php:222 -#: actions/profilesettings.php:211 actions/profilesettings.php:212 -#: actions/profilesettings.php:228 -msgid "Timezone not selected." +#: actions/passwordsettings.php:180 +msgid "Error saving user; invalid." msgstr "" -#: ../actions/remotesubscribe.php:43 actions/remotesubscribe.php:74 -#: actions/remotesubscribe.php:98 -#, php-format -msgid "" -"To subscribe, you can [login](%%action.login%%), or [register](%%action." -"register%%) a new account. If you already have an account on a [compatible " -"microblogging site](%%doc.openmublog%%), enter your profile URL below." +#: actions/passwordsettings.php:185 actions/recoverpassword.php:368 +msgid "Can't save new password." msgstr "" -#: ../actions/twitapifriendships.php:163 actions/twitapifriendships.php:167 -#: actions/twitapifriendships.php:132 actions/twitapifriendships.php:139 -#: actions/apifriendshipsexists.php:103 actions/apifriendshipsexists.php:94 -msgid "Two user ids or screen_names must be supplied." +#: actions/passwordsettings.php:191 actions/recoverpassword.php:211 +msgid "Password saved." msgstr "" -#: ../actions/profilesettings.php:48 ../actions/register.php:169 -#: actions/profilesettings.php:81 actions/register.php:183 -#: actions/profilesettings.php:109 actions/register.php:398 -#: actions/register.php:444 actions/profilesettings.php:117 -#: actions/register.php:448 actions/register.php:454 -msgid "URL of your homepage, blog, or profile on another site" +#: actions/peoplesearch.php:52 +#, php-format +msgid "" +"Search for users on %%site.name%% by their name, location, or interests. " +"Separate the terms by spaces; they must be 3 characters or more." msgstr "" -#: ../actions/remotesubscribe.php:74 actions/remotesubscribe.php:83 -#: actions/remotesubscribe.php:110 actions/remotesubscribe.php:134 -msgid "URL of your profile on another compatible microblogging service" +#: actions/peoplesearch.php:58 +msgid "People search" msgstr "" -#: ../actions/emailsettings.php:130 ../actions/imsettings.php:110 -#: ../actions/recoverpassword.php:39 ../actions/smssettings.php:135 -#: actions/emailsettings.php:144 actions/imsettings.php:118 -#: actions/recoverpassword.php:39 actions/smssettings.php:143 -#: actions/twittersettings.php:108 actions/avatarsettings.php:258 -#: actions/emailsettings.php:242 actions/grouplogo.php:317 -#: actions/imsettings.php:214 actions/recoverpassword.php:44 -#: actions/smssettings.php:236 actions/twittersettings.php:302 -#: actions/avatarsettings.php:263 actions/emailsettings.php:247 -#: actions/grouplogo.php:324 actions/twittersettings.php:306 -#: actions/twittersettings.php:322 lib/designsettings.php:301 -#: actions/emailsettings.php:255 actions/grouplogo.php:319 -#: actions/imsettings.php:220 actions/smssettings.php:248 -#: actions/avatarsettings.php:277 lib/designsettings.php:304 -msgid "Unexpected form submission." +#: actions/peopletag.php:70 +#, php-format +msgid "Not a valid user tag: %s" msgstr "" -#: ../actions/recoverpassword.php:276 actions/recoverpassword.php:289 -#: actions/recoverpassword.php:323 actions/recoverpassword.php:341 -#: actions/recoverpassword.php:344 -msgid "Unexpected password reset." +#: actions/peopletag.php:144 +#, php-format +msgid "Users self-tagged with %s - page %d" msgstr "" -#: ../index.php:57 index.php:57 actions/recoverpassword.php:202 -#: actions/recoverpassword.php:210 actions/recoverpassword.php:213 -msgid "Unknown action" +#: actions/postnotice.php:84 +msgid "Invalid notice content" msgstr "" -#: ../actions/finishremotesubscribe.php:58 -#: actions/finishremotesubscribe.php:60 actions/finishremotesubscribe.php:61 -msgid "Unknown version of OMB protocol." +#: actions/postnotice.php:90 +#, php-format +msgid "Notice license ‘%s’ is not compatible with site license ‘%s’." msgstr "" -#: ../lib/util.php:269 lib/util.php:285 -msgid "" -"Unless otherwise specified, contents of this site are copyright by the " -"contributors and available under the " +#: actions/profilesettings.php:60 +msgid "Profile settings" msgstr "" -#: ../actions/confirmaddress.php:48 actions/confirmaddress.php:48 -#: actions/confirmaddress.php:90 -#, php-format -msgid "Unrecognized address type %s" +#: actions/profilesettings.php:71 +msgid "" +"You can update your personal profile info here so readers know more about " +"you." msgstr "" -#: ../actions/showstream.php:209 actions/showstream.php:219 -#: lib/unsubscribeform.php:137 -msgid "Unsubscribe" +#: actions/profilesettings.php:99 +msgid "Profile information" msgstr "" -#: ../actions/postnotice.php:44 ../actions/updateprofile.php:45 -#: actions/postnotice.php:45 actions/updateprofile.php:46 -#: actions/postnotice.php:48 actions/updateprofile.php:49 -#: actions/updateprofile.php:51 -msgid "Unsupported OMB version" +#: actions/profilesettings.php:108 lib/groupeditform.php:154 +msgid "1-64 lowercase letters or numbers, no punctuation or spaces" msgstr "" -#: ../actions/avatar.php:105 actions/profilesettings.php:342 -#: lib/imagefile.php:102 lib/imagefile.php:99 lib/imagefile.php:100 -#: lib/imagefile.php:105 -msgid "Unsupported image file format." +#: actions/profilesettings.php:111 actions/register.php:447 +#: actions/showgroup.php:247 actions/tagother.php:104 +#: lib/groupeditform.php:157 lib/userprofile.php:149 +msgid "Full name" msgstr "" -#: ../lib/settingsaction.php:100 lib/settingsaction.php:94 -#: lib/connectsettingsaction.php:108 lib/connectsettingsaction.php:116 -msgid "Updates by SMS" +#: actions/profilesettings.php:115 actions/register.php:452 +#: lib/groupeditform.php:161 +msgid "Homepage" msgstr "" -#: ../lib/settingsaction.php:103 lib/settingsaction.php:97 -#: lib/connectsettingsaction.php:105 lib/connectsettingsaction.php:111 -msgid "Updates by instant messenger (IM)" +#: actions/profilesettings.php:117 actions/register.php:454 +msgid "URL of your homepage, blog, or profile on another site" msgstr "" -#: ../actions/twitapistatuses.php:241 actions/twitapistatuses.php:158 -#: actions/twitapistatuses.php:129 actions/twitapistatuses.php:134 -#: actions/twitapistatuses.php:94 actions/allrss.php:119 -#: actions/apitimelinefriends.php:121 +#: actions/profilesettings.php:122 actions/register.php:460 #, php-format -msgid "Updates from %1$s and friends on %2$s!" +msgid "Describe yourself and your interests in %d chars" msgstr "" -#: ../actions/twitapistatuses.php:341 actions/twitapistatuses.php:268 -#: actions/twitapistatuses.php:202 actions/twitapistatuses.php:213 -#: actions/twitapigroups.php:74 actions/twitapistatuses.php:159 -#: actions/apitimelinegroup.php:110 actions/apitimelineuser.php:125 -#: actions/userrss.php:92 -#, php-format -msgid "Updates from %1$s on %2$s!" +#: actions/profilesettings.php:125 actions/register.php:463 +msgid "Describe yourself and your interests" msgstr "" -#: ../actions/avatar.php:68 actions/profilesettings.php:161 -#: actions/avatarsettings.php:162 actions/grouplogo.php:232 -#: actions/avatarsettings.php:165 actions/grouplogo.php:238 -#: actions/grouplogo.php:233 -msgid "Upload" +#: actions/profilesettings.php:127 actions/register.php:465 +msgid "Bio" msgstr "" -#: ../actions/avatar.php:27 -msgid "" -"Upload a new \"avatar\" (user image) here. You can't edit the picture after " -"you upload it, so make sure it's more or less square. It must be under the " -"site license, also. Use a picture that belongs to you and that you want to " -"share." +#: actions/profilesettings.php:132 actions/register.php:470 +#: actions/showgroup.php:256 actions/tagother.php:112 +#: actions/userauthorization.php:158 lib/groupeditform.php:177 +#: lib/userprofile.php:164 +msgid "Location" msgstr "" -#: ../lib/settingsaction.php:91 -msgid "Upload a new profile image" +#: actions/profilesettings.php:134 actions/register.php:472 +msgid "Where you are, like \"City, State (or Region), Country\"" msgstr "" -#: ../actions/invite.php:114 actions/invite.php:121 actions/invite.php:154 -#: actions/invite.php:156 actions/invite.php:162 -msgid "" -"Use this form to invite your friends and colleagues to use this service." +#: actions/profilesettings.php:138 actions/tagother.php:149 +#: actions/tagother.php:209 lib/subscriptionlist.php:106 +#: lib/subscriptionlist.php:108 lib/userprofile.php:209 +msgid "Tags" msgstr "" -#: ../actions/register.php:159 ../actions/register.php:162 -#: actions/register.php:173 actions/register.php:176 actions/register.php:382 -#: actions/register.php:386 actions/register.php:428 actions/register.php:432 -#: actions/register.php:436 actions/register.php:438 actions/register.php:442 -msgid "Used only for updates, announcements, and password recovery" +#: actions/profilesettings.php:140 +msgid "" +"Tags for yourself (letters, numbers, -, ., and _), comma- or space- separated" msgstr "" -#: ../actions/finishremotesubscribe.php:86 -#: actions/finishremotesubscribe.php:88 actions/finishremotesubscribe.php:94 -msgid "User being listened to doesn't exist." -msgstr "" - -#: ../actions/all.php:41 ../actions/avatarbynickname.php:48 -#: ../actions/foaf.php:47 ../actions/replies.php:41 -#: ../actions/showstream.php:44 ../actions/twitapiaccount.php:82 -#: ../actions/twitapistatuses.php:319 ../actions/twitapistatuses.php:685 -#: ../actions/twitapiusers.php:82 actions/all.php:41 -#: actions/avatarbynickname.php:48 actions/foaf.php:47 actions/replies.php:41 -#: actions/showfavorites.php:41 actions/showstream.php:44 -#: actions/twitapiaccount.php:80 actions/twitapifavorites.php:68 -#: actions/twitapistatuses.php:235 actions/twitapistatuses.php:609 -#: actions/twitapiusers.php:87 lib/mailbox.php:50 -#: actions/avatarbynickname.php:80 actions/foaf.php:48 actions/replies.php:80 -#: actions/showstream.php:107 actions/twitapiaccount.php:70 -#: actions/twitapifavorites.php:42 actions/twitapistatuses.php:167 -#: actions/twitapistatuses.php:503 actions/twitapiusers.php:55 -#: actions/usergroups.php:99 lib/galleryaction.php:67 lib/twitterapi.php:626 -#: actions/twitapiaccount.php:71 actions/twitapistatuses.php:179 -#: actions/twitapistatuses.php:535 actions/twitapiusers.php:59 -#: actions/foaf.php:65 actions/replies.php:79 actions/twitapiusers.php:57 -#: actions/usergroups.php:98 lib/galleryaction.php:66 lib/profileaction.php:84 -#: actions/apiusershow.php:108 actions/apiaccountupdateprofileimage.php:124 -#: actions/apiaccountupdateprofileimage.php:130 -msgid "User has no profile." +#: actions/profilesettings.php:144 +msgid "Language" msgstr "" -#: ../actions/remotesubscribe.php:71 actions/remotesubscribe.php:80 -#: actions/remotesubscribe.php:105 actions/remotesubscribe.php:129 -msgid "User nickname" +#: actions/profilesettings.php:145 +msgid "Preferred language" msgstr "" -#: ../actions/twitapiusers.php:75 actions/twitapiusers.php:80 -msgid "User not found." +#: actions/profilesettings.php:154 +msgid "Timezone" msgstr "" -#: ../actions/profilesettings.php:63 actions/profilesettings.php:96 -#: actions/profilesettings.php:139 actions/profilesettings.php:140 #: actions/profilesettings.php:155 msgid "What timezone are you normally in?" msgstr "" -#: ../lib/util.php:1159 lib/util.php:1293 lib/noticeform.php:141 -#: lib/noticeform.php:158 -#, php-format -msgid "What's up, %s?" -msgstr "" - -#: ../actions/profilesettings.php:54 ../actions/register.php:175 -#: actions/profilesettings.php:87 actions/register.php:189 -#: actions/profilesettings.php:119 actions/register.php:410 -#: actions/register.php:456 actions/profilesettings.php:134 -#: actions/register.php:466 actions/register.php:472 -msgid "Where you are, like \"City, State (or Region), Country\"" -msgstr "" - -#: ../actions/updateprofile.php:128 actions/updateprofile.php:129 -#: actions/updateprofile.php:132 actions/updateprofile.php:134 -#, php-format -msgid "Wrong image type for '%s'" +#: actions/profilesettings.php:160 +msgid "" +"Automatically subscribe to whoever subscribes to me (best for non-humans)" msgstr "" -#: ../actions/updateprofile.php:123 actions/updateprofile.php:124 -#: actions/updateprofile.php:127 actions/updateprofile.php:129 +#: actions/profilesettings.php:221 actions/register.php:223 #, php-format -msgid "Wrong size image at '%s'" -msgstr "" - -#: ../actions/deletenotice.php:63 ../actions/deletenotice.php:72 -#: actions/deletenotice.php:64 actions/deletenotice.php:79 -#: actions/block.php:148 actions/deletenotice.php:122 -#: actions/deletenotice.php:141 actions/deletenotice.php:115 -#: actions/block.php:150 actions/deletenotice.php:116 -#: actions/groupblock.php:177 actions/deletenotice.php:146 -msgid "Yes" +msgid "Bio is too long (max %d chars)." msgstr "" -#: ../actions/finishaddopenid.php:64 actions/finishaddopenid.php:64 -#: actions/finishaddopenid.php:112 -msgid "You already have this OpenID!" +#: actions/profilesettings.php:228 +msgid "Timezone not selected." msgstr "" -#: ../actions/deletenotice.php:37 actions/deletenotice.php:37 -msgid "" -"You are about to permanently delete a notice. Once this is done, it cannot " -"be undone." +#: actions/profilesettings.php:234 +msgid "Language is too long (max 50 chars)." msgstr "" -#: ../actions/recoverpassword.php:31 actions/recoverpassword.php:31 -#: actions/recoverpassword.php:36 -msgid "You are already logged in!" +#: actions/profilesettings.php:246 actions/tagother.php:178 +#, php-format +msgid "Invalid tag: \"%s\"" msgstr "" -#: ../actions/invite.php:81 actions/invite.php:88 actions/invite.php:120 -#: actions/invite.php:122 actions/invite.php:128 -msgid "You are already subscribed to these users:" +#: actions/profilesettings.php:295 +msgid "Couldn't update user for autosubscribe." msgstr "" -#: ../actions/twitapifriendships.php:128 actions/twitapifriendships.php:128 -#: actions/twitapifriendships.php:105 actions/twitapifriendships.php:111 -msgid "You are not friends with the specified user." +#: actions/profilesettings.php:328 +msgid "Couldn't save profile." msgstr "" -#: ../actions/password.php:27 -msgid "You can change your password here. Choose a good one!" +#: actions/profilesettings.php:336 +msgid "Couldn't save tags." msgstr "" -#: ../actions/register.php:135 actions/register.php:145 -msgid "You can create a new account to start posting notices." +#: actions/profilesettings.php:344 +msgid "Settings saved." msgstr "" -#: ../actions/smssettings.php:28 actions/smssettings.php:28 -#: actions/smssettings.php:69 +#: actions/public.php:83 #, php-format -msgid "You can receive SMS messages through email from %%site.name%%." +msgid "Beyond the page limit (%s)" msgstr "" -#: ../actions/openidsettings.php:86 actions/openidsettings.php:143 -msgid "" -"You can remove an OpenID from your account by clicking the button marked " -"\"Remove\"." +#: actions/public.php:92 +msgid "Could not retrieve public stream." msgstr "" -#: ../actions/imsettings.php:28 actions/imsettings.php:28 -#: actions/imsettings.php:70 +#: actions/public.php:129 #, php-format -msgid "" -"You can send and receive notices through Jabber/GTalk [instant messages](%%" -"doc.im%%). Configure your address and settings below." +msgid "Public timeline, page %d" msgstr "" -#: ../actions/profilesettings.php:27 actions/profilesettings.php:69 -#: actions/profilesettings.php:71 -msgid "" -"You can update your personal profile info here so people know more about you." +#: actions/public.php:131 lib/publicgroupnav.php:79 +msgid "Public timeline" msgstr "" -#: ../actions/finishremotesubscribe.php:31 ../actions/remotesubscribe.php:31 -#: actions/finishremotesubscribe.php:31 actions/remotesubscribe.php:31 -#: actions/finishremotesubscribe.php:33 actions/finishremotesubscribe.php:85 -#: actions/finishremotesubscribe.php:101 actions/remotesubscribe.php:35 -#: actions/finishremotesubscribe.php:87 actions/remotesubscribe.php:59 -msgid "You can use the local subscription!" +#: actions/public.php:151 +msgid "Public Stream Feed (RSS 1.0)" msgstr "" -#: ../actions/finishopenidlogin.php:33 ../actions/register.php:61 -#: actions/finishopenidlogin.php:38 actions/register.php:68 -#: actions/finishopenidlogin.php:43 actions/register.php:149 -#: actions/register.php:186 actions/register.php:192 actions/register.php:198 -msgid "You can't register if you don't agree to the license." +#: actions/public.php:155 +msgid "Public Stream Feed (RSS 2.0)" msgstr "" -#: ../actions/updateprofile.php:63 actions/updateprofile.php:64 -#: actions/updateprofile.php:67 actions/updateprofile.php:69 -msgid "You did not send us that profile" +#: actions/public.php:159 +msgid "Public Stream Feed (Atom)" msgstr "" -#: ../lib/mail.php:147 lib/mail.php:289 lib/mail.php:288 +#: actions/public.php:179 #, php-format msgid "" -"You have a new posting address on %1$s.\n" -"\n" -"Send email to %2$s to post new messages.\n" -"\n" -"More email instructions at %3$s.\n" -"\n" -"Faithfully yours,\n" -"%4$s" +"This is the public timeline for %%site.name%% but no one has posted anything " +"yet." msgstr "" -#: ../actions/twitapistatuses.php:612 actions/twitapistatuses.php:537 -#: actions/twitapistatuses.php:463 actions/twitapistatuses.php:486 -#: actions/twitapistatuses.php:443 actions/apistatusesdestroy.php:130 -msgid "You may not delete another user's status." +#: actions/public.php:182 +msgid "Be the first to post!" msgstr "" -#: ../actions/invite.php:31 actions/invite.php:31 actions/invite.php:39 -#: actions/invite.php:41 +#: actions/public.php:186 #, php-format -msgid "You must be logged in to invite other users to use %s" -msgstr "" - -#: ../actions/invite.php:103 actions/invite.php:110 actions/invite.php:142 -#: actions/invite.php:144 actions/invite.php:150 msgid "" -"You will be notified when your invitees accept the invitation and register " -"on the site. Thanks for growing the community!" -msgstr "" - -#: ../actions/recoverpassword.php:149 actions/recoverpassword.php:158 -msgid "You've been identified. Enter a new password below. " -msgstr "" - -#: ../actions/openidlogin.php:67 actions/openidlogin.php:76 -#: actions/openidlogin.php:104 actions/openidlogin.php:113 -msgid "Your OpenID URL" +"Why not [register an account](%%action.register%%) and be the first to post!" msgstr "" -#: ../actions/recoverpassword.php:164 actions/recoverpassword.php:188 -#: actions/recoverpassword.php:193 -msgid "Your nickname on this server, or your registered email address." +#: actions/public.php:233 +#, php-format +msgid "" +"This is %%site.name%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-" +"blogging) service based on the Free Software [StatusNet](http://status.net/) " +"tool. [Join now](%%action.register%%) to share notices about yourself with " +"friends, family, and colleagues! ([Read more](%%doc.help%%))" msgstr "" -#: ../actions/openidsettings.php:28 actions/openidsettings.php:70 +#: actions/public.php:238 #, php-format msgid "" -"[OpenID](%%doc.openid%%) lets you log into many sites with the same user " -"account. Manage your associated OpenIDs from here." +"This is %%site.name%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-" +"blogging) service based on the Free Software [StatusNet](http://status.net/) " +"tool." msgstr "" -#: ../lib/util.php:943 lib/util.php:992 lib/util.php:945 lib/util.php:756 -#: lib/util.php:770 lib/util.php:816 lib/util.php:844 -msgid "a few seconds ago" +#: actions/publictagcloud.php:57 +msgid "Public tag cloud" msgstr "" -#: ../lib/util.php:955 lib/util.php:1004 lib/util.php:957 lib/util.php:768 -#: lib/util.php:782 lib/util.php:828 lib/util.php:856 +#: actions/publictagcloud.php:63 #, php-format -msgid "about %d days ago" +msgid "These are most popular recent tags on %s " msgstr "" -#: ../lib/util.php:951 lib/util.php:1000 lib/util.php:953 lib/util.php:764 -#: lib/util.php:778 lib/util.php:824 lib/util.php:852 +#: actions/publictagcloud.php:69 #, php-format -msgid "about %d hours ago" +msgid "No one has posted a notice with a [hashtag](%%doc.tags%%) yet." msgstr "" -#: ../lib/util.php:947 lib/util.php:996 lib/util.php:949 lib/util.php:760 -#: lib/util.php:774 lib/util.php:820 lib/util.php:848 -#, php-format -msgid "about %d minutes ago" +#: actions/publictagcloud.php:72 +msgid "Be the first to post one!" msgstr "" -#: ../lib/util.php:959 lib/util.php:1008 lib/util.php:961 lib/util.php:772 -#: lib/util.php:786 lib/util.php:832 lib/util.php:860 +#: actions/publictagcloud.php:75 #, php-format -msgid "about %d months ago" +msgid "" +"Why not [register an account](%%action.register%%) and be the first to post " +"one!" msgstr "" -#: ../lib/util.php:953 lib/util.php:1002 lib/util.php:955 lib/util.php:766 -#: lib/util.php:780 lib/util.php:826 lib/util.php:854 -msgid "about a day ago" +#: actions/publictagcloud.php:135 +msgid "Tag cloud" msgstr "" -#: ../lib/util.php:945 lib/util.php:994 lib/util.php:947 lib/util.php:758 -#: lib/util.php:772 lib/util.php:818 lib/util.php:846 -msgid "about a minute ago" +#: actions/recoverpassword.php:36 +msgid "You are already logged in!" msgstr "" -#: ../lib/util.php:957 lib/util.php:1006 lib/util.php:959 lib/util.php:770 -#: lib/util.php:784 lib/util.php:830 lib/util.php:858 -msgid "about a month ago" +#: actions/recoverpassword.php:62 +msgid "No such recovery code." msgstr "" -#: ../lib/util.php:961 lib/util.php:1010 lib/util.php:963 lib/util.php:774 -#: lib/util.php:788 lib/util.php:834 lib/util.php:862 -msgid "about a year ago" +#: actions/recoverpassword.php:66 +msgid "Not a recovery code." msgstr "" -#: ../lib/util.php:949 lib/util.php:998 lib/util.php:951 lib/util.php:762 -#: lib/util.php:776 lib/util.php:822 lib/util.php:850 -msgid "about an hour ago" +#: actions/recoverpassword.php:73 +msgid "Recovery code for unknown user." msgstr "" -#: ../actions/showstream.php:423 ../lib/stream.php:132 -#: actions/showstream.php:441 lib/stream.php:99 -msgid "delete" +#: actions/recoverpassword.php:86 +msgid "Error with confirmation code." msgstr "" -#: ../actions/noticesearch.php:130 ../actions/showstream.php:408 -#: ../lib/stream.php:117 actions/noticesearch.php:136 -#: actions/showstream.php:426 lib/stream.php:84 actions/noticesearch.php:187 -msgid "in reply to..." +#: actions/recoverpassword.php:97 +msgid "This confirmation code is too old. Please start again." msgstr "" -#: ../actions/noticesearch.php:137 ../actions/showstream.php:415 -#: ../lib/stream.php:124 actions/noticesearch.php:143 -#: actions/showstream.php:433 lib/stream.php:91 actions/noticesearch.php:194 -msgid "reply" +#: actions/recoverpassword.php:111 +msgid "Could not update user with confirmed email address." msgstr "" -#: ../actions/password.php:44 actions/profilesettings.php:183 -#: actions/passwordsettings.php:106 actions/passwordsettings.php:112 -msgid "same as password above" +#: actions/recoverpassword.php:152 +msgid "" +"If you have forgotten or lost your password, you can get a new one sent to " +"the email address you have stored in your account." msgstr "" -#: ../actions/twitapistatuses.php:755 actions/twitapistatuses.php:678 -#: actions/twitapistatuses.php:555 actions/twitapistatuses.php:596 -#: actions/twitapistatuses.php:618 actions/twitapistatuses.php:553 -#: actions/twitapistatuses.php:575 -msgid "unsupported file type" -msgstr "" - -#: ../lib/util.php:1309 lib/util.php:1443 -msgid "« After" -msgstr "" - -#: actions/deletenotice.php:74 actions/disfavor.php:43 -#: actions/emailsettings.php:127 actions/favor.php:45 -#: actions/finishopenidlogin.php:33 actions/imsettings.php:105 -#: actions/invite.php:46 actions/newmessage.php:45 actions/openidlogin.php:36 -#: actions/openidsettings.php:123 actions/profilesettings.php:47 -#: actions/recoverpassword.php:282 actions/register.php:42 -#: actions/remotesubscribe.php:40 actions/smssettings.php:124 -#: actions/subscribe.php:44 actions/twittersettings.php:97 -#: actions/unsubscribe.php:41 actions/userauthorization.php:35 -#: actions/block.php:64 actions/disfavor.php:74 actions/favor.php:77 -#: actions/finishopenidlogin.php:38 actions/invite.php:54 actions/nudge.php:80 -#: actions/openidlogin.php:37 actions/recoverpassword.php:316 -#: actions/subscribe.php:46 actions/unblock.php:65 actions/unsubscribe.php:43 -#: actions/avatarsettings.php:251 actions/emailsettings.php:229 -#: actions/grouplogo.php:314 actions/imsettings.php:200 actions/login.php:103 -#: actions/newmessage.php:133 actions/newnotice.php:96 -#: actions/openidsettings.php:188 actions/othersettings.php:136 -#: actions/passwordsettings.php:131 actions/profilesettings.php:172 -#: actions/register.php:113 actions/remotesubscribe.php:53 -#: actions/smssettings.php:216 actions/subedit.php:38 actions/tagother.php:166 -#: actions/twittersettings.php:294 actions/userauthorization.php:39 -#: actions/favor.php:75 actions/groupblock.php:66 actions/groupunblock.php:66 -#: actions/invite.php:56 actions/makeadmin.php:66 actions/newnotice.php:102 -#: actions/othersettings.php:138 actions/recoverpassword.php:334 -#: actions/register.php:153 actions/twittersettings.php:310 -#: lib/designsettings.php:291 actions/emailsettings.php:237 -#: actions/grouplogo.php:309 actions/imsettings.php:206 actions/login.php:105 -#: actions/newmessage.php:135 actions/newnotice.php:103 -#: actions/othersettings.php:145 actions/passwordsettings.php:137 -#: actions/profilesettings.php:187 actions/recoverpassword.php:337 -#: actions/register.php:159 actions/remotesubscribe.php:77 -#: actions/smssettings.php:228 actions/unsubscribe.php:69 -#: actions/userauthorization.php:52 actions/login.php:131 -#: actions/register.php:165 actions/avatarsettings.php:265 -#: lib/designsettings.php:294 -msgid "There was a problem with your session token. Try again, please." +#: actions/recoverpassword.php:158 +msgid "You have been identified. Enter a new password below. " msgstr "" -#: actions/disfavor.php:55 actions/disfavor.php:81 -msgid "This notice is not a favorite!" +#: actions/recoverpassword.php:188 +msgid "Password recovery" msgstr "" -#: actions/disfavor.php:63 actions/disfavor.php:87 -#: actions/twitapifavorites.php:188 actions/apifavoritedestroy.php:134 -msgid "Could not delete favorite." +#: actions/recoverpassword.php:191 +msgid "Nickname or email address" msgstr "" -#: actions/disfavor.php:72 lib/favorform.php:140 -msgid "Favor" +#: actions/recoverpassword.php:193 +msgid "Your nickname on this server, or your registered email address." msgstr "" -#: actions/emailsettings.php:92 actions/emailsettings.php:157 -#: actions/emailsettings.php:163 -msgid "Send me email when someone adds my notice as a favorite." +#: actions/recoverpassword.php:199 actions/recoverpassword.php:200 +msgid "Recover" msgstr "" -#: actions/emailsettings.php:95 actions/emailsettings.php:163 -#: actions/emailsettings.php:169 -msgid "Send me email when someone sends me a private message." +#: actions/recoverpassword.php:208 +msgid "Reset password" msgstr "" -#: actions/favor.php:53 actions/twitapifavorites.php:142 actions/favor.php:81 -#: actions/twitapifavorites.php:118 actions/twitapifavorites.php:124 -#: actions/favor.php:79 -msgid "This notice is already a favorite!" +#: actions/recoverpassword.php:209 +msgid "Recover password" msgstr "" -#: actions/favor.php:60 actions/twitapifavorites.php:151 -#: classes/Command.php:132 actions/favor.php:86 -#: actions/twitapifavorites.php:125 classes/Command.php:152 -#: actions/twitapifavorites.php:131 lib/command.php:152 actions/favor.php:84 -#: actions/twitapifavorites.php:133 lib/command.php:145 -#: actions/apifavoritecreate.php:130 lib/command.php:176 -msgid "Could not create favorite." +#: actions/recoverpassword.php:210 actions/recoverpassword.php:322 +msgid "Password recovery requested" msgstr "" -#: actions/favor.php:70 -msgid "Disfavor" +#: actions/recoverpassword.php:213 +msgid "Unknown action" msgstr "" -#: actions/favoritesrss.php:60 actions/showfavorites.php:47 -#: actions/favoritesrss.php:100 actions/showfavorites.php:77 -#: actions/favoritesrss.php:110 -#, php-format -msgid "%s favorite notices" +#: actions/recoverpassword.php:236 +msgid "6 or more characters, and don't forget it!" msgstr "" -#: actions/favoritesrss.php:64 actions/favoritesrss.php:104 -#: actions/favoritesrss.php:114 -#, php-format -msgid "Feed of favorite notices of %s" +#: actions/recoverpassword.php:240 +msgid "Same as password above" msgstr "" -#: actions/inbox.php:28 actions/inbox.php:59 -#, php-format -msgid "Inbox for %s - page %d" -msgstr "" - -#: actions/inbox.php:30 actions/inbox.php:62 -#, php-format -msgid "Inbox for %s" -msgstr "" - -#: actions/inbox.php:53 actions/inbox.php:115 -msgid "This is your inbox, which lists your incoming private messages." +#: actions/recoverpassword.php:243 +msgid "Reset" msgstr "" -#: actions/invite.php:178 actions/invite.php:213 -#, php-format -msgid "" -"%1$s has invited you to join them on %2$s (%3$s).\n" -"\n" +#: actions/recoverpassword.php:252 +msgid "Enter a nickname or email address." msgstr "" -#: actions/login.php:104 actions/login.php:235 actions/openidlogin.php:108 -#: actions/register.php:416 -msgid "Automatically login in the future; " +#: actions/recoverpassword.php:272 +msgid "No user with that email address or username." msgstr "" -#: actions/login.php:122 actions/login.php:264 -msgid "For security reasons, please re-enter your " +#: actions/recoverpassword.php:287 +msgid "No registered email address for that user." msgstr "" -#: actions/login.php:126 actions/login.php:268 -msgid "Login with your username and password. " +#: actions/recoverpassword.php:301 +msgid "Error saving address confirmation." msgstr "" -#: actions/newmessage.php:58 actions/twitapidirect_messages.php:130 -#: actions/twitapidirect_messages.php:141 actions/newmessage.php:148 -#: actions/twitapidirect_messages.php:150 -#: actions/twitapidirect_messages.php:145 -msgid "That's too long. Max message size is 140 chars." +#: actions/recoverpassword.php:325 +msgid "" +"Instructions for recovering your password have been sent to the email " +"address registered to your account." msgstr "" -#: actions/newmessage.php:65 actions/newmessage.php:128 -#: actions/newmessage.php:155 actions/newmessage.php:158 -msgid "No recipient specified." +#: actions/recoverpassword.php:344 +msgid "Unexpected password reset." msgstr "" -#: actions/newmessage.php:68 actions/newmessage.php:113 -#: classes/Command.php:206 actions/newmessage.php:131 -#: actions/newmessage.php:168 classes/Command.php:237 -#: actions/newmessage.php:119 actions/newmessage.php:158 lib/command.php:237 -#: lib/command.php:230 actions/newmessage.php:121 actions/newmessage.php:161 -#: lib/command.php:367 -msgid "You can't send a message to this user." +#: actions/recoverpassword.php:352 +msgid "Password must be 6 chars or more." msgstr "" -#: actions/newmessage.php:71 actions/twitapidirect_messages.php:146 -#: classes/Command.php:209 actions/twitapidirect_messages.php:158 -#: classes/Command.php:240 actions/newmessage.php:161 -#: actions/twitapidirect_messages.php:167 lib/command.php:240 -#: actions/twitapidirect_messages.php:163 lib/command.php:233 -#: actions/newmessage.php:164 lib/command.php:370 -msgid "" -"Don't send a message to yourself; just say it to yourself quietly instead." +#: actions/recoverpassword.php:356 +msgid "Password and confirmation do not match." msgstr "" -#: actions/newmessage.php:108 actions/microsummary.php:62 -#: actions/newmessage.php:163 actions/newmessage.php:114 -#: actions/newmessage.php:116 actions/remotesubscribe.php:154 -msgid "No such user" +#: actions/recoverpassword.php:382 +msgid "New password successfully saved. You are now logged in." msgstr "" -#: actions/newmessage.php:117 actions/newmessage.php:67 -#: actions/newmessage.php:71 actions/newmessage.php:231 -msgid "New message" +#: actions/register.php:85 actions/register.php:189 actions/register.php:404 +msgid "Sorry. Only those invited can register." msgstr "" -#: actions/noticesearch.php:95 actions/noticesearch.php:146 -msgid "Notice without matching profile" +#: actions/register.php:92 +msgid "Sorry. This is an invalid invitation code." msgstr "" -#: actions/openidsettings.php:28 actions/openidsettings.php:70 -#, php-format -msgid "[OpenID](%%doc.openid%%) lets you log into many sites " +#: actions/register.php:112 +msgid "Registration successful" msgstr "" -#: actions/openidsettings.php:46 actions/openidsettings.php:96 -msgid "If you want to add an OpenID to your account, " +#: actions/register.php:114 actions/register.php:502 lib/action.php:450 +#: lib/logingroupnav.php:85 +msgid "Register" msgstr "" -#: actions/openidsettings.php:74 -msgid "Removing your only OpenID would make it impossible to log in! " +#: actions/register.php:135 +msgid "Registration not allowed." msgstr "" -#: actions/openidsettings.php:87 actions/openidsettings.php:143 -msgid "You can remove an OpenID from your account " +#: actions/register.php:198 +msgid "You can't register if you don't agree to the license." msgstr "" -#: actions/outbox.php:28 actions/outbox.php:58 -#, php-format -msgid "Outbox for %s - page %d" +#: actions/register.php:201 +msgid "Not a valid email address." msgstr "" -#: actions/outbox.php:30 actions/outbox.php:61 -#, php-format -msgid "Outbox for %s" +#: actions/register.php:212 +msgid "Email address already exists." msgstr "" -#: actions/outbox.php:53 actions/outbox.php:116 -msgid "This is your outbox, which lists private messages you have sent." +#: actions/register.php:243 actions/register.php:264 +msgid "Invalid username or password." msgstr "" -#: actions/peoplesearch.php:28 actions/peoplesearch.php:52 -#, php-format +#: actions/register.php:342 msgid "" -"Search for people on %%site.name%% by their name, location, or interests. " +"With this form you can create a new account. You can then post notices and " +"link up to friends and colleagues. " msgstr "" -#: actions/profilesettings.php:27 actions/profilesettings.php:69 -msgid "You can update your personal profile info here " +#: actions/register.php:424 +msgid "1-64 lowercase letters or numbers, no punctuation or spaces. Required." msgstr "" -#: actions/profilesettings.php:115 actions/remotesubscribe.php:320 -#: actions/userauthorization.php:159 actions/userrss.php:76 -#: actions/avatarsettings.php:104 actions/avatarsettings.php:179 -#: actions/grouplogo.php:177 actions/remotesubscribe.php:367 -#: actions/userauthorization.php:176 actions/userrss.php:82 -#: actions/avatarsettings.php:106 actions/avatarsettings.php:182 -#: actions/grouplogo.php:183 actions/remotesubscribe.php:366 -#: actions/remotesubscribe.php:364 actions/userauthorization.php:215 -#: actions/userrss.php:103 actions/grouplogo.php:178 -#: actions/remotesubscribe.php:191 actions/userauthorization.php:72 -msgid "User without matching profile" +#: actions/register.php:429 +msgid "6 or more characters. Required." msgstr "" -#: actions/recoverpassword.php:91 actions/recoverpassword.php:97 -msgid "This confirmation code is too old. " +#: actions/register.php:433 +msgid "Same as password above. Required." msgstr "" -#: actions/recoverpassword.php:141 actions/recoverpassword.php:152 -msgid "If you've forgotten or lost your" +#: actions/register.php:437 actions/register.php:441 +#: lib/accountsettingsaction.php:117 +msgid "Email" msgstr "" -#: actions/recoverpassword.php:154 actions/recoverpassword.php:158 -msgid "You've been identified. Enter a " +#: actions/register.php:438 actions/register.php:442 +msgid "Used only for updates, announcements, and password recovery" msgstr "" -#: actions/recoverpassword.php:169 actions/recoverpassword.php:188 -msgid "Your nickname on this server, " +#: actions/register.php:449 +msgid "Longer name, preferably your \"real\" name" msgstr "" -#: actions/recoverpassword.php:271 actions/recoverpassword.php:304 -msgid "Instructions for recovering your password " +#: actions/register.php:493 +msgid "My text and files are available under " msgstr "" -#: actions/recoverpassword.php:327 actions/recoverpassword.php:361 -msgid "New password successfully saved. " +#: actions/register.php:495 +msgid "Creative Commons Attribution 3.0" msgstr "" -#: actions/register.php:95 actions/register.php:180 -#: actions/passwordsettings.php:147 actions/register.php:217 -#: actions/passwordsettings.php:153 actions/register.php:224 -#: actions/register.php:230 -msgid "Password must be 6 or more characters." +#: actions/register.php:496 +msgid "" +" except this private data: password, email address, IM address, and phone " +"number." msgstr "" -#: actions/register.php:216 +#: actions/register.php:537 #, php-format msgid "" "Congratulations, %s! And welcome to %%%%site.name%%%%. From here, you may " -"want to..." +"want to...\n" +"\n" +"* Go to [your profile](%s) and post your first message.\n" +"* Add a [Jabber/GTalk address](%%%%action.imsettings%%%%) so you can send " +"notices through instant messages.\n" +"* [Search for users](%%%%action.peoplesearch%%%%) that you may know or that " +"share your interests. \n" +"* Update your [profile settings](%%%%action.profilesettings%%%%) to tell " +"others more about you. \n" +"* Read over the [online docs](%%%%doc.help%%%%) for features you may have " +"missed. \n" +"\n" +"Thanks for signing up and we hope you enjoy using this service." msgstr "" -#: actions/register.php:227 -msgid "(You should receive a message by email momentarily, with " +#: actions/register.php:561 +msgid "" +"(You should receive a message by email momentarily, with instructions on how " +"to confirm your email address.)" msgstr "" -#: actions/remotesubscribe.php:51 actions/remotesubscribe.php:74 +#: actions/remotesubscribe.php:98 #, php-format -msgid "To subscribe, you can [login](%%action.login%%)," +msgid "" +"To subscribe, you can [login](%%action.login%%), or [register](%%action." +"register%%) a new account. If you already have an account on a [compatible " +"microblogging site](%%doc.openmublog%%), enter your profile URL below." msgstr "" -#: actions/showfavorites.php:61 actions/showfavorites.php:145 -#: actions/showfavorites.php:147 -#, php-format -msgid "Feed for favorites of %s" +#: actions/remotesubscribe.php:112 +msgid "Remote subscribe" msgstr "" -#: actions/showfavorites.php:84 actions/twitapifavorites.php:85 -#: actions/showfavorites.php:202 actions/twitapifavorites.php:59 -#: actions/showfavorites.php:179 actions/showfavorites.php:209 -#: actions/showfavorites.php:132 -msgid "Could not retrieve favorite notices." +#: actions/remotesubscribe.php:124 +msgid "Subscribe to a remote user" msgstr "" -#: actions/showmessage.php:33 actions/showmessage.php:81 -msgid "No such message." +#: actions/remotesubscribe.php:129 +msgid "User nickname" msgstr "" -#: actions/showmessage.php:42 actions/showmessage.php:98 -msgid "Only the sender and recipient may read this message." +#: actions/remotesubscribe.php:130 +msgid "Nickname of the user you want to follow" msgstr "" -#: actions/showmessage.php:61 actions/showmessage.php:108 -#, php-format -msgid "Message to %1$s on %2$s" +#: actions/remotesubscribe.php:133 +msgid "Profile URL" msgstr "" -#: actions/showmessage.php:66 actions/showmessage.php:113 -#, php-format -msgid "Message from %1$s on %2$s" +#: actions/remotesubscribe.php:134 +msgid "URL of your profile on another compatible microblogging service" msgstr "" -#: actions/showstream.php:154 -msgid "Send a message" +#: actions/remotesubscribe.php:137 lib/subscribeform.php:139 +#: lib/userprofile.php:321 +msgid "Subscribe" msgstr "" -#: actions/smssettings.php:312 actions/smssettings.php:464 -#, php-format -msgid "Mobile carrier for your phone. " +#: actions/remotesubscribe.php:159 +msgid "Invalid profile URL (bad format)" msgstr "" -#: actions/twitapidirect_messages.php:76 actions/twitapidirect_messages.php:68 -#: actions/twitapidirect_messages.php:67 actions/twitapidirect_messages.php:53 -#: actions/apidirectmessage.php:101 -#, php-format -msgid "Direct messages to %s" +#: actions/remotesubscribe.php:168 +msgid "" +"Not a valid profile URL (no YADIS document or no or invalid XRDS defined)." msgstr "" -#: actions/twitapidirect_messages.php:77 actions/twitapidirect_messages.php:69 -#: actions/twitapidirect_messages.php:68 actions/twitapidirect_messages.php:54 -#: actions/apidirectmessage.php:105 -#, php-format -msgid "All the direct messages sent to %s" +#: actions/remotesubscribe.php:176 +msgid "That’s a local profile! Login to subscribe." msgstr "" -#: actions/twitapidirect_messages.php:81 actions/twitapidirect_messages.php:73 -#: actions/twitapidirect_messages.php:72 actions/twitapidirect_messages.php:59 -msgid "Direct Messages You've Sent" +#: actions/remotesubscribe.php:183 +msgid "Couldn’t get a request token." msgstr "" -#: actions/twitapidirect_messages.php:82 actions/twitapidirect_messages.php:74 -#: actions/twitapidirect_messages.php:73 actions/twitapidirect_messages.php:60 -#: actions/apidirectmessage.php:93 +#: actions/replies.php:125 actions/repliesrss.php:68 +#: lib/personalgroupnav.php:105 #, php-format -msgid "All the direct messages sent from %s" -msgstr "" - -#: actions/twitapidirect_messages.php:128 -#: actions/twitapidirect_messages.php:137 -#: actions/twitapidirect_messages.php:146 -#: actions/twitapidirect_messages.php:140 actions/apidirectmessagenew.php:126 -msgid "No message text!" +msgid "Replies to %s" msgstr "" -#: actions/twitapidirect_messages.php:138 -#: actions/twitapidirect_messages.php:150 -#: actions/twitapidirect_messages.php:159 -#: actions/twitapidirect_messages.php:154 actions/apidirectmessagenew.php:146 -msgid "Recipient user not found." +#: actions/replies.php:127 +#, php-format +msgid "Replies to %s, page %d" msgstr "" -#: actions/twitapidirect_messages.php:141 -#: actions/twitapidirect_messages.php:153 -#: actions/twitapidirect_messages.php:162 -#: actions/twitapidirect_messages.php:158 actions/apidirectmessagenew.php:150 -msgid "Can't send direct messages to users who aren't your friend." +#: actions/replies.php:144 +#, php-format +msgid "Replies feed for %s (RSS 1.0)" msgstr "" -#: actions/twitapifavorites.php:92 actions/twitapifavorites.php:66 -#: actions/twitapifavorites.php:64 actions/twitapifavorites.php:49 -#: actions/apitimelinefavorites.php:107 +#: actions/replies.php:151 #, php-format -msgid "%s / Favorites from %s" +msgid "Replies feed for %s (RSS 2.0)" msgstr "" -#: actions/twitapifavorites.php:95 actions/twitapifavorites.php:69 -#: actions/twitapifavorites.php:68 actions/twitapifavorites.php:55 -#: actions/apitimelinefavorites.php:119 +#: actions/replies.php:158 #, php-format -msgid "%s updates favorited by %s / %s." +msgid "Replies feed for %s (Atom)" msgstr "" -#: actions/twitapifavorites.php:187 lib/mail.php:275 -#: actions/twitapifavorites.php:164 lib/mail.php:553 -#: actions/twitapifavorites.php:170 lib/mail.php:554 -#: actions/twitapifavorites.php:221 +#: actions/replies.php:198 #, php-format -msgid "%s added your notice as a favorite" +msgid "" +"This is the timeline showing replies to %s but %s has not received a notice " +"to his attention yet." msgstr "" -#: actions/twitapifavorites.php:188 lib/mail.php:276 -#: actions/twitapifavorites.php:165 +#: actions/replies.php:203 #, php-format msgid "" -"%1$s just added your notice from %2$s as one of their favorites.\n" -"\n" +"You can engage other users in a conversation, subscribe to more users or " +"[join groups](%%action.groups%%)." msgstr "" -#: actions/twittersettings.php:27 +#: actions/replies.php:205 +#, php-format msgid "" -"Add your Twitter account to automatically send your notices to Twitter, " +"You can try to [nudge %s](../%s) or [post something to his or her attention]" +"(%%%%action.newnotice%%%%?status_textarea=%s)." msgstr "" -#: actions/twittersettings.php:41 actions/twittersettings.php:60 -#: actions/twittersettings.php:61 -msgid "Twitter settings" +#: actions/repliesrss.php:72 +#, php-format +msgid "Replies to %1$s on %2$s!" msgstr "" -#: actions/twittersettings.php:48 actions/twittersettings.php:105 -#: actions/twittersettings.php:106 -msgid "Twitter Account" +#: actions/showfavorites.php:79 +#, php-format +msgid "%s's favorite notices, page %d" msgstr "" -#: actions/twittersettings.php:56 actions/twittersettings.php:113 -#: actions/twittersettings.php:114 -msgid "Current verified Twitter account." +#: actions/showfavorites.php:132 +msgid "Could not retrieve favorite notices." msgstr "" -#: actions/twittersettings.php:63 -msgid "Twitter Username" +#: actions/showfavorites.php:170 +#, php-format +msgid "Feed for favorites of %s (RSS 1.0)" msgstr "" -#: actions/twittersettings.php:65 actions/twittersettings.php:123 -#: actions/twittersettings.php:126 -msgid "No spaces, please." +#: actions/showfavorites.php:177 +#, php-format +msgid "Feed for favorites of %s (RSS 2.0)" msgstr "" -#: actions/twittersettings.php:67 -msgid "Twitter Password" +#: actions/showfavorites.php:184 +#, php-format +msgid "Feed for favorites of %s (Atom)" msgstr "" -#: actions/twittersettings.php:72 actions/twittersettings.php:139 -#: actions/twittersettings.php:142 -msgid "Automatically send my notices to Twitter." +#: actions/showfavorites.php:205 +msgid "" +"You haven't chosen any favorite notices yet. Click the fave button on " +"notices you like to bookmark them for later or shed a spotlight on them." msgstr "" -#: actions/twittersettings.php:75 actions/twittersettings.php:146 -#: actions/twittersettings.php:149 -msgid "Send local \"@\" replies to Twitter." +#: actions/showfavorites.php:207 +#, php-format +msgid "" +"%s hasn't added any notices to his favorites yet. Post something interesting " +"they would add to their favorites :)" msgstr "" -#: actions/twittersettings.php:78 actions/twittersettings.php:153 -#: actions/twittersettings.php:156 -msgid "Subscribe to my Twitter friends here." +#: actions/showfavorites.php:211 +#, php-format +msgid "" +"%s hasn't added any notices to his favorites yet. Why not [register an " +"account](%%%%action.register%%%%) and then post something interesting they " +"would add to their favorites :)" msgstr "" -#: actions/twittersettings.php:122 actions/twittersettings.php:331 -#: actions/twittersettings.php:348 -msgid "" -"Username must have only numbers, upper- and lowercase letters, and " -"underscore (_). 15 chars max." +#: actions/showfavorites.php:242 +msgid "This is a way to share what you like." msgstr "" -#: actions/twittersettings.php:128 actions/twittersettings.php:334 -#: actions/twittersettings.php:338 actions/twittersettings.php:355 -msgid "Could not verify your Twitter credentials!" +#: actions/showgroup.php:82 lib/groupnav.php:85 +#, php-format +msgid "%s group" msgstr "" -#: actions/twittersettings.php:137 +#: actions/showgroup.php:84 #, php-format -msgid "Unable to retrieve account information for \"%s\" from Twitter." +msgid "%s group, page %d" msgstr "" -#: actions/twittersettings.php:151 actions/twittersettings.php:170 -#: actions/twittersettings.php:348 actions/twittersettings.php:368 -#: actions/twittersettings.php:352 actions/twittersettings.php:372 -#: actions/twittersettings.php:369 actions/twittersettings.php:389 -msgid "Unable to save your Twitter settings!" +#: actions/showgroup.php:218 +msgid "Group profile" msgstr "" -#: actions/twittersettings.php:174 actions/twittersettings.php:376 -#: actions/twittersettings.php:380 actions/twittersettings.php:399 -msgid "Twitter settings saved." +#: actions/showgroup.php:263 actions/tagother.php:118 +#: actions/userauthorization.php:167 lib/userprofile.php:177 +msgid "URL" msgstr "" -#: actions/twittersettings.php:192 actions/twittersettings.php:395 -#: actions/twittersettings.php:399 actions/twittersettings.php:418 -msgid "That is not your Twitter account." +#: actions/showgroup.php:274 actions/tagother.php:128 +#: actions/userauthorization.php:179 lib/userprofile.php:194 +msgid "Note" msgstr "" -#: actions/twittersettings.php:200 actions/twittersettings.php:208 -#: actions/twittersettings.php:403 actions/twittersettings.php:407 -#: actions/twittersettings.php:426 -msgid "Couldn't remove Twitter user." +#: actions/showgroup.php:284 lib/groupeditform.php:184 +msgid "Aliases" msgstr "" -#: actions/twittersettings.php:212 actions/twittersettings.php:407 -#: actions/twittersettings.php:411 actions/twittersettings.php:430 -msgid "Twitter account removed." +#: actions/showgroup.php:293 +msgid "Group actions" msgstr "" -#: actions/twittersettings.php:225 actions/twittersettings.php:239 -#: actions/twittersettings.php:428 actions/twittersettings.php:439 -#: actions/twittersettings.php:453 actions/twittersettings.php:432 -#: actions/twittersettings.php:443 actions/twittersettings.php:457 -#: actions/twittersettings.php:452 actions/twittersettings.php:463 -#: actions/twittersettings.php:477 -msgid "Couldn't save Twitter preferences." +#: actions/showgroup.php:328 +#, php-format +msgid "Notice feed for %s group (RSS 1.0)" msgstr "" -#: actions/twittersettings.php:245 actions/twittersettings.php:461 -#: actions/twittersettings.php:465 actions/twittersettings.php:485 -msgid "Twitter preferences saved." +#: actions/showgroup.php:334 +#, php-format +msgid "Notice feed for %s group (RSS 2.0)" msgstr "" -#: actions/userauthorization.php:84 actions/userauthorization.php:86 -msgid "Please check these details to make sure " +#: actions/showgroup.php:340 +#, php-format +msgid "Notice feed for %s group (Atom)" msgstr "" -#: actions/userauthorization.php:324 actions/userauthorization.php:340 -msgid "The subscription has been authorized, but no " +#: actions/showgroup.php:345 +#, php-format +msgid "FOAF for %s group" msgstr "" -#: actions/userauthorization.php:334 actions/userauthorization.php:351 -msgid "The subscription has been rejected, but no " +#: actions/showgroup.php:381 actions/showgroup.php:438 lib/groupnav.php:90 +msgid "Members" msgstr "" -#: classes/Channel.php:113 classes/Channel.php:132 classes/Channel.php:151 -#: lib/channel.php:138 lib/channel.php:158 -msgid "Command results" +#: actions/showgroup.php:386 lib/profileaction.php:117 +#: lib/profileaction.php:148 lib/profileaction.php:226 lib/section.php:95 +#: lib/tagcloudsection.php:71 +msgid "(None)" msgstr "" -#: classes/Channel.php:148 classes/Channel.php:204 lib/channel.php:210 -msgid "Command complete" +#: actions/showgroup.php:392 +msgid "All members" msgstr "" -#: classes/Channel.php:158 classes/Channel.php:215 lib/channel.php:221 -msgid "Command failed" +#: actions/showgroup.php:429 lib/profileaction.php:173 +msgid "Statistics" msgstr "" -#: classes/Command.php:39 classes/Command.php:44 lib/command.php:44 -msgid "Sorry, this command is not yet implemented." +#: actions/showgroup.php:432 +msgid "Created" msgstr "" -#: classes/Command.php:96 classes/Command.php:113 +#: actions/showgroup.php:448 #, php-format -msgid "Subscriptions: %1$s\n" +msgid "" +"**%s** is a user group on %%%%site.name%%%%, a [micro-blogging](http://en." +"wikipedia.org/wiki/Micro-blogging) service based on the Free Software " +"[StatusNet](http://status.net/) tool. Its members share short messages about " +"their life and interests. [Join now](%%%%action.register%%%%) to become part " +"of this group and many more! ([Read more](%%%%doc.help%%%%))" msgstr "" -#: classes/Command.php:125 classes/Command.php:242 classes/Command.php:145 -#: classes/Command.php:276 lib/command.php:145 lib/command.php:276 -#: lib/command.php:138 lib/command.php:269 lib/command.php:168 -#: lib/command.php:416 lib/command.php:471 -msgid "User has no last notice" +#: actions/showgroup.php:454 +#, php-format +msgid "" +"**%s** is a user group on %%%%site.name%%%%, a [micro-blogging](http://en." +"wikipedia.org/wiki/Micro-blogging) service based on the Free Software " +"[StatusNet](http://status.net/) tool. Its members share short messages about " +"their life and interests. " msgstr "" -#: classes/Command.php:146 classes/Command.php:166 lib/command.php:166 -#: lib/command.php:159 lib/command.php:190 -msgid "Notice marked as fave." +#: actions/showgroup.php:482 +msgid "Admins" msgstr "" -#: classes/Command.php:166 classes/Command.php:189 lib/command.php:189 -#: lib/command.php:182 lib/command.php:315 -#, php-format -msgid "%1$s (%2$s)" +#: actions/showmessage.php:81 +msgid "No such message." msgstr "" -#: classes/Command.php:169 classes/Command.php:192 lib/command.php:192 -#: lib/command.php:185 lib/command.php:318 -#, php-format -msgid "Fullname: %s" +#: actions/showmessage.php:98 +msgid "Only the sender and recipient may read this message." msgstr "" -#: classes/Command.php:172 classes/Command.php:195 lib/command.php:195 -#: lib/command.php:188 lib/command.php:321 +#: actions/showmessage.php:108 #, php-format -msgid "Location: %s" +msgid "Message to %1$s on %2$s" msgstr "" -#: classes/Command.php:175 classes/Command.php:198 lib/command.php:198 -#: lib/command.php:191 lib/command.php:324 +#: actions/showmessage.php:113 #, php-format -msgid "Homepage: %s" +msgid "Message from %1$s on %2$s" msgstr "" -#: classes/Command.php:178 classes/Command.php:201 lib/command.php:201 -#: lib/command.php:194 lib/command.php:327 -#, php-format -msgid "About: %s" +#: actions/shownotice.php:90 +msgid "Notice deleted." msgstr "" -#: classes/Command.php:200 classes/Command.php:228 lib/command.php:228 -#: lib/command.php:221 +#: actions/showstream.php:73 #, php-format -msgid "Message too long - maximum is 140 characters, you sent %d" +msgid " tagged %s" msgstr "" -#: classes/Command.php:214 classes/Command.php:245 lib/command.php:245 -#: actions/newmessage.php:182 lib/command.php:238 actions/newmessage.php:185 -#: lib/command.php:375 +#: actions/showstream.php:79 #, php-format -msgid "Direct message to %s sent" -msgstr "" - -#: classes/Command.php:216 classes/Command.php:247 lib/command.php:247 -#: lib/command.php:240 lib/command.php:377 -msgid "Error sending direct message." -msgstr "" - -#: classes/Command.php:263 classes/Command.php:300 lib/command.php:300 -#: lib/command.php:293 lib/command.php:495 -msgid "Specify the name of the user to subscribe to" +msgid "%s, page %d" msgstr "" -#: classes/Command.php:270 classes/Command.php:307 lib/command.php:307 -#: lib/command.php:300 lib/command.php:502 +#: actions/showstream.php:122 #, php-format -msgid "Subscribed to %s" -msgstr "" - -#: classes/Command.php:288 classes/Command.php:328 lib/command.php:328 -#: lib/command.php:321 lib/command.php:523 -msgid "Specify the name of the user to unsubscribe from" +msgid "Notice feed for %s tagged %s (RSS 1.0)" msgstr "" -#: classes/Command.php:295 classes/Command.php:335 lib/command.php:335 -#: lib/command.php:328 lib/command.php:530 +#: actions/showstream.php:129 #, php-format -msgid "Unsubscribed from %s" -msgstr "" - -#: classes/Command.php:310 classes/Command.php:330 classes/Command.php:353 -#: classes/Command.php:376 lib/command.php:353 lib/command.php:376 -#: lib/command.php:346 lib/command.php:369 lib/command.php:548 -#: lib/command.php:571 -msgid "Command not yet implemented." -msgstr "" - -#: classes/Command.php:313 classes/Command.php:356 lib/command.php:356 -#: lib/command.php:349 lib/command.php:551 -msgid "Notification off." -msgstr "" - -#: classes/Command.php:315 classes/Command.php:358 lib/command.php:358 -#: lib/command.php:351 lib/command.php:553 -msgid "Can't turn off notification." -msgstr "" - -#: classes/Command.php:333 classes/Command.php:379 lib/command.php:379 -#: lib/command.php:372 lib/command.php:574 -msgid "Notification on." +msgid "Notice feed for %s (RSS 1.0)" msgstr "" -#: classes/Command.php:335 classes/Command.php:381 lib/command.php:381 -#: lib/command.php:374 lib/command.php:576 -msgid "Can't turn on notification." +#: actions/showstream.php:136 +#, php-format +msgid "Notice feed for %s (RSS 2.0)" msgstr "" -#: classes/Command.php:344 classes/Command.php:392 -msgid "Commands:\n" +#: actions/showstream.php:143 +#, php-format +msgid "Notice feed for %s (Atom)" msgstr "" -#: classes/Message.php:53 classes/Message.php:56 classes/Message.php:55 -msgid "Could not insert message." +#: actions/showstream.php:148 +#, php-format +msgid "FOAF for %s" msgstr "" -#: classes/Message.php:63 classes/Message.php:66 classes/Message.php:65 -msgid "Could not update message with new URI." +#: actions/showstream.php:191 +#, php-format +msgid "This is the timeline for %s but %s hasn't posted anything yet." msgstr "" -#: lib/gallery.php:46 -msgid "User without matching profile in system." +#: actions/showstream.php:196 +msgid "" +"Seen anything interesting recently? You haven't posted any notices yet, now " +"would be a good time to start :)" msgstr "" -#: lib/mail.php:147 lib/mail.php:289 +#: actions/showstream.php:198 #, php-format msgid "" -"You have a new posting address on %1$s.\n" -"\n" +"You can try to nudge %s or [post something to his or her attention](%%%%" +"action.newnotice%%%%?status_textarea=%s)." msgstr "" -#: lib/mail.php:249 lib/mail.php:508 lib/mail.php:509 +#: actions/showstream.php:234 #, php-format -msgid "New private message from %s" +msgid "" +"**%s** has an account on %%%%site.name%%%%, a [micro-blogging](http://en." +"wikipedia.org/wiki/Micro-blogging) service based on the Free Software " +"[StatusNet](http://status.net/) tool. [Join now](%%%%action.register%%%%) to " +"follow **%s**'s notices and many more! ([Read more](%%%%doc.help%%%%))" msgstr "" -#: lib/mail.php:253 lib/mail.php:512 +#: actions/showstream.php:239 #, php-format msgid "" -"%1$s (%2$s) sent you a private message:\n" -"\n" -msgstr "" - -#: lib/mailbox.php:43 lib/mailbox.php:89 lib/mailbox.php:91 -msgid "Only the user can read their own mailboxes." +"**%s** has an account on %%%%site.name%%%%, a [micro-blogging](http://en." +"wikipedia.org/wiki/Micro-blogging) service based on the Free Software " +"[StatusNet](http://status.net/) tool. " msgstr "" -#: lib/openid.php:195 lib/openid.php:203 -msgid "This form should automatically submit itself. " +#: actions/smssettings.php:58 +msgid "SMS Settings" msgstr "" -#: lib/personal.php:65 lib/personalgroupnav.php:113 -#: lib/personalgroupnav.php:114 -msgid "Favorites" +#: actions/smssettings.php:69 +#, php-format +msgid "You can receive SMS messages through email from %%site.name%%." msgstr "" -#: lib/personal.php:66 lib/personalgroupnav.php:114 -#: actions/favoritesrss.php:110 actions/showfavorites.php:77 -#: lib/personalgroupnav.php:115 actions/favoritesrss.php:111 -#, php-format -msgid "%s's favorite notices" +#: actions/smssettings.php:91 +msgid "SMS is not available." msgstr "" -#: lib/personal.php:66 lib/personalgroupnav.php:114 -#: lib/personalgroupnav.php:115 -msgid "User" +#: actions/smssettings.php:104 +msgid "SMS address" msgstr "" -#: lib/personal.php:75 lib/personalgroupnav.php:123 -#: lib/personalgroupnav.php:124 -msgid "Inbox" +#: actions/smssettings.php:112 +msgid "Current confirmed SMS-enabled phone number." msgstr "" -#: lib/personal.php:76 lib/personalgroupnav.php:124 -#: lib/personalgroupnav.php:125 -msgid "Your incoming messages" +#: actions/smssettings.php:123 +msgid "Awaiting confirmation on this phone number." msgstr "" -#: lib/personal.php:80 lib/personalgroupnav.php:128 -#: lib/personalgroupnav.php:129 -msgid "Outbox" +#: actions/smssettings.php:130 +msgid "Confirmation code" msgstr "" -#: lib/personal.php:81 lib/personalgroupnav.php:129 -#: lib/personalgroupnav.php:130 -msgid "Your sent messages" +#: actions/smssettings.php:131 +msgid "Enter the code you received on your phone." msgstr "" -#: lib/settingsaction.php:99 lib/connectsettingsaction.php:110 -msgid "Twitter" +#: actions/smssettings.php:138 +msgid "SMS Phone number" msgstr "" -#: lib/settingsaction.php:100 lib/connectsettingsaction.php:111 -msgid "Twitter integration options" +#: actions/smssettings.php:140 +msgid "Phone number, no punctuation or spaces, with area code" msgstr "" -#: lib/util.php:1718 lib/messageform.php:139 lib/noticelist.php:422 -#: lib/messageform.php:137 lib/noticelist.php:425 lib/messageform.php:135 -#: lib/noticelist.php:433 lib/messageform.php:146 -msgid "To" +#: actions/smssettings.php:174 +msgid "" +"Send me notices through SMS; I understand I may incur exorbitant charges " +"from my carrier." msgstr "" -#: scripts/maildaemon.php:45 scripts/maildaemon.php:48 -#: scripts/maildaemon.php:47 -msgid "Could not parse message." +#: actions/smssettings.php:306 +msgid "No phone number." msgstr "" -#: actions/all.php:63 actions/facebookhome.php:162 actions/all.php:66 -#: actions/facebookhome.php:161 actions/all.php:48 -#: actions/facebookhome.php:156 actions/all.php:84 -#, php-format -msgid "%s and friends, page %d" +#: actions/smssettings.php:311 +msgid "No carrier selected." msgstr "" -#: actions/avatarsettings.php:76 -msgid "You can upload your personal avatar." +#: actions/smssettings.php:318 +msgid "That is already your phone number." msgstr "" -#: actions/avatarsettings.php:117 actions/avatarsettings.php:191 -#: actions/grouplogo.php:250 actions/avatarsettings.php:119 -#: actions/avatarsettings.php:194 actions/grouplogo.php:256 -#: actions/grouplogo.php:251 -msgid "Avatar settings" +#: actions/smssettings.php:321 +msgid "That phone number already belongs to another user." msgstr "" -#: actions/avatarsettings.php:124 actions/avatarsettings.php:199 -#: actions/grouplogo.php:198 actions/grouplogo.php:258 -#: actions/avatarsettings.php:126 actions/avatarsettings.php:202 -#: actions/grouplogo.php:204 actions/grouplogo.php:264 -#: actions/grouplogo.php:199 actions/grouplogo.php:259 -msgid "Original" +#: actions/smssettings.php:347 +msgid "" +"A confirmation code was sent to the phone number you added. Check your phone " +"for the code and instructions on how to use it." msgstr "" -#: actions/avatarsettings.php:139 actions/avatarsettings.php:211 -#: actions/grouplogo.php:209 actions/grouplogo.php:270 -#: actions/avatarsettings.php:141 actions/avatarsettings.php:214 -#: actions/grouplogo.php:215 actions/grouplogo.php:276 -#: actions/grouplogo.php:210 actions/grouplogo.php:271 -msgid "Preview" +#: actions/smssettings.php:374 +msgid "That is the wrong confirmation number." msgstr "" -#: actions/avatarsettings.php:225 actions/grouplogo.php:284 -#: actions/avatarsettings.php:228 actions/grouplogo.php:291 -#: actions/grouplogo.php:286 -msgid "Crop" +#: actions/smssettings.php:405 +msgid "That is not your phone number." msgstr "" -#: actions/avatarsettings.php:248 actions/deletenotice.php:133 -#: actions/emailsettings.php:224 actions/grouplogo.php:307 -#: actions/imsettings.php:200 actions/login.php:102 actions/newmessage.php:100 -#: actions/newnotice.php:96 actions/openidsettings.php:188 -#: actions/othersettings.php:136 actions/passwordsettings.php:131 -#: actions/profilesettings.php:172 actions/register.php:113 -#: actions/remotesubscribe.php:53 actions/smssettings.php:216 -#: actions/subedit.php:38 actions/twittersettings.php:290 -#: actions/userauthorization.php:39 -msgid "There was a problem with your session token. " +#: actions/smssettings.php:465 +msgid "Mobile carrier" msgstr "" -#: actions/avatarsettings.php:303 actions/grouplogo.php:360 -#: actions/avatarsettings.php:308 actions/avatarsettings.php:322 -msgid "Pick a square area of the image to be your avatar" +#: actions/smssettings.php:469 +msgid "Select a carrier" msgstr "" -#: actions/avatarsettings.php:327 actions/grouplogo.php:384 -#: actions/avatarsettings.php:323 actions/grouplogo.php:382 -#: actions/grouplogo.php:377 actions/avatarsettings.php:337 -msgid "Lost our file data." +#: actions/smssettings.php:476 +#, php-format +msgid "" +"Mobile carrier for your phone. If you know a carrier that accepts SMS over " +"email but isn't listed here, send email to let us know at %s." msgstr "" -#: actions/avatarsettings.php:334 actions/grouplogo.php:391 -#: classes/User_group.php:112 lib/imagefile.php:112 lib/imagefile.php:113 -#: lib/imagefile.php:118 -msgid "Lost our file." +#: actions/smssettings.php:498 +msgid "No code entered" msgstr "" -#: actions/avatarsettings.php:349 actions/avatarsettings.php:383 -#: actions/grouplogo.php:406 actions/grouplogo.php:440 -#: classes/User_group.php:129 classes/User_group.php:161 lib/imagefile.php:144 -#: lib/imagefile.php:191 lib/imagefile.php:145 lib/imagefile.php:192 -#: lib/imagefile.php:150 lib/imagefile.php:197 -msgid "Unknown file type" +#: actions/subedit.php:70 +msgid "You are not subscribed to that profile." msgstr "" -#: actions/block.php:69 actions/subedit.php:46 actions/unblock.php:70 -#: actions/groupblock.php:71 actions/groupunblock.php:71 -#: actions/makeadmin.php:71 -msgid "No profile specified." +#: actions/subedit.php:83 +msgid "Could not save subscription." msgstr "" -#: actions/block.php:74 actions/subedit.php:53 actions/tagother.php:46 -#: actions/unblock.php:75 actions/groupblock.php:76 -#: actions/groupunblock.php:76 actions/makeadmin.php:76 -msgid "No profile with that ID." +#: actions/subscribe.php:55 +msgid "Not a local user." msgstr "" -#: actions/block.php:111 actions/block.php:134 -msgid "Block user" +#: actions/subscribe.php:69 +msgid "Subscribed" msgstr "" -#: actions/block.php:129 -msgid "Are you sure you want to block this user? " +#: actions/subscribers.php:50 +#, php-format +msgid "%s subscribers" msgstr "" -#: actions/block.php:162 actions/block.php:165 -msgid "You have already blocked this user." +#: actions/subscribers.php:52 +#, php-format +msgid "%s subscribers, page %d" msgstr "" -#: actions/block.php:167 actions/block.php:170 -msgid "Failed to save block information." +#: actions/subscribers.php:63 +msgid "These are the users who have subscribed to your notices." msgstr "" -#: actions/confirmaddress.php:159 +#: actions/subscribers.php:67 #, php-format -msgid "The address \"%s\" has been " +msgid "These are the users who have subscribed to %s's notices." msgstr "" -#: actions/deletenotice.php:73 -msgid "You are about to permanently delete a notice. " +#: actions/subscribers.php:108 +msgid "" +"You have no subscribers. Try subscribing to users you know and they might " +"return the favor" msgstr "" -#: actions/disfavor.php:94 -msgid "Add to favorites" +#: actions/subscribers.php:110 +#, php-format +msgid "%s has no subscribers. Want to be the first?" msgstr "" -#: actions/editgroup.php:54 actions/editgroup.php:56 +#: actions/subscribers.php:114 #, php-format -msgid "Edit %s group" +msgid "" +"%s has no subscribers. Why not [register an account](%%%%action.register%%%" +"%) and be the first?" msgstr "" -#: actions/editgroup.php:66 actions/groupbyid.php:72 actions/grouplogo.php:66 -#: actions/joingroup.php:60 actions/newgroup.php:65 actions/showgroup.php:100 -#: actions/grouplogo.php:70 actions/grouprss.php:80 actions/editgroup.php:68 -#: actions/groupdesignsettings.php:68 actions/showgroup.php:105 -msgid "Inboxes must be enabled for groups to work" +#: actions/subscriptions.php:52 +#, php-format +msgid "%s subscriptions" msgstr "" -#: actions/editgroup.php:71 actions/grouplogo.php:71 actions/newgroup.php:70 -#: actions/grouplogo.php:75 actions/editgroup.php:73 actions/editgroup.php:68 -#: actions/grouplogo.php:70 actions/newgroup.php:65 -msgid "You must be logged in to create a group." +#: actions/subscriptions.php:54 +#, php-format +msgid "%s subscriptions, page %d" msgstr "" -#: actions/editgroup.php:87 actions/grouplogo.php:87 -#: actions/groupmembers.php:76 actions/joingroup.php:81 -#: actions/showgroup.php:121 actions/grouplogo.php:91 actions/grouprss.php:96 -#: actions/blockedfromgroup.php:73 actions/editgroup.php:89 -#: actions/groupdesignsettings.php:89 actions/showgroup.php:126 -#: actions/editgroup.php:84 actions/groupdesignsettings.php:84 -#: actions/grouplogo.php:86 actions/grouprss.php:91 actions/joingroup.php:76 -msgid "No nickname" +#: actions/subscriptions.php:65 +msgid "These are the users whose notices you have subscribed to." msgstr "" -#: actions/editgroup.php:99 actions/groupbyid.php:88 actions/grouplogo.php:100 -#: actions/groupmembers.php:83 actions/joingroup.php:88 -#: actions/showgroup.php:128 actions/grouplogo.php:104 -#: actions/grouprss.php:103 actions/blockedfromgroup.php:80 -#: actions/editgroup.php:101 actions/groupdesignsettings.php:102 -#: actions/showgroup.php:133 actions/editgroup.php:96 actions/groupbyid.php:83 -#: actions/groupdesignsettings.php:97 actions/grouplogo.php:99 -#: actions/grouprss.php:98 actions/joingroup.php:83 actions/showgroup.php:137 -msgid "No such group" +#: actions/subscriptions.php:69 +#, php-format +msgid "These are the users whose notices %s has subscribed to." msgstr "" -#: actions/editgroup.php:106 actions/editgroup.php:165 -#: actions/grouplogo.php:107 actions/grouplogo.php:111 -#: actions/editgroup.php:108 actions/editgroup.php:167 -#: actions/groupdesignsettings.php:109 actions/editgroup.php:103 -#: actions/editgroup.php:168 actions/groupdesignsettings.php:104 -#: actions/grouplogo.php:106 -msgid "You must be an admin to edit the group" +#: actions/subscriptions.php:121 +#, php-format +msgid "" +"You have not subscribed to anyone's notices right now. Try subscribing to " +"users you know. Try [user search](%%action.peoplesearch%%), look for members " +"in groups you're interested in and in our [featured users](%%action.featured%" +"%). If you are a [Twitter user](%%action.twittersettings%%), you can " +"automatically subscribe to users you already follow there." msgstr "" -#: actions/editgroup.php:157 actions/editgroup.php:159 -#: actions/editgroup.php:154 -msgid "Use this form to edit the group." +#: actions/subscriptions.php:123 actions/subscriptions.php:127 +#, php-format +msgid "%s is not listening to anyone." msgstr "" -#: actions/editgroup.php:179 actions/newgroup.php:130 actions/register.php:156 -msgid "Nickname must have only lowercase letters " +#: actions/subscriptions.php:194 +msgid "Jabber" msgstr "" -#: actions/editgroup.php:198 actions/newgroup.php:149 -#: actions/editgroup.php:200 actions/newgroup.php:150 -msgid "description is too long (max 140 chars)." +#: actions/subscriptions.php:199 lib/connectsettingsaction.php:115 +msgid "SMS" msgstr "" -#: actions/editgroup.php:218 actions/editgroup.php:253 -msgid "Could not update group." +#: actions/tagother.php:33 +msgid "Not logged in" msgstr "" -#: actions/editgroup.php:226 actions/editgroup.php:269 -msgid "Options saved." +#: actions/tagother.php:39 +msgid "No id argument." msgstr "" -#: actions/emailsettings.php:107 actions/imsettings.php:108 +#: actions/tagother.php:65 #, php-format -msgid "Awaiting confirmation on this address. " +msgid "Tag %s" msgstr "" -#: actions/emailsettings.php:139 actions/smssettings.php:150 -msgid "Make a new email address for posting to; " +#: actions/tagother.php:77 lib/userprofile.php:75 +msgid "User profile" msgstr "" -#: actions/emailsettings.php:157 -msgid "Send me email when someone " +#: actions/tagother.php:81 lib/userprofile.php:102 +msgid "Photo" msgstr "" -#: actions/emailsettings.php:168 actions/emailsettings.php:173 -#: actions/emailsettings.php:179 -msgid "Allow friends to nudge me and send me an email." +#: actions/tagother.php:141 +msgid "Tag user" msgstr "" -#: actions/emailsettings.php:321 -msgid "That email address already belongs " +#: actions/tagother.php:151 +msgid "" +"Tags for this user (letters, numbers, -, ., and _), comma- or space- " +"separated" msgstr "" -#: actions/emailsettings.php:343 -msgid "A confirmation code was sent to the email address you added. " +#: actions/tagother.php:193 +msgid "" +"You can only tag users you are subscribed to or who are subscribed to you." msgstr "" -#: actions/facebookhome.php:110 actions/facebookhome.php:109 -msgid "Server error - couldn't get user!" +#: actions/tagother.php:200 +msgid "Could not save tags." msgstr "" -#: actions/facebookhome.php:196 -#, php-format -msgid "If you would like the %s app to automatically update " +#: actions/tagother.php:236 +msgid "Use this form to add tags to your subscribers or subscriptions." msgstr "" -#: actions/facebookhome.php:213 actions/facebooksettings.php:137 +#: actions/tag.php:68 #, php-format -msgid "Allow %s to update my Facebook status" +msgid "Notices tagged with %s, page %d" msgstr "" -#: actions/facebookhome.php:218 actions/facebookhome.php:223 -#: actions/facebookhome.php:217 -msgid "Skip" +#: actions/tag.php:86 +#, php-format +msgid "Notice feed for tag %s (RSS 1.0)" msgstr "" -#: actions/facebookhome.php:235 lib/facebookaction.php:479 -#: lib/facebookaction.php:471 -msgid "No notice content!" +#: actions/tag.php:92 +#, php-format +msgid "Notice feed for tag %s (RSS 2.0)" msgstr "" -#: actions/facebookhome.php:295 lib/action.php:870 lib/facebookaction.php:399 -#: actions/facebookhome.php:253 lib/action.php:973 lib/facebookaction.php:433 -#: actions/facebookhome.php:247 lib/action.php:1037 lib/facebookaction.php:435 -#: lib/action.php:1053 -msgid "Pagination" +#: actions/tag.php:98 +#, php-format +msgid "Notice feed for tag %s (Atom)" msgstr "" -#: actions/facebookhome.php:304 lib/action.php:879 lib/facebookaction.php:408 -#: actions/facebookhome.php:262 lib/action.php:982 lib/facebookaction.php:442 -#: actions/facebookhome.php:256 lib/action.php:1046 lib/facebookaction.php:444 -#: lib/action.php:1062 -msgid "After" +#: actions/tagrss.php:35 +msgid "No such tag." msgstr "" -#: actions/facebookhome.php:312 lib/action.php:887 lib/facebookaction.php:416 -#: actions/facebookhome.php:270 lib/action.php:990 lib/facebookaction.php:450 -#: actions/facebookhome.php:264 lib/action.php:1054 lib/facebookaction.php:452 -#: lib/action.php:1070 -msgid "Before" +#: actions/twitapitrends.php:87 +msgid "API method under construction." msgstr "" -#: actions/facebookinvite.php:70 actions/facebookinvite.php:72 -#, php-format -msgid "Thanks for inviting your friends to use %s" +#: actions/unsubscribe.php:77 +msgid "No profile id in request." msgstr "" -#: actions/facebookinvite.php:72 actions/facebookinvite.php:74 -msgid "Invitations have been sent to the following users:" +#: actions/unsubscribe.php:84 +msgid "No profile with that id." msgstr "" -#: actions/facebookinvite.php:96 actions/facebookinvite.php:102 -#: actions/facebookinvite.php:94 -#, php-format -msgid "You have been invited to %s" +#: actions/unsubscribe.php:98 +msgid "Unsubscribed" msgstr "" -#: actions/facebookinvite.php:105 actions/facebookinvite.php:111 -#: actions/facebookinvite.php:103 +#: actions/updateprofile.php:62 actions/userauthorization.php:330 #, php-format -msgid "Invite your friends to use %s" +msgid "Listenee stream license ‘%s’ is not compatible with site license ‘%s’." msgstr "" -#: actions/facebookinvite.php:113 actions/facebookinvite.php:126 -#: actions/facebookinvite.php:124 -#, php-format -msgid "Friends already using %s:" +#: actions/userauthorization.php:105 +msgid "Authorize subscription" msgstr "" -#: actions/facebookinvite.php:130 actions/facebookinvite.php:143 -#: actions/facebookinvite.php:142 -#, php-format -msgid "Send invitations" +#: actions/userauthorization.php:110 +msgid "" +"Please check these details to make sure that you want to subscribe to this " +"user’s notices. If you didn’t just ask to subscribe to someone’s notices, " +"click “Reject”." msgstr "" -#: actions/facebookremove.php:56 -msgid "Couldn't remove Facebook user." +#: actions/userauthorization.php:188 +msgid "License" msgstr "" -#: actions/facebooksettings.php:65 -msgid "There was a problem saving your sync preferences!" +#: actions/userauthorization.php:209 +msgid "Accept" msgstr "" -#: actions/facebooksettings.php:67 -msgid "Sync preferences saved." +#: actions/userauthorization.php:210 lib/subscribeform.php:115 +#: lib/subscribeform.php:139 +msgid "Subscribe to this user" msgstr "" -#: actions/facebooksettings.php:90 -msgid "Automatically update my Facebook status with my notices." +#: actions/userauthorization.php:211 +msgid "Reject" msgstr "" -#: actions/facebooksettings.php:97 -msgid "Send \"@\" replies to Facebook." +#: actions/userauthorization.php:212 +msgid "Reject this subscription" msgstr "" -#: actions/facebooksettings.php:106 -msgid "Prefix" -msgstr "" - -#: actions/facebooksettings.php:108 -msgid "A string to prefix notices with." +#: actions/userauthorization.php:225 +msgid "No authorization request!" msgstr "" -#: actions/facebooksettings.php:124 -#, php-format -msgid "If you would like %s to automatically update " +#: actions/userauthorization.php:247 +msgid "Subscription authorized" msgstr "" -#: actions/facebooksettings.php:147 -msgid "Sync preferences" +#: actions/userauthorization.php:249 +msgid "" +"The subscription has been authorized, but no callback URL was passed. Check " +"with the site’s instructions for details on how to authorize the " +"subscription. Your subscription token is:" msgstr "" -#: actions/favor.php:94 lib/disfavorform.php:140 actions/favor.php:92 -msgid "Disfavor favorite" +#: actions/userauthorization.php:259 +msgid "Subscription rejected" msgstr "" -#: actions/favorited.php:65 lib/popularnoticesection.php:76 -#: lib/publicgroupnav.php:91 lib/popularnoticesection.php:82 -#: lib/publicgroupnav.php:93 lib/popularnoticesection.php:91 -#: lib/popularnoticesection.php:87 -msgid "Popular notices" +#: actions/userauthorization.php:261 +msgid "" +"The subscription has been rejected, but no callback URL was passed. Check " +"with the site’s instructions for details on how to fully reject the " +"subscription." msgstr "" -#: actions/favorited.php:67 +#: actions/userauthorization.php:296 #, php-format -msgid "Popular notices, page %d" -msgstr "" - -#: actions/favorited.php:79 -msgid "The most popular notices on the site right now." +msgid "Listener URI ‘%s’ not found here" msgstr "" -#: actions/featured.php:69 lib/featureduserssection.php:82 -#: lib/publicgroupnav.php:87 lib/publicgroupnav.php:89 -#: lib/featureduserssection.php:87 -msgid "Featured users" +#: actions/userauthorization.php:301 +#, php-format +msgid "Listenee URI ‘%s’ is too long." msgstr "" -#: actions/featured.php:71 +#: actions/userauthorization.php:307 #, php-format -msgid "Featured users, page %d" +msgid "Listenee URI ‘%s’ is a local user." msgstr "" -#: actions/featured.php:99 +#: actions/userauthorization.php:322 #, php-format -msgid "A selection of some of the great users on %s" +msgid "Profile URL ‘%s’ is for a local user." msgstr "" -#: actions/finishremotesubscribe.php:188 actions/finishremotesubscribe.php:96 -msgid "That user has blocked you from subscribing." +#: actions/userauthorization.php:338 +#, php-format +msgid "Avatar URL ‘%s’ is not valid." msgstr "" -#: actions/groupbyid.php:79 actions/groupbyid.php:74 -msgid "No ID" +#: actions/userauthorization.php:343 +#, php-format +msgid "Can’t read avatar URL ‘%s’." msgstr "" -#: actions/grouplogo.php:138 actions/grouplogo.php:191 -#: actions/grouplogo.php:144 actions/grouplogo.php:197 -#: actions/grouplogo.php:139 actions/grouplogo.php:192 -msgid "Group logo" +#: actions/userauthorization.php:348 +#, php-format +msgid "Wrong image type for avatar URL ‘%s’." msgstr "" -#: actions/grouplogo.php:149 -msgid "You can upload a logo image for your group." +#: actions/userbyid.php:70 +msgid "No id." msgstr "" -#: actions/grouplogo.php:448 actions/grouplogo.php:401 -#: actions/grouplogo.php:396 -msgid "Logo updated." +#: actions/userdesignsettings.php:76 lib/designsettings.php:65 +msgid "Profile design" msgstr "" -#: actions/grouplogo.php:450 actions/grouplogo.php:403 -#: actions/grouplogo.php:398 -msgid "Failed updating logo." +#: actions/userdesignsettings.php:87 lib/designsettings.php:76 +msgid "" +"Customize the way your profile looks with a background image and a colour " +"palette of your choice." msgstr "" -#: actions/groupmembers.php:93 lib/groupnav.php:91 -#, php-format -msgid "%s group members" +#: actions/userdesignsettings.php:282 +msgid "Enjoy your hotdog!" msgstr "" -#: actions/groupmembers.php:96 +#: actions/usergroups.php:64 #, php-format -msgid "%s group members, page %d" +msgid "%s groups, page %d" msgstr "" -#: actions/groupmembers.php:111 -msgid "A list of the users in this group." +#: actions/usergroups.php:130 +msgid "Search for more groups" msgstr "" -#: actions/groups.php:62 actions/showstream.php:518 lib/publicgroupnav.php:79 -#: lib/subgroupnav.php:96 lib/publicgroupnav.php:81 lib/profileaction.php:220 -#: lib/subgroupnav.php:98 -msgid "Groups" +#: actions/usergroups.php:153 +#, php-format +msgid "%s is not a member of any group." msgstr "" -#: actions/groups.php:64 +#: actions/usergroups.php:158 #, php-format -msgid "Groups, page %d" +msgid "Try [searching for groups](%%action.groupsearch%%) and joining them." msgstr "" -#: actions/groups.php:90 +#: classes/File.php:137 #, php-format -msgid "%%%%site.name%%%% groups let you find and talk with " +msgid "" +"No file may be larger than %d bytes and the file you sent was %d bytes. Try " +"to upload a smaller version." msgstr "" -#: actions/groups.php:106 actions/usergroups.php:124 lib/groupeditform.php:123 -#: actions/usergroups.php:125 actions/groups.php:107 lib/groupeditform.php:122 -msgid "Create a new group" +#: classes/File.php:147 +#, php-format +msgid "A file this large would exceed your user quota of %d bytes." msgstr "" -#: actions/groupsearch.php:57 +#: classes/File.php:154 #, php-format -msgid "" -"Search for groups on %%site.name%% by their name, location, or description. " +msgid "A file this large would exceed your monthly quota of %d bytes." msgstr "" -#: actions/groupsearch.php:63 actions/groupsearch.php:58 -msgid "Group search" +#: classes/Message.php:55 +msgid "Could not insert message." msgstr "" -#: actions/imsettings.php:70 -msgid "You can send and receive notices through " +#: classes/Message.php:65 +msgid "Could not update message with new URI." msgstr "" -#: actions/imsettings.php:120 +#: classes/Notice.php:164 #, php-format -msgid "Jabber or GTalk address, " +msgid "DB error inserting hashtag: %s" msgstr "" -#: actions/imsettings.php:147 -msgid "Send me replies through Jabber/GTalk " +#: classes/Notice.php:179 +msgid "Problem saving notice. Too long." msgstr "" -#: actions/imsettings.php:321 -#, php-format -msgid "A confirmation code was sent " +#: classes/Notice.php:183 +msgid "Problem saving notice. Unknown user." msgstr "" -#: actions/joingroup.php:65 actions/joingroup.php:60 -msgid "You must be logged in to join a group." +#: classes/Notice.php:188 +msgid "" +"Too many notices too fast; take a breather and post again in a few minutes." msgstr "" -#: actions/joingroup.php:95 actions/joingroup.php:90 lib/command.php:217 -msgid "You are already a member of that group" +#: classes/Notice.php:194 +msgid "" +"Too many duplicate messages too quickly; take a breather and post again in a " +"few minutes." msgstr "" -#: actions/joingroup.php:128 actions/joingroup.php:133 lib/command.php:234 -#, php-format -msgid "Could not join user %s to group %s" +#: classes/Notice.php:202 +msgid "You are banned from posting notices on this site." +msgstr "" + +#: classes/Notice.php:268 classes/Notice.php:293 +msgid "Problem saving notice." msgstr "" -#: actions/joingroup.php:135 actions/joingroup.php:140 lib/command.php:239 +#: classes/Notice.php:1120 #, php-format -msgid "%s joined group %s" +msgid "DB error inserting reply: %s" msgstr "" -#: actions/leavegroup.php:60 -msgid "Inboxes must be enabled for groups to work." +#: classes/User.php:333 +#, php-format +msgid "Welcome to %1$s, @%2$s!" msgstr "" -#: actions/leavegroup.php:65 actions/leavegroup.php:60 -msgid "You must be logged in to leave a group." +#: lib/accountsettingsaction.php:108 lib/personalgroupnav.php:109 +msgid "Profile" msgstr "" -#: actions/leavegroup.php:88 actions/groupblock.php:86 -#: actions/groupunblock.php:86 actions/makeadmin.php:86 -#: actions/foafgroup.php:44 actions/foafgroup.php:62 actions/leavegroup.php:83 -#: lib/command.php:212 lib/command.php:263 -msgid "No such group." +#: lib/accountsettingsaction.php:109 +msgid "Change your profile settings" msgstr "" -#: actions/leavegroup.php:95 actions/leavegroup.php:90 lib/command.php:268 -msgid "You are not a member of that group." +#: lib/accountsettingsaction.php:112 +msgid "Upload an avatar" msgstr "" -#: actions/leavegroup.php:100 -msgid "You may not leave a group while you are its administrator." +#: lib/accountsettingsaction.php:115 +msgid "Change your password" msgstr "" -#: actions/leavegroup.php:130 actions/leavegroup.php:124 -#: actions/leavegroup.php:119 lib/command.php:278 -msgid "Could not find membership record." +#: lib/accountsettingsaction.php:118 +msgid "Change email handling" msgstr "" -#: actions/leavegroup.php:138 actions/leavegroup.php:132 -#: actions/leavegroup.php:127 lib/command.php:284 -#, php-format -msgid "Could not remove user %s to group %s" +#: lib/accountsettingsaction.php:120 lib/groupnav.php:118 +msgid "Design" msgstr "" -#: actions/leavegroup.php:145 actions/leavegroup.php:139 -#: actions/leavegroup.php:134 lib/command.php:289 -#, php-format -msgid "%s left group %s" +#: lib/accountsettingsaction.php:121 +msgid "Design your profile" msgstr "" -#: actions/login.php:225 lib/facebookaction.php:304 actions/login.php:208 -#: actions/login.php:216 actions/login.php:243 -msgid "Login to site" +#: lib/accountsettingsaction.php:123 +msgid "Other" msgstr "" -#: actions/microsummary.php:69 -msgid "No current status" +#: lib/accountsettingsaction.php:124 +msgid "Other options" msgstr "" -#: actions/newgroup.php:53 -msgid "New group" +#: lib/action.php:144 +#, php-format +msgid "%s - %s" msgstr "" -#: actions/newgroup.php:115 actions/newgroup.php:110 -msgid "Use this form to create a new group." +#: lib/action.php:159 +msgid "Untitled page" msgstr "" -#: actions/newgroup.php:177 actions/newgroup.php:209 -#: actions/apigroupcreate.php:136 actions/newgroup.php:204 -msgid "Could not create group." +#: lib/action.php:424 +msgid "Primary site navigation" msgstr "" -#: actions/newgroup.php:191 actions/newgroup.php:229 -#: actions/apigroupcreate.php:166 actions/newgroup.php:224 -msgid "Could not set group membership." +#: lib/action.php:430 +msgid "Home" msgstr "" -#: actions/newmessage.php:119 actions/newnotice.php:132 -msgid "That's too long. " +#: lib/action.php:430 +msgid "Personal profile and friends timeline" msgstr "" -#: actions/newmessage.php:134 -msgid "Don't send a message to yourself; " +#: lib/action.php:432 +msgid "Account" msgstr "" -#: actions/newnotice.php:166 actions/newnotice.php:174 -#: actions/newnotice.php:272 actions/newnotice.php:199 -msgid "Notice posted" +#: lib/action.php:432 +msgid "Change your email, avatar, password, profile" msgstr "" -#: actions/newnotice.php:200 classes/Channel.php:163 actions/newnotice.php:208 -#: lib/channel.php:170 actions/newmessage.php:207 actions/newnotice.php:387 -#: actions/newmessage.php:210 actions/newnotice.php:233 -msgid "Ajax Error" +#: lib/action.php:435 +msgid "Connect" msgstr "" -#: actions/nudge.php:85 -msgid "" -"This user doesn't allow nudges or hasn't confirmed or set his email yet." +#: lib/action.php:435 +msgid "Connect to services" msgstr "" -#: actions/nudge.php:94 -msgid "Nudge sent" +#: lib/action.php:439 lib/subgroupnav.php:105 +msgid "Invite" msgstr "" -#: actions/nudge.php:97 -msgid "Nudge sent!" +#: lib/action.php:440 lib/subgroupnav.php:106 +#, php-format +msgid "Invite friends and colleagues to join you on %s" msgstr "" -#: actions/openidlogin.php:97 actions/openidlogin.php:106 -msgid "OpenID login" +#: lib/action.php:445 +msgid "Logout" msgstr "" -#: actions/openidsettings.php:128 -msgid "Removing your only OpenID " +#: lib/action.php:445 +msgid "Logout from the site" msgstr "" -#: actions/othersettings.php:60 -msgid "Other Settings" +#: lib/action.php:450 +msgid "Create an account" msgstr "" -#: actions/othersettings.php:71 -msgid "Manage various other options." +#: lib/action.php:453 +msgid "Login to the site" msgstr "" -#: actions/othersettings.php:93 -msgid "URL Auto-shortening" +#: lib/action.php:456 lib/action.php:719 +msgid "Help" msgstr "" -#: actions/othersettings.php:112 -msgid "Service" +#: lib/action.php:456 +msgid "Help me!" msgstr "" -#: actions/othersettings.php:113 actions/othersettings.php:111 -#: actions/othersettings.php:118 -msgid "Automatic shortening service to use." +#: lib/action.php:459 +msgid "Search" msgstr "" -#: actions/othersettings.php:144 actions/othersettings.php:146 -#: actions/othersettings.php:153 -msgid "URL shortening service is too long (max 50 chars)." +#: lib/action.php:459 +msgid "Search for users or text" msgstr "" -#: actions/passwordsettings.php:69 -msgid "Change your password." +#: lib/action.php:480 +msgid "Site notice" msgstr "" -#: actions/passwordsettings.php:89 actions/recoverpassword.php:228 -#: actions/passwordsettings.php:95 actions/recoverpassword.php:231 -msgid "Password change" +#: lib/action.php:546 +msgid "Local views" msgstr "" -#: actions/peopletag.php:35 actions/peopletag.php:70 -#, php-format -msgid "Not a valid people tag: %s" +#: lib/action.php:612 +msgid "Page notice" msgstr "" -#: actions/peopletag.php:47 actions/peopletag.php:144 -#, php-format -msgid "Users self-tagged with %s - page %d" +#: lib/action.php:714 +msgid "Secondary site navigation" msgstr "" -#: actions/peopletag.php:91 -#, php-format -msgid "These are users who have tagged themselves \"%s\" " +#: lib/action.php:721 +msgid "About" msgstr "" -#: actions/profilesettings.php:91 actions/profilesettings.php:99 -msgid "Profile information" +#: lib/action.php:723 +msgid "FAQ" msgstr "" -#: actions/profilesettings.php:124 actions/profilesettings.php:125 -#: actions/profilesettings.php:140 -msgid "" -"Tags for yourself (letters, numbers, -, ., and _), comma- or space- separated" +#: lib/action.php:727 +msgid "TOS" msgstr "" -#: actions/profilesettings.php:144 -msgid "Automatically subscribe to whoever " +#: lib/action.php:730 +msgid "Privacy" msgstr "" -#: actions/profilesettings.php:229 actions/tagother.php:176 -#: actions/tagother.php:178 actions/profilesettings.php:230 -#: actions/profilesettings.php:246 -#, php-format -msgid "Invalid tag: \"%s\"" +#: lib/action.php:732 +msgid "Source" msgstr "" -#: actions/profilesettings.php:311 actions/profilesettings.php:310 -#: actions/profilesettings.php:336 -msgid "Couldn't save tags." +#: lib/action.php:734 +msgid "Contact" msgstr "" -#: actions/public.php:107 actions/public.php:110 actions/public.php:118 -#: actions/public.php:129 -#, php-format -msgid "Public timeline, page %d" +#: lib/action.php:736 +msgid "Badge" msgstr "" -#: actions/public.php:173 actions/public.php:184 actions/public.php:210 -#: actions/public.php:92 -msgid "Could not retrieve public stream." +#: lib/action.php:764 +msgid "StatusNet software license" msgstr "" -#: actions/public.php:220 +#: lib/action.php:767 #, php-format msgid "" -"This is %%site.name%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-" -"blogging) service " +"**%%site.name%%** is a microblogging service brought to you by [%%site." +"broughtby%%](%%site.broughtbyurl%%). " msgstr "" -#: actions/publictagcloud.php:57 -msgid "Public tag cloud" +#: lib/action.php:769 +#, php-format +msgid "**%%site.name%%** is a microblogging service. " msgstr "" -#: actions/publictagcloud.php:63 +#: lib/action.php:771 #, php-format -msgid "These are most popular recent tags on %s " +msgid "" +"It runs the [StatusNet](http://status.net/) microblogging software, version %" +"s, available under the [GNU Affero General Public License](http://www.fsf." +"org/licensing/licenses/agpl-3.0.html)." msgstr "" -#: actions/publictagcloud.php:119 actions/publictagcloud.php:135 -msgid "Tag cloud" +#: lib/action.php:785 +msgid "Site content license" msgstr "" -#: actions/register.php:139 actions/register.php:349 actions/register.php:79 -#: actions/register.php:177 actions/register.php:394 actions/register.php:183 -#: actions/register.php:398 actions/register.php:85 actions/register.php:189 -#: actions/register.php:404 -msgid "Sorry, only invited people can register." +#: lib/action.php:794 +msgid "All " msgstr "" -#: actions/register.php:149 -msgid "You can't register if you don't " +#: lib/action.php:799 +msgid "license." msgstr "" -#: actions/register.php:286 -msgid "With this form you can create " +#: lib/action.php:1053 +msgid "Pagination" msgstr "" -#: actions/register.php:368 -msgid "1-64 lowercase letters or numbers, " +#: lib/action.php:1062 +msgid "After" msgstr "" -#: actions/register.php:382 actions/register.php:386 -msgid "Used only for updates, announcements, " +#: lib/action.php:1070 +msgid "Before" msgstr "" -#: actions/register.php:398 -msgid "URL of your homepage, blog, " -msgstr "" - -#: actions/register.php:404 -msgid "Describe yourself and your " +#: lib/attachmentlist.php:87 +msgid "Attachments" msgstr "" -#: actions/register.php:410 -msgid "Where you are, like \"City, " +#: lib/attachmentlist.php:265 +msgid "Author" msgstr "" -#: actions/register.php:432 -msgid " except this private data: password, " +#: lib/attachmentlist.php:278 +msgid "Provider" msgstr "" -#: actions/register.php:471 -#, php-format -msgid "Congratulations, %s! And welcome to %%%%site.name%%%%. " +#: lib/attachmentnoticesection.php:67 +msgid "Notices where this attachment appears" msgstr "" -#: actions/register.php:495 -msgid "(You should receive a message by email " +#: lib/attachmenttagcloudsection.php:48 +msgid "Tags for this attachment" msgstr "" -#: actions/remotesubscribe.php:166 actions/remotesubscribe.php:171 -msgid "That's a local profile! Login to subscribe." +#: lib/channel.php:138 lib/channel.php:158 +msgid "Command results" msgstr "" -#: actions/replies.php:118 actions/replies.php:120 actions/replies.php:119 -#: actions/replies.php:127 -#, php-format -msgid "Replies to %s, page %d" +#: lib/channel.php:210 +msgid "Command complete" msgstr "" -#: actions/showfavorites.php:79 -#, php-format -msgid "%s favorite notices, page %d" +#: lib/channel.php:221 +msgid "Command failed" msgstr "" -#: actions/showgroup.php:77 lib/groupnav.php:85 actions/showgroup.php:82 -#, php-format -msgid "%s group" +#: lib/command.php:44 +msgid "Sorry, this command is not yet implemented." msgstr "" -#: actions/showgroup.php:79 actions/showgroup.php:84 +#: lib/command.php:88 #, php-format -msgid "%s group, page %d" -msgstr "" - -#: actions/showgroup.php:206 actions/showgroup.php:208 -#: actions/showgroup.php:213 actions/showgroup.php:218 -msgid "Group profile" -msgstr "" - -#: actions/showgroup.php:251 actions/showstream.php:278 -#: actions/tagother.php:119 lib/grouplist.php:134 lib/profilelist.php:133 -#: actions/showgroup.php:253 actions/showstream.php:271 -#: actions/tagother.php:118 lib/profilelist.php:131 actions/showgroup.php:258 -#: actions/showstream.php:236 actions/userauthorization.php:137 -#: lib/profilelist.php:197 actions/showgroup.php:263 -#: actions/showstream.php:295 actions/userauthorization.php:167 -#: lib/profilelist.php:230 lib/userprofile.php:177 -msgid "URL" +msgid "Could not find a user with nickname %s" msgstr "" -#: actions/showgroup.php:262 actions/showstream.php:289 -#: actions/tagother.php:129 lib/grouplist.php:145 lib/profilelist.php:144 -#: actions/showgroup.php:264 actions/showstream.php:282 -#: actions/tagother.php:128 lib/profilelist.php:142 actions/showgroup.php:269 -#: actions/showstream.php:247 actions/userauthorization.php:149 -#: lib/profilelist.php:212 actions/showgroup.php:274 -#: actions/showstream.php:312 actions/userauthorization.php:179 -#: lib/profilelist.php:245 lib/userprofile.php:194 -msgid "Note" +#: lib/command.php:92 +msgid "It does not make a lot of sense to nudge yourself!" msgstr "" -#: actions/showgroup.php:270 actions/showgroup.php:272 -#: actions/showgroup.php:288 actions/showgroup.php:293 -msgid "Group actions" +#: lib/command.php:99 +#, php-format +msgid "Nudge sent to %s" msgstr "" -#: actions/showgroup.php:323 actions/showgroup.php:304 +#: lib/command.php:126 #, php-format -msgid "Notice feed for %s group" +msgid "" +"Subscriptions: %1$s\n" +"Subscribers: %2$s\n" +"Notices: %3$s" msgstr "" -#: actions/showgroup.php:357 lib/groupnav.php:90 actions/showgroup.php:339 -#: actions/showgroup.php:384 actions/showgroup.php:373 -#: actions/showgroup.php:430 actions/showgroup.php:381 -#: actions/showgroup.php:438 -msgid "Members" +#: lib/command.php:152 lib/command.php:400 +msgid "Notice with that id does not exist" msgstr "" -#: actions/showgroup.php:363 actions/showstream.php:413 -#: actions/showstream.php:442 actions/showstream.php:524 lib/section.php:95 -#: lib/tagcloudsection.php:71 actions/showgroup.php:344 -#: actions/showgroup.php:378 lib/profileaction.php:117 -#: lib/profileaction.php:148 lib/profileaction.php:226 -#: actions/showgroup.php:386 -msgid "(None)" +#: lib/command.php:168 lib/command.php:416 lib/command.php:471 +msgid "User has no last notice" msgstr "" -#: actions/showgroup.php:370 actions/showgroup.php:350 -#: actions/showgroup.php:384 actions/showgroup.php:392 -msgid "All members" +#: lib/command.php:190 +msgid "Notice marked as fave." msgstr "" -#: actions/showgroup.php:378 +#: lib/command.php:315 #, php-format -msgid "" -"**%s** is a user group on %%%%site.name%%%%, a [micro-blogging](http://en." -"wikipedia.org/wiki/Micro-blogging) service " +msgid "%1$s (%2$s)" msgstr "" -#: actions/showmessage.php:98 -msgid "Only the sender and recipient " +#: lib/command.php:318 +#, php-format +msgid "Fullname: %s" msgstr "" -#: actions/showstream.php:73 actions/showstream.php:78 -#: actions/showstream.php:79 +#: lib/command.php:321 #, php-format -msgid "%s, page %d" +msgid "Location: %s" msgstr "" -#: actions/showstream.php:143 -msgid "'s profile" +#: lib/command.php:324 +#, php-format +msgid "Homepage: %s" msgstr "" -#: actions/showstream.php:236 actions/tagother.php:77 -#: actions/showstream.php:220 actions/showstream.php:185 -#: actions/showstream.php:193 lib/userprofile.php:75 -msgid "User profile" +#: lib/command.php:327 +#, php-format +msgid "About: %s" msgstr "" -#: actions/showstream.php:240 actions/tagother.php:81 -#: actions/showstream.php:224 actions/showstream.php:189 -#: actions/showstream.php:220 lib/userprofile.php:102 -msgid "Photo" +#: lib/command.php:358 scripts/xmppdaemon.php:321 +#, php-format +msgid "Message too long - maximum is %d characters, you sent %d" msgstr "" -#: actions/showstream.php:317 actions/showstream.php:309 -#: actions/showstream.php:274 actions/showstream.php:354 -#: lib/userprofile.php:236 -msgid "User actions" +#: lib/command.php:377 +msgid "Error sending direct message." msgstr "" -#: actions/showstream.php:342 actions/showstream.php:307 -#: actions/showstream.php:390 lib/userprofile.php:272 -msgid "Send a direct message to this user" +#: lib/command.php:431 +#, php-format +msgid "Notice too long - maximum is %d characters, you sent %d" msgstr "" -#: actions/showstream.php:343 actions/showstream.php:308 -#: actions/showstream.php:391 lib/userprofile.php:273 -msgid "Message" +#: lib/command.php:439 +#, php-format +msgid "Reply to %s sent" msgstr "" -#: actions/showstream.php:451 lib/profileaction.php:157 -msgid "All subscribers" +#: lib/command.php:441 +msgid "Error saving notice." msgstr "" -#: actions/showstream.php:533 lib/profileaction.php:235 -msgid "All groups" +#: lib/command.php:495 +msgid "Specify the name of the user to subscribe to" msgstr "" -#: actions/showstream.php:542 +#: lib/command.php:502 #, php-format -msgid "" -"**%s** has an account on %%%%site.name%%%%, a [micro-blogging](http://en." -"wikipedia.org/wiki/Micro-blogging) service " +msgid "Subscribed to %s" msgstr "" -#: actions/smssettings.php:128 -msgid "Phone number, no punctuation or spaces, " +#: lib/command.php:523 +msgid "Specify the name of the user to unsubscribe from" msgstr "" -#: actions/smssettings.php:162 -msgid "Send me notices through SMS; " +#: lib/command.php:530 +#, php-format +msgid "Unsubscribed from %s" msgstr "" -#: actions/smssettings.php:335 -msgid "A confirmation code was sent to the phone number you added. " +#: lib/command.php:548 lib/command.php:571 +msgid "Command not yet implemented." msgstr "" -#: actions/smssettings.php:453 actions/smssettings.php:465 -msgid "Mobile carrier" +#: lib/command.php:551 +msgid "Notification off." msgstr "" -#: actions/subedit.php:70 -msgid "You are not subscribed to that profile." +#: lib/command.php:553 +msgid "Can't turn off notification." msgstr "" -#: actions/subedit.php:83 -msgid "Could not save subscription." +#: lib/command.php:574 +msgid "Notification on." msgstr "" -#: actions/subscribe.php:55 -msgid "Not a local user." +#: lib/command.php:576 +msgid "Can't turn on notification." msgstr "" -#: actions/subscribe.php:69 -msgid "Subscribed" +#: lib/command.php:597 +#, php-format +msgid "Could not create login token for %s" msgstr "" -#: actions/subscribers.php:50 +#: lib/command.php:602 #, php-format -msgid "%s subscribers" +msgid "This link is useable only once, and is good for only 2 minutes: %s" msgstr "" -#: actions/subscribers.php:52 -#, php-format -msgid "%s subscribers, page %d" +#: lib/command.php:613 +msgid "" +"Commands:\n" +"on - turn on notifications\n" +"off - turn off notifications\n" +"help - show this help\n" +"follow - subscribe to user\n" +"leave - unsubscribe from user\n" +"d - direct message to user\n" +"get - get last notice from user\n" +"whois - get profile info on user\n" +"fav - add user's last notice as a 'fave'\n" +"fav # - add notice with the given id as a 'fave'\n" +"reply # - reply to notice with a given id\n" +"reply - reply to the last notice from user\n" +"join - join group\n" +"login - Get a link to login to the web interface\n" +"drop - leave group\n" +"stats - get your stats\n" +"stop - same as 'off'\n" +"quit - same as 'off'\n" +"sub - same as 'follow'\n" +"unsub - same as 'leave'\n" +"last - same as 'get'\n" +"on - not yet implemented.\n" +"off - not yet implemented.\n" +"nudge - remind a user to update.\n" +"invite - not yet implemented.\n" +"track - not yet implemented.\n" +"untrack - not yet implemented.\n" +"track off - not yet implemented.\n" +"untrack all - not yet implemented.\n" +"tracks - not yet implemented.\n" +"tracking - not yet implemented.\n" msgstr "" -#: actions/subscribers.php:63 -msgid "These are the people who listen to " +#: lib/common.php:191 +msgid "No configuration file found. " msgstr "" -#: actions/subscribers.php:67 -#, php-format -msgid "These are the people who " +#: lib/common.php:192 +msgid "I looked for configuration files in the following places: " msgstr "" -#: actions/subscriptions.php:52 -#, php-format -msgid "%s subscriptions" +#: lib/common.php:193 +msgid "You may wish to run the installer to fix this." msgstr "" -#: actions/subscriptions.php:54 -#, php-format -msgid "%s subscriptions, page %d" +#: lib/common.php:194 +msgid "Go to the installer." msgstr "" -#: actions/subscriptions.php:65 -msgid "These are the people whose notices " +#: lib/connectsettingsaction.php:110 +msgid "IM" msgstr "" -#: actions/subscriptions.php:69 -#, php-format -msgid "These are the people whose " +#: lib/connectsettingsaction.php:111 +msgid "Updates by instant messenger (IM)" msgstr "" -#: actions/subscriptions.php:122 actions/subscriptions.php:124 -#: actions/subscriptions.php:183 actions/subscriptions.php:194 -msgid "Jabber" +#: lib/connectsettingsaction.php:116 +msgid "Updates by SMS" msgstr "" -#: actions/tag.php:43 actions/tag.php:51 actions/tag.php:59 actions/tag.php:68 -#, php-format -msgid "Notices tagged with %s, page %d" +#: lib/dberroraction.php:60 +msgid "Database error" msgstr "" -#: actions/tag.php:66 actions/tag.php:73 -#, php-format -msgid "Messages tagged \"%s\", most recent first" +#: lib/designsettings.php:101 +msgid "Change background image" msgstr "" -#: actions/tagother.php:33 -msgid "Not logged in" +#: lib/designsettings.php:105 +msgid "Upload file" msgstr "" -#: actions/tagother.php:39 -msgid "No id argument." +#: lib/designsettings.php:109 +msgid "" +"You can upload your personal background image. The maximum file size is 2Mb." msgstr "" -#: actions/tagother.php:65 -#, php-format -msgid "Tag %s" +#: lib/designsettings.php:139 +msgid "On" msgstr "" -#: actions/tagother.php:141 -msgid "Tag user" +#: lib/designsettings.php:155 +msgid "Off" msgstr "" -#: actions/tagother.php:149 actions/tagother.php:151 -msgid "" -"Tags for this user (letters, numbers, -, ., and _), comma- or space- " -"separated" +#: lib/designsettings.php:156 +msgid "Turn background image on or off." msgstr "" -#: actions/tagother.php:164 -msgid "There was a problem with your session token." +#: lib/designsettings.php:161 +msgid "Tile background image" msgstr "" -#: actions/tagother.php:191 actions/tagother.php:193 -msgid "" -"You can only tag people you are subscribed to or who are subscribed to you." +#: lib/designsettings.php:170 +msgid "Change colours" msgstr "" -#: actions/tagother.php:198 actions/tagother.php:200 -msgid "Could not save tags." +#: lib/designsettings.php:178 +msgid "Background" msgstr "" -#: actions/tagother.php:233 actions/tagother.php:235 actions/tagother.php:236 -msgid "Use this form to add tags to your subscribers or subscriptions." +#: lib/designsettings.php:191 +msgid "Content" msgstr "" -#: actions/tagrss.php:35 -msgid "No such tag." +#: lib/designsettings.php:204 +msgid "Sidebar" msgstr "" -#: actions/tagrss.php:66 actions/tagrss.php:64 -#, php-format -msgid "Microblog tagged with %s" +#: lib/designsettings.php:217 +msgid "Text" msgstr "" -#: actions/twitapiblocks.php:47 actions/twitapiblocks.php:49 -#: actions/apiblockcreate.php:108 -msgid "Block user failed." +#: lib/designsettings.php:230 +msgid "Links" msgstr "" -#: actions/twitapiblocks.php:69 actions/twitapiblocks.php:71 -#: actions/apiblockdestroy.php:107 -msgid "Unblock user failed." +#: lib/designsettings.php:247 +msgid "Use defaults" msgstr "" -#: actions/twitapiusers.php:48 actions/twitapiusers.php:52 -#: actions/twitapiusers.php:50 actions/apiusershow.php:96 -msgid "Not found." +#: lib/designsettings.php:248 +msgid "Restore default designs" msgstr "" -#: actions/twittersettings.php:71 -msgid "Add your Twitter account to automatically send " +#: lib/designsettings.php:254 +msgid "Reset back to default" msgstr "" -#: actions/twittersettings.php:119 actions/twittersettings.php:122 -msgid "Twitter user name" +#: lib/designsettings.php:257 +msgid "Save design" msgstr "" -#: actions/twittersettings.php:126 actions/twittersettings.php:129 -msgid "Twitter password" +#: lib/designsettings.php:372 +msgid "Bad default color settings: " msgstr "" -#: actions/twittersettings.php:228 actions/twittersettings.php:232 -#: actions/twittersettings.php:248 -msgid "Twitter Friends" +#: lib/designsettings.php:468 +msgid "Design defaults restored." msgstr "" -#: actions/twittersettings.php:327 -msgid "Username must have only numbers, " +#: lib/disfavorform.php:114 lib/disfavorform.php:140 +msgid "Disfavor this notice" msgstr "" -#: actions/twittersettings.php:341 -#, php-format -msgid "Unable to retrieve account information " +#: lib/favorform.php:114 lib/favorform.php:140 +msgid "Favor this notice" msgstr "" -#: actions/unblock.php:108 actions/groupunblock.php:128 -msgid "Error removing the block." +#: lib/favorform.php:140 +msgid "Favor" msgstr "" -#: actions/unsubscribe.php:50 actions/unsubscribe.php:77 -msgid "No profile id in request." +#: lib/feedlist.php:64 +msgid "Export data" msgstr "" -#: actions/unsubscribe.php:57 actions/unsubscribe.php:84 -msgid "No profile with that id." +#: lib/feed.php:85 +msgid "RSS 1.0" msgstr "" -#: actions/unsubscribe.php:71 actions/unsubscribe.php:98 -msgid "Unsubscribed" -msgstr "" - -#: actions/usergroups.php:63 actions/usergroups.php:62 -#: actions/apigrouplistall.php:90 -#, php-format -msgid "%s groups" -msgstr "" - -#: actions/usergroups.php:65 actions/usergroups.php:64 -#, php-format -msgid "%s groups, page %d" -msgstr "" - -#: classes/Notice.php:104 classes/Notice.php:128 classes/Notice.php:144 -#: classes/Notice.php:183 -msgid "Problem saving notice. Unknown user." -msgstr "" - -#: classes/Notice.php:109 classes/Notice.php:133 classes/Notice.php:149 -#: classes/Notice.php:188 -msgid "" -"Too many notices too fast; take a breather and post again in a few minutes." -msgstr "" - -#: classes/Notice.php:116 classes/Notice.php:145 classes/Notice.php:161 -#: classes/Notice.php:202 -msgid "You are banned from posting notices on this site." -msgstr "" - -#: lib/accountsettingsaction.php:108 lib/accountsettingsaction.php:112 -msgid "Upload an avatar" +#: lib/feed.php:87 +msgid "RSS 2.0" msgstr "" -#: lib/accountsettingsaction.php:119 lib/accountsettingsaction.php:122 -#: lib/accountsettingsaction.php:123 -msgid "Other" +#: lib/feed.php:89 +msgid "Atom" msgstr "" -#: lib/accountsettingsaction.php:120 lib/accountsettingsaction.php:123 -#: lib/accountsettingsaction.php:124 -msgid "Other options" +#: lib/feed.php:91 +msgid "FOAF" msgstr "" -#: lib/action.php:130 lib/action.php:132 lib/action.php:142 lib/action.php:144 -#, php-format -msgid "%s - %s" +#: lib/galleryaction.php:121 +msgid "Filter tags" msgstr "" -#: lib/action.php:145 lib/action.php:147 lib/action.php:157 lib/action.php:159 -msgid "Untitled page" +#: lib/galleryaction.php:131 +msgid "All" msgstr "" -#: lib/action.php:316 lib/action.php:387 lib/action.php:411 lib/action.php:424 -msgid "Primary site navigation" +#: lib/galleryaction.php:139 +msgid "Select tag to filter" msgstr "" -#: lib/action.php:322 lib/action.php:393 lib/action.php:417 lib/action.php:430 -msgid "Personal profile and friends timeline" +#: lib/galleryaction.php:140 +msgid "Tag" msgstr "" -#: lib/action.php:325 lib/action.php:396 lib/action.php:448 lib/action.php:459 -msgid "Search for people or text" +#: lib/galleryaction.php:141 +msgid "Choose a tag to narrow list" msgstr "" -#: lib/action.php:328 lib/action.php:399 lib/action.php:419 lib/action.php:432 -msgid "Account" +#: lib/galleryaction.php:143 +msgid "Go" msgstr "" -#: lib/action.php:328 lib/action.php:399 lib/action.php:419 lib/action.php:432 -msgid "Change your email, avatar, password, profile" +#: lib/groupeditform.php:163 +msgid "URL of the homepage or blog of the group or topic" msgstr "" -#: lib/action.php:330 lib/action.php:403 lib/action.php:422 -msgid "Connect to IM, SMS, Twitter" +#: lib/groupeditform.php:168 +msgid "Describe the group or topic" msgstr "" -#: lib/action.php:332 lib/action.php:409 lib/action.php:435 lib/action.php:445 -msgid "Logout from the site" +#: lib/groupeditform.php:170 +#, php-format +msgid "Describe the group or topic in %d characters" msgstr "" -#: lib/action.php:335 lib/action.php:412 lib/action.php:443 lib/action.php:453 -msgid "Login to the site" +#: lib/groupeditform.php:172 +msgid "Description" msgstr "" -#: lib/action.php:338 lib/action.php:415 lib/action.php:440 lib/action.php:450 -msgid "Create an account" +#: lib/groupeditform.php:179 +msgid "" +"Location for the group, if any, like \"City, State (or Region), Country\"" msgstr "" -#: lib/action.php:341 lib/action.php:418 -msgid "Login with OpenID" +#: lib/groupeditform.php:187 +#, php-format +msgid "Extra nicknames for the group, comma- or space- separated, max %d" msgstr "" -#: lib/action.php:344 lib/action.php:421 lib/action.php:446 lib/action.php:456 -msgid "Help me!" +#: lib/groupnav.php:84 lib/searchgroupnav.php:84 +msgid "Group" msgstr "" -#: lib/action.php:362 lib/action.php:441 lib/action.php:468 lib/action.php:480 -msgid "Site notice" +#: lib/groupnav.php:100 +msgid "Blocked" msgstr "" -#: lib/action.php:417 lib/action.php:504 lib/action.php:531 lib/action.php:546 -msgid "Local views" +#: lib/groupnav.php:101 +#, php-format +msgid "%s blocked users" msgstr "" -#: lib/action.php:472 lib/action.php:559 lib/action.php:597 lib/action.php:612 -msgid "Page notice" +#: lib/groupnav.php:107 +#, php-format +msgid "Edit %s group properties" msgstr "" -#: lib/action.php:562 lib/action.php:654 lib/action.php:699 lib/action.php:714 -msgid "Secondary site navigation" +#: lib/groupnav.php:112 +msgid "Logo" msgstr "" -#: lib/action.php:602 lib/action.php:623 lib/action.php:699 lib/action.php:720 -#: lib/action.php:749 lib/action.php:770 lib/action.php:764 -msgid "StatusNet software license" +#: lib/groupnav.php:113 +#, php-format +msgid "Add or edit %s logo" msgstr "" -#: lib/action.php:630 lib/action.php:727 lib/action.php:779 lib/action.php:794 -msgid "All " +#: lib/groupnav.php:119 +#, php-format +msgid "Add or edit %s design" msgstr "" -#: lib/action.php:635 lib/action.php:732 lib/action.php:784 lib/action.php:799 -msgid "license." +#: lib/groupsbymemberssection.php:71 +msgid "Groups with most members" msgstr "" -#: lib/blockform.php:123 lib/blockform.php:153 actions/groupmembers.php:343 -#: actions/groupmembers.php:346 -msgid "Block this user" +#: lib/groupsbypostssection.php:71 +msgid "Groups with most posts" msgstr "" -#: lib/blockform.php:153 actions/groupmembers.php:343 -#: actions/groupmembers.php:346 -msgid "Block" +#: lib/grouptagcloudsection.php:56 +#, php-format +msgid "Tags in %s group's notices" msgstr "" -#: lib/disfavorform.php:114 lib/disfavorform.php:140 -msgid "Disfavor this notice" +#: lib/htmloutputter.php:104 +msgid "This page is not available in a media type you accept" msgstr "" -#: lib/facebookaction.php:268 +#: lib/imagefile.php:75 #, php-format -msgid "To use the %s Facebook Application you need to login " +msgid "That file is too big. The maximum file size is %s." msgstr "" -#: lib/facebookaction.php:271 lib/facebookaction.php:273 -#: lib/facebookaction.php:275 -msgid " a new account." +#: lib/imagefile.php:80 +msgid "Partial upload." msgstr "" -#: lib/facebookaction.php:557 lib/mailbox.php:214 lib/noticelist.php:354 -#: lib/facebookaction.php:675 lib/mailbox.php:216 lib/noticelist.php:357 -#: lib/mailbox.php:217 lib/noticelist.php:361 -msgid "Published" +#: lib/imagefile.php:88 lib/mediafile.php:170 +msgid "System error uploading file." msgstr "" -#: lib/favorform.php:114 lib/favorform.php:140 -msgid "Favor this notice" +#: lib/imagefile.php:96 +msgid "Not an image or corrupt file." msgstr "" -#: lib/feedlist.php:64 -msgid "Export data" +#: lib/imagefile.php:105 +msgid "Unsupported image file format." msgstr "" -#: lib/galleryaction.php:121 -msgid "Filter tags" +#: lib/imagefile.php:118 +msgid "Lost our file." msgstr "" -#: lib/galleryaction.php:131 -msgid "All" +#: lib/imagefile.php:150 lib/imagefile.php:197 +msgid "Unknown file type" msgstr "" -#: lib/galleryaction.php:137 lib/galleryaction.php:138 -#: lib/galleryaction.php:140 -msgid "Tag" +#: lib/jabber.php:192 +#, php-format +msgid "notice id: %s" msgstr "" -#: lib/galleryaction.php:138 lib/galleryaction.php:139 -#: lib/galleryaction.php:141 -msgid "Choose a tag to narrow list" +#: lib/joinform.php:114 +msgid "Join" msgstr "" -#: lib/galleryaction.php:139 lib/galleryaction.php:141 -#: lib/galleryaction.php:143 -msgid "Go" +#: lib/leaveform.php:114 +msgid "Leave" msgstr "" -#: lib/groupeditform.php:148 lib/groupeditform.php:163 -msgid "URL of the homepage or blog of the group or topic" +#: lib/logingroupnav.php:80 +msgid "Login with a username and password" msgstr "" -#: lib/groupeditform.php:151 lib/groupeditform.php:166 -#: lib/groupeditform.php:172 -msgid "Description" +#: lib/logingroupnav.php:86 +msgid "Sign up for a new account" msgstr "" -#: lib/groupeditform.php:153 lib/groupeditform.php:168 -msgid "Describe the group or topic in 140 chars" +#: lib/mailbox.php:89 +msgid "Only the user can read their own mailboxes." msgstr "" -#: lib/groupeditform.php:158 lib/groupeditform.php:173 -#: lib/groupeditform.php:179 +#: lib/mailbox.php:139 msgid "" -"Location for the group, if any, like \"City, State (or Region), Country\"" -msgstr "" - -#: lib/groupnav.php:84 lib/searchgroupnav.php:84 -msgid "Group" -msgstr "" - -#: lib/groupnav.php:100 actions/groupmembers.php:175 lib/groupnav.php:106 -msgid "Admin" +"You have no private messages. You can send private message to engage other " +"users in conversation. People can send you messages for your eyes only." msgstr "" -#: lib/groupnav.php:101 lib/groupnav.php:107 -#, php-format -msgid "Edit %s group properties" +#: lib/mailbox.php:227 lib/noticelist.php:424 +msgid "from" msgstr "" -#: lib/groupnav.php:106 lib/groupnav.php:112 -msgid "Logo" +#: lib/mail.php:172 +msgid "Email address confirmation" msgstr "" -#: lib/groupnav.php:107 lib/groupnav.php:113 +#: lib/mail.php:174 #, php-format -msgid "Add or edit %s logo" -msgstr "" - -#: lib/groupsbymemberssection.php:71 -msgid "Groups with most members" -msgstr "" - -#: lib/groupsbypostssection.php:71 -msgid "Groups with most posts" +msgid "" +"Hey, %s.\n" +"\n" +"Someone just entered this email address on %s.\n" +"\n" +"If it was you, and you want to confirm your entry, use the URL below:\n" +"\n" +"\t%s\n" +"\n" +"If not, just ignore this message.\n" +"\n" +"Thanks for your time, \n" +"%s\n" msgstr "" -#: lib/grouptagcloudsection.php:56 +#: lib/mail.php:235 #, php-format -msgid "Tags in %s group's notices" -msgstr "" - -#: lib/htmloutputter.php:104 -msgid "This page is not available in a " -msgstr "" - -#: lib/joinform.php:114 -msgid "Join" -msgstr "" - -#: lib/leaveform.php:114 -msgid "Leave" -msgstr "" - -#: lib/logingroupnav.php:76 lib/logingroupnav.php:80 -msgid "Login with a username and password" -msgstr "" - -#: lib/logingroupnav.php:79 lib/logingroupnav.php:86 -msgid "Sign up for a new account" -msgstr "" - -#: lib/logingroupnav.php:82 -msgid "Login or register with OpenID" +msgid "%1$s is now listening to your notices on %2$s." msgstr "" -#: lib/mail.php:175 +#: lib/mail.php:240 #, php-format msgid "" -"Hey, %s.\n" +"%1$s is now listening to your notices on %2$s.\n" "\n" +"\t%3$s\n" +"\n" +"%4$s%5$s%6$s\n" +"Faithfully yours,\n" +"%7$s.\n" +"\n" +"----\n" +"Change your email address or notification options at %8$s\n" msgstr "" -#: lib/mail.php:236 -#, php-format -msgid "%1$s is now listening to " -msgstr "" - -#: lib/mail.php:254 lib/mail.php:253 +#: lib/mail.php:253 #, php-format msgid "Location: %s\n" msgstr "" -#: lib/mail.php:256 lib/mail.php:255 +#: lib/mail.php:255 #, php-format msgid "Homepage: %s\n" msgstr "" -#: lib/mail.php:258 lib/mail.php:257 +#: lib/mail.php:257 #, php-format msgid "" "Bio: %s\n" "\n" msgstr "" -#: lib/mail.php:461 lib/mail.php:462 +#: lib/mail.php:285 #, php-format -msgid "You've been nudged by %s" +msgid "New email address for posting to %s" msgstr "" -#: lib/mail.php:465 +#: lib/mail.php:288 #, php-format -msgid "%1$s (%2$s) is wondering what you are up to " +msgid "" +"You have a new posting address on %1$s.\n" +"\n" +"Send email to %2$s to post new messages.\n" +"\n" +"More email instructions at %3$s.\n" +"\n" +"Faithfully yours,\n" +"%4$s" msgstr "" -#: lib/mail.php:555 +#: lib/mail.php:412 #, php-format -msgid "%1$s just added your notice from %2$s" +msgid "%s status" msgstr "" -#: lib/mailbox.php:229 lib/noticelist.php:380 lib/mailbox.php:231 -#: lib/noticelist.php:383 lib/mailbox.php:232 lib/noticelist.php:388 -msgid "From" +#: lib/mail.php:438 +msgid "SMS confirmation" msgstr "" -#: lib/messageform.php:110 lib/messageform.php:109 lib/messageform.php:120 -msgid "Send a direct notice" +#: lib/mail.php:462 +#, php-format +msgid "You've been nudged by %s" msgstr "" -#: lib/noticeform.php:125 lib/noticeform.php:128 lib/noticeform.php:145 -msgid "Send a notice" +#: lib/mail.php:466 +#, php-format +msgid "" +"%1$s (%2$s) is wondering what you are up to these days and is inviting you " +"to post some news.\n" +"\n" +"So let's hear from you :)\n" +"\n" +"%3$s\n" +"\n" +"Don't reply to this email; it won't get to them.\n" +"\n" +"With kind regards,\n" +"%4$s\n" msgstr "" -#: lib/noticeform.php:152 lib/noticeform.php:149 lib/messageform.php:162 -#: lib/noticeform.php:173 -msgid "Available characters" +#: lib/mail.php:509 +#, php-format +msgid "New private message from %s" msgstr "" -#: lib/noticelist.php:426 lib/noticelist.php:429 -msgid "in reply to" -msgstr "" - -#: lib/noticelist.php:447 lib/noticelist.php:450 lib/noticelist.php:451 -#: lib/noticelist.php:454 lib/noticelist.php:458 lib/noticelist.php:461 -#: lib/noticelist.php:498 -msgid "Reply to this notice" -msgstr "" - -#: lib/noticelist.php:451 lib/noticelist.php:455 lib/noticelist.php:462 -#: lib/noticelist.php:499 -msgid "Reply" -msgstr "" - -#: lib/noticelist.php:471 lib/noticelist.php:474 lib/noticelist.php:476 -#: lib/noticelist.php:479 actions/deletenotice.php:116 lib/noticelist.php:483 -#: lib/noticelist.php:486 actions/deletenotice.php:146 lib/noticelist.php:522 -msgid "Delete this notice" +#: lib/mail.php:513 +#, php-format +msgid "" +"%1$s (%2$s) sent you a private message:\n" +"\n" +"------------------------------------------------------\n" +"%3$s\n" +"------------------------------------------------------\n" +"\n" +"You can reply to their message here:\n" +"\n" +"%4$s\n" +"\n" +"Don't reply to this email; it won't get to them.\n" +"\n" +"With kind regards,\n" +"%5$s\n" msgstr "" -#: lib/noticelist.php:474 actions/avatarsettings.php:148 -#: lib/noticelist.php:479 lib/noticelist.php:486 lib/noticelist.php:522 -msgid "Delete" +#: lib/mail.php:554 +#, php-format +msgid "%s (@%s) added your notice as a favorite" msgstr "" -#: lib/nudgeform.php:116 -msgid "Nudge this user" +#: lib/mail.php:556 +#, php-format +msgid "" +"%1$s (@%7$s) just added your notice from %2$s as one of their favorites.\n" +"\n" +"The URL of your notice is:\n" +"\n" +"%3$s\n" +"\n" +"The text of your notice is:\n" +"\n" +"%4$s\n" +"\n" +"You can see the list of %1$s's favorites here:\n" +"\n" +"%5$s\n" +"\n" +"Faithfully yours,\n" +"%6$s\n" msgstr "" -#: lib/nudgeform.php:128 -msgid "Nudge" +#: lib/mail.php:611 +#, php-format +msgid "%s (@%s) sent a notice to your attention" msgstr "" -#: lib/nudgeform.php:128 -msgid "Send a nudge to this user" +#: lib/mail.php:613 +#, php-format +msgid "" +"%1$s (@%9$s) just sent a notice to your attention (an '@-reply') on %2$s.\n" +"\n" +"The notice is here:\n" +"\n" +"\t%3$s\n" +"\n" +"It reads:\n" +"\n" +"\t%4$s\n" +"\n" msgstr "" -#: lib/personaltagcloudsection.php:56 -#, php-format -msgid "Tags in %s's notices" +#: lib/mediafile.php:98 lib/mediafile.php:123 +msgid "There was a database error while saving your file. Please try again." msgstr "" -#: lib/profilelist.php:182 lib/profilelist.php:180 -#: lib/subscriptionlist.php:126 -msgid "(none)" +#: lib/mediafile.php:142 +msgid "The uploaded file exceeds the upload_max_filesize directive in php.ini." msgstr "" -#: lib/publicgroupnav.php:76 lib/publicgroupnav.php:78 -msgid "Public" +#: lib/mediafile.php:147 +msgid "" +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in " +"the HTML form." msgstr "" -#: lib/publicgroupnav.php:80 lib/publicgroupnav.php:82 -msgid "User groups" +#: lib/mediafile.php:152 +msgid "The uploaded file was only partially uploaded." msgstr "" -#: lib/publicgroupnav.php:82 lib/publicgroupnav.php:83 -#: lib/publicgroupnav.php:84 lib/publicgroupnav.php:85 -msgid "Recent tags" +#: lib/mediafile.php:159 +msgid "Missing a temporary folder." msgstr "" -#: lib/publicgroupnav.php:86 lib/publicgroupnav.php:88 -msgid "Featured" +#: lib/mediafile.php:162 +msgid "Failed to write file to disk." msgstr "" -#: lib/publicgroupnav.php:90 lib/publicgroupnav.php:92 -msgid "Popular" +#: lib/mediafile.php:165 +msgid "File upload stopped by extension." msgstr "" -#: lib/searchgroupnav.php:82 -msgid "Notice" +#: lib/mediafile.php:179 lib/mediafile.php:216 +msgid "File exceeds user's quota!" msgstr "" -#: lib/searchgroupnav.php:85 -msgid "Find groups on this site" +#: lib/mediafile.php:196 lib/mediafile.php:233 +msgid "File could not be moved to destination directory." msgstr "" -#: lib/section.php:89 -msgid "Untitled section" +#: lib/mediafile.php:201 lib/mediafile.php:237 +msgid "Could not determine file's mime-type!" msgstr "" -#: lib/subgroupnav.php:81 lib/subgroupnav.php:83 +#: lib/mediafile.php:270 #, php-format -msgid "People %s subscribes to" +msgid " Try using another %s format." msgstr "" -#: lib/subgroupnav.php:89 lib/subgroupnav.php:91 +#: lib/mediafile.php:275 #, php-format -msgid "People subscribed to %s" +msgid "%s is not a supported filetype on this server." msgstr "" -#: lib/subgroupnav.php:97 lib/subgroupnav.php:99 -#, php-format -msgid "Groups %s is a member of" +#: lib/messageform.php:120 +msgid "Send a direct notice" msgstr "" -#: lib/subgroupnav.php:104 lib/action.php:430 lib/subgroupnav.php:106 -#: lib/action.php:440 -#, php-format -msgid "Invite friends and colleagues to join you on %s" +#: lib/messageform.php:146 +msgid "To" msgstr "" -#: lib/subs.php:53 lib/subs.php:52 -msgid "User has blocked you." +#: lib/messageform.php:162 lib/noticeform.php:173 +msgid "Available characters" msgstr "" -#: lib/subscribeform.php:115 lib/subscribeform.php:139 -#: actions/userauthorization.php:178 actions/userauthorization.php:210 -msgid "Subscribe to this user" +#: lib/noticeform.php:145 +msgid "Send a notice" msgstr "" -#: lib/tagcloudsection.php:56 -msgid "None" +#: lib/noticeform.php:158 +#, php-format +msgid "What's up, %s?" msgstr "" -#: lib/topposterssection.php:74 -msgid "Top posters" +#: lib/noticeform.php:180 +msgid "Attach" msgstr "" -#: lib/unblockform.php:120 lib/unblockform.php:150 -#: actions/blockedfromgroup.php:313 -msgid "Unblock this user" +#: lib/noticeform.php:184 +msgid "Attach a file" msgstr "" -#: lib/unblockform.php:150 actions/blockedfromgroup.php:313 -msgid "Unblock" +#: lib/noticelist.php:478 +msgid "in context" msgstr "" -#: lib/unsubscribeform.php:113 lib/unsubscribeform.php:137 -msgid "Unsubscribe from this user" +#: lib/noticelist.php:498 +msgid "Reply to this notice" msgstr "" -#: actions/all.php:77 actions/all.php:59 actions/all.php:99 -#, php-format -msgid "Feed for friends of %s (RSS 1.0)" +#: lib/noticelist.php:499 +msgid "Reply" msgstr "" -#: actions/all.php:82 actions/all.php:64 actions/all.php:107 -#, php-format -msgid "Feed for friends of %s (RSS 2.0)" +#: lib/nudgeform.php:116 +msgid "Nudge this user" msgstr "" -#: actions/all.php:87 actions/all.php:69 actions/all.php:115 -#, php-format -msgid "Feed for friends of %s (Atom)" +#: lib/nudgeform.php:128 +msgid "Nudge" msgstr "" -#: actions/all.php:112 actions/all.php:125 actions/all.php:165 -msgid "You and friends" +#: lib/nudgeform.php:128 +msgid "Send a nudge to this user" msgstr "" -#: actions/avatarsettings.php:78 -#, php-format -msgid "You can upload your personal avatar. The maximum file size is %s." +#: lib/oauthstore.php:283 +msgid "Error inserting new profile" msgstr "" -#: actions/avatarsettings.php:373 actions/avatarsettings.php:387 -msgid "Avatar deleted." +#: lib/oauthstore.php:291 +msgid "Error inserting avatar" msgstr "" -#: actions/block.php:129 actions/block.php:136 -msgid "" -"Are you sure you want to block this user? Afterwards, they will be " -"unsubscribed from you, unable to subscribe to you in the future, and you " -"will not be notified of any @-replies from them." +#: lib/oauthstore.php:311 +msgid "Error inserting remote profile" msgstr "" -#: actions/deletenotice.php:73 actions/deletenotice.php:103 -msgid "" -"You are about to permanently delete a notice. Once this is done, it cannot " -"be undone." +#: lib/oauthstore.php:345 +msgid "Duplicate notice" msgstr "" -#: actions/deletenotice.php:127 actions/deletenotice.php:157 -msgid "There was a problem with your session token. Try again, please." +#: lib/oauthstore.php:487 +msgid "Couldn't insert new subscription." msgstr "" -#: actions/emailsettings.php:168 actions/emailsettings.php:174 -msgid "Send me email when someone sends me an \"@-reply\"." +#: lib/personalgroupnav.php:99 +msgid "Personal" msgstr "" -#: actions/facebookhome.php:193 actions/facebookhome.php:187 -#, php-format -msgid "" -"If you would like the %s app to automatically update your Facebook status " -"with your latest notice, you need to give it permission." +#: lib/personalgroupnav.php:104 +msgid "Replies" msgstr "" -#: actions/facebookhome.php:217 actions/facebookhome.php:211 -#, php-format -msgid "Okay, do it!" +#: lib/personalgroupnav.php:114 +msgid "Favorites" msgstr "" -#: actions/facebooksettings.php:124 -#, php-format -msgid "" -"If you would like %s to automatically update your Facebook status with your " -"latest notice, you need to give it permission." +#: lib/personalgroupnav.php:115 +msgid "User" msgstr "" -#: actions/grouplogo.php:155 actions/grouplogo.php:150 -#, php-format -msgid "" -"You can upload a logo image for your group. The maximum file size is %s." +#: lib/personalgroupnav.php:124 +msgid "Inbox" msgstr "" -#: actions/grouplogo.php:367 actions/grouplogo.php:362 -msgid "Pick a square area of the image to be the logo." +#: lib/personalgroupnav.php:125 +msgid "Your incoming messages" msgstr "" -#: actions/grouprss.php:136 actions/grouprss.php:137 -#, php-format -msgid "Microblog by %s group" +#: lib/personalgroupnav.php:129 +msgid "Outbox" msgstr "" -#: actions/groupsearch.php:57 actions/groupsearch.php:52 -#, php-format -msgid "" -"Search for groups on %%site.name%% by their name, location, or description. " -"Separate the terms by spaces; they must be 3 characters or more." +#: lib/personalgroupnav.php:130 +msgid "Your sent messages" msgstr "" -#: actions/groups.php:90 +#: lib/personaltagcloudsection.php:56 #, php-format -msgid "" -"%%%%site.name%%%% groups let you find and talk with people of similar " -"interests. After you join a group you can send messages to all other members " -"using the syntax \"!groupname\". Don't see a group you like? Try [searching " -"for one](%%%%action.groupsearch%%%%) or [start your own!](%%%%action.newgroup" -"%%%%)" +msgid "Tags in %s's notices" msgstr "" -#: actions/newmessage.php:102 -msgid "Only logged-in users can send direct messages." +#: lib/profileaction.php:109 lib/profileaction.php:191 lib/subgroupnav.php:82 +msgid "Subscriptions" msgstr "" -#: actions/noticesearch.php:91 -#, php-format -msgid "Search results for \"%s\" on %s" +#: lib/profileaction.php:126 +msgid "All subscriptions" msgstr "" -#: actions/openidlogin.php:66 -#, php-format -msgid "" -"For security reasons, please re-login with your [OpenID](%%doc.openid%%) " -"before changing your settings." +#: lib/profileaction.php:140 lib/profileaction.php:200 lib/subgroupnav.php:90 +msgid "Subscribers" msgstr "" -#: actions/public.php:125 actions/public.php:133 actions/public.php:151 -msgid "Public Stream Feed (RSS 1.0)" +#: lib/profileaction.php:157 +msgid "All subscribers" msgstr "" -#: actions/public.php:130 actions/public.php:138 actions/public.php:155 -msgid "Public Stream Feed (RSS 2.0)" +#: lib/profileaction.php:177 +msgid "User ID" msgstr "" -#: actions/public.php:135 actions/public.php:143 actions/public.php:159 -msgid "Public Stream Feed (Atom)" +#: lib/profileaction.php:182 +msgid "Member since" msgstr "" -#: actions/public.php:210 actions/public.php:241 actions/public.php:233 -#, php-format -msgid "" -"This is %%site.name%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-" -"blogging) service based on the Free Software [StatusNet](http://status.net/) " -"tool. [Join now](%%action.register%%) to share notices about yourself with " -"friends, family, and colleagues! ([Read more](%%doc.help%%))" +#: lib/profileaction.php:235 +msgid "All groups" msgstr "" -#: actions/register.php:286 actions/register.php:329 -#, php-format -msgid "" -"With this form you can create a new account. You can then post notices and " -"link up to friends and colleagues. (Have an [OpenID](http://openid.net/)? " -"Try our [OpenID registration](%%action.openidlogin%%)!)" +#: lib/publicgroupnav.php:78 +msgid "Public" msgstr "" -#: actions/register.php:432 actions/register.php:479 actions/register.php:489 -#: actions/register.php:495 -msgid "Creative Commons Attribution 3.0" +#: lib/publicgroupnav.php:82 +msgid "User groups" msgstr "" -#: actions/register.php:433 actions/register.php:480 actions/register.php:490 -#: actions/register.php:496 -msgid "" -" except this private data: password, email address, IM address, and phone " -"number." +#: lib/publicgroupnav.php:84 lib/publicgroupnav.php:85 +msgid "Recent tags" msgstr "" -#: actions/showgroup.php:378 actions/showgroup.php:424 -#: actions/showgroup.php:432 -msgid "Created" +#: lib/publicgroupnav.php:88 +msgid "Featured" msgstr "" -#: actions/showgroup.php:393 actions/showgroup.php:440 -#: actions/showgroup.php:448 -#, php-format -msgid "" -"**%s** is a user group on %%%%site.name%%%%, a [micro-blogging](http://en." -"wikipedia.org/wiki/Micro-blogging) service based on the Free Software " -"[StatusNet](http://status.net/) tool. Its members share short messages about " -"their life and interests. [Join now](%%%%action.register%%%%) to become part " -"of this group and many more! ([Read more](%%%%doc.help%%%%))" +#: lib/publicgroupnav.php:92 +msgid "Popular" msgstr "" -#: actions/showstream.php:147 -msgid "Your profile" +#: lib/searchaction.php:120 +msgid "Search site" msgstr "" -#: actions/showstream.php:149 -#, php-format -msgid "%s's profile" +#: lib/searchaction.php:162 +msgid "Search help" msgstr "" -#: actions/showstream.php:163 actions/showstream.php:128 -#: actions/showstream.php:129 -#, php-format -msgid "Notice feed for %s (RSS 1.0)" +#: lib/searchgroupnav.php:80 +msgid "People" msgstr "" -#: actions/showstream.php:170 actions/showstream.php:135 -#: actions/showstream.php:136 -#, php-format -msgid "Notice feed for %s (RSS 2.0)" +#: lib/searchgroupnav.php:81 +msgid "Find people on this site" msgstr "" -#: actions/showstream.php:177 actions/showstream.php:142 -#: actions/showstream.php:143 -#, php-format -msgid "Notice feed for %s (Atom)" +#: lib/searchgroupnav.php:82 +msgid "Notice" msgstr "" -#: actions/showstream.php:182 actions/showstream.php:147 -#: actions/showstream.php:148 -#, php-format -msgid "FOAF for %s" +#: lib/searchgroupnav.php:83 +msgid "Find content of notices" msgstr "" -#: actions/showstream.php:237 actions/showstream.php:202 -#: actions/showstream.php:234 lib/userprofile.php:116 -msgid "Edit Avatar" +#: lib/searchgroupnav.php:85 +msgid "Find groups on this site" msgstr "" -#: actions/showstream.php:316 actions/showstream.php:281 -#: actions/showstream.php:366 lib/userprofile.php:248 -msgid "Edit profile settings" +#: lib/section.php:89 +msgid "Untitled section" msgstr "" -#: actions/showstream.php:317 actions/showstream.php:282 -#: actions/showstream.php:367 lib/userprofile.php:249 -msgid "Edit" +#: lib/section.php:106 +msgid "More..." msgstr "" -#: actions/showstream.php:542 actions/showstream.php:388 -#: actions/showstream.php:487 actions/showstream.php:234 +#: lib/subgroupnav.php:83 #, php-format -msgid "" -"**%s** has an account on %%%%site.name%%%%, a [micro-blogging](http://en." -"wikipedia.org/wiki/Micro-blogging) service based on the Free Software " -"[StatusNet](http://status.net/) tool. [Join now](%%%%action.register%%%%) to " -"follow **%s**'s notices and many more! ([Read more](%%%%doc.help%%%%))" +msgid "People %s subscribes to" msgstr "" -#: actions/smssettings.php:335 actions/smssettings.php:347 -msgid "" -"A confirmation code was sent to the phone number you added. Check your phone " -"for the code and instructions on how to use it." +#: lib/subgroupnav.php:91 +#, php-format +msgid "People subscribed to %s" msgstr "" -#: actions/twitapifavorites.php:171 lib/mail.php:556 -#: actions/twitapifavorites.php:222 +#: lib/subgroupnav.php:99 #, php-format -msgid "" -"%1$s just added your notice from %2$s as one of their favorites.\n" -"\n" -"In case you forgot, you can see the text of your notice here:\n" -"\n" -"%3$s\n" -"\n" -"You can see the list of %1$s's favorites here:\n" -"\n" -"%4$s\n" -"\n" -"Faithfully yours,\n" -"%5$s\n" +msgid "Groups %s is a member of" msgstr "" -#: actions/twitapistatuses.php:124 actions/twitapistatuses.php:82 -#: actions/twitapistatuses.php:314 actions/apiblockcreate.php:97 -#: actions/apiblockdestroy.php:96 actions/apidirectmessage.php:77 -#: actions/apidirectmessagenew.php:75 actions/apigroupcreate.php:112 -#: actions/apigroupismember.php:90 actions/apigroupjoin.php:99 -#: actions/apigroupleave.php:99 actions/apigrouplist.php:90 -#: actions/apistatusesupdate.php:125 actions/apisubscriptions.php:87 -#: actions/apitimelinefavorites.php:70 actions/apitimelinefriends.php:79 -#: actions/apitimelinementions.php:79 actions/apitimelineuser.php:81 -#: actions/apiaccountupdateprofileimage.php:91 -#: actions/apiaccountupdateprofileimage.php:105 -#: actions/apistatusesupdate.php:139 -msgid "No such user!" +#: lib/subscriberspeopleselftagcloudsection.php:48 +#: lib/subscriptionspeopleselftagcloudsection.php:48 +msgid "People Tagcloud as self-tagged" msgstr "" -#: actions/twittersettings.php:72 -msgid "" -"Add your Twitter account to automatically send your notices to Twitter, and " -"subscribe to Twitter friends already here." +#: lib/subscriberspeopletagcloudsection.php:48 +#: lib/subscriptionspeopletagcloudsection.php:48 +msgid "People Tagcloud as tagged" msgstr "" -#: actions/twittersettings.php:345 actions/twittersettings.php:362 -#, php-format -msgid "Unable to retrieve account information For \"%s\" from Twitter." +#: lib/subscriptionlist.php:126 +msgid "(none)" msgstr "" -#: actions/userauthorization.php:86 actions/userauthorization.php:81 -msgid "" -"Please check these details to make sure that you want to subscribe to this " -"user's notices. If you didn't just ask to subscribe to someone's notices, " -"click \"Reject\"." +#: lib/subs.php:48 +msgid "Already subscribed!" msgstr "" -#: actions/usergroups.php:131 actions/usergroups.php:130 -msgid "Search for more groups" +#: lib/subs.php:52 +msgid "User has blocked you." msgstr "" -#: classes/Notice.php:138 classes/Notice.php:154 classes/Notice.php:194 -msgid "" -"Too many duplicate messages too quickly; take a breather and post again in a " -"few minutes." +#: lib/subs.php:56 +msgid "Could not subscribe." msgstr "" -#: lib/action.php:406 lib/action.php:425 -msgid "Connect to SMS, Twitter" +#: lib/subs.php:75 +msgid "Could not subscribe other to you." msgstr "" -#: lib/action.php:671 lib/action.php:721 lib/action.php:736 -msgid "Badge" +#: lib/subs.php:124 +msgid "Not subscribed!." msgstr "" -#: lib/command.php:113 lib/command.php:106 lib/command.php:126 -#, php-format -msgid "" -"Subscriptions: %1$s\n" -"Subscribers: %2$s\n" -"Notices: %3$s" +#: lib/subs.php:136 +msgid "Couldn't delete subscription." msgstr "" -#: lib/dberroraction.php:60 -msgid "Database error" +#: lib/tagcloudsection.php:56 +msgid "None" msgstr "" -#: lib/facebookaction.php:271 lib/facebookaction.php:273 -#, php-format -msgid "" -"To use the %s Facebook Application you need to login with your username and " -"password. Don't have a username yet? " +#: lib/topposterssection.php:74 +msgid "Top posters" msgstr "" -#: lib/feed.php:85 -msgid "RSS 1.0" +#: lib/unsubscribeform.php:113 lib/unsubscribeform.php:137 +msgid "Unsubscribe from this user" msgstr "" -#: lib/feed.php:87 -msgid "RSS 2.0" +#: lib/unsubscribeform.php:137 +msgid "Unsubscribe" msgstr "" -#: lib/feed.php:89 -msgid "Atom" +#: lib/userprofile.php:116 +msgid "Edit Avatar" msgstr "" -#: lib/feed.php:91 -msgid "FOAF" +#: lib/userprofile.php:236 +msgid "User actions" msgstr "" -#: lib/imagefile.php:75 -#, php-format -msgid "That file is too big. The maximum file size is %d." +#: lib/userprofile.php:248 +msgid "Edit profile settings" msgstr "" -#: lib/mail.php:175 lib/mail.php:174 -#, php-format -msgid "" -"Hey, %s.\n" -"\n" -"Someone just entered this email address on %s.\n" -"\n" -"If it was you, and you want to confirm your entry, use the URL below:\n" -"\n" -"\t%s\n" -"\n" -"If not, just ignore this message.\n" -"\n" -"Thanks for your time, \n" -"%s\n" +#: lib/userprofile.php:249 +msgid "Edit" msgstr "" -#: lib/mail.php:241 lib/mail.php:240 -#, php-format -msgid "" -"%1$s is now listening to your notices on %2$s.\n" -"\n" -"\t%3$s\n" -"\n" -"%4$s%5$s%6$s\n" -"Faithfully yours,\n" -"%7$s.\n" -"\n" -"----\n" -"Change your email address or notification options at %8$s\n" +#: lib/userprofile.php:272 +msgid "Send a direct message to this user" msgstr "" -#: lib/mail.php:466 -#, php-format -msgid "" -"%1$s (%2$s) is wondering what you are up to these days and is inviting you " -"to post some news.\n" -"\n" -"So let's hear from you :)\n" -"\n" -"%3$s\n" -"\n" -"Don't reply to this email; it won't get to them.\n" -"\n" -"With kind regards,\n" -"%4$s\n" +#: lib/userprofile.php:273 +msgid "Message" msgstr "" -#: lib/mail.php:513 -#, php-format -msgid "" -"%1$s (%2$s) sent you a private message:\n" -"\n" -"------------------------------------------------------\n" -"%3$s\n" -"------------------------------------------------------\n" -"\n" -"You can reply to their message here:\n" -"\n" -"%4$s\n" -"\n" -"Don't reply to this email; it won't get to them.\n" -"\n" -"With kind regards,\n" -"%5$s\n" +#: lib/util.php:844 +msgid "a few seconds ago" msgstr "" -#: lib/mail.php:598 lib/mail.php:600 -#, php-format -msgid "%s sent a notice to your attention" +#: lib/util.php:846 +msgid "about a minute ago" msgstr "" -#: lib/mail.php:600 lib/mail.php:602 +#: lib/util.php:848 #, php-format -msgid "" -"%1$s just sent a notice to your attention (an '@-reply') on %2$s.\n" -"\n" -"The notice is here:\n" -"\n" -"\t%3$s\n" -"\n" -"It reads:\n" -"\n" -"\t%4$s\n" -"\n" -"You can reply back here:\n" -"\n" -"\t%5$s\n" -"\n" -"The list of all @-replies for you here:\n" -"\n" -"%6$s\n" -"\n" -"Faithfully yours,\n" -"%2$s\n" -"\n" -"P.S. You can turn off these email notifications here: %7$s\n" -msgstr "" - -#: lib/searchaction.php:122 lib/searchaction.php:120 -msgid "Search site" -msgstr "" - -#: lib/section.php:106 -msgid "More..." +msgid "about %d minutes ago" msgstr "" -#: actions/all.php:80 actions/all.php:127 -#, php-format -msgid "" -"This is the timeline for %s and friends but no one has posted anything yet." +#: lib/util.php:850 +msgid "about an hour ago" msgstr "" -#: actions/all.php:85 actions/all.php:132 +#: lib/util.php:852 #, php-format -msgid "" -"Try subscribing to more people, [join a group](%%action.groups%%) or post " -"something yourself." +msgid "about %d hours ago" msgstr "" -#: actions/all.php:87 actions/all.php:134 -#, php-format -msgid "" -"You can try to [nudge %s](../%s) from his profile or [post something to his " -"or her attention](%%%%action.newnotice%%%%?status_textarea=%s)." +#: lib/util.php:854 +msgid "about a day ago" msgstr "" -#: actions/all.php:91 actions/replies.php:190 actions/showstream.php:361 -#: actions/all.php:137 actions/replies.php:209 actions/showstream.php:455 -#: actions/showstream.php:202 +#: lib/util.php:856 #, php-format -msgid "" -"Why not [register an account](%%%%action.register%%%%) and then nudge %s or " -"post a notice to his or her attention." +msgid "about %d days ago" msgstr "" -#: actions/attachment.php:73 -msgid "No such attachment." +#: lib/util.php:858 +msgid "about a month ago" msgstr "" -#: actions/block.php:149 -msgid "Do not block this user from this group" +#: lib/util.php:860 +#, php-format +msgid "about %d months ago" msgstr "" -#: actions/block.php:150 -msgid "Block this user from this group" +#: lib/util.php:862 +msgid "about a year ago" msgstr "" -#: actions/blockedfromgroup.php:90 +#: lib/webcolor.php:82 #, php-format -msgid "%s blocked profiles" +msgid "%s is not a valid color!" msgstr "" -#: actions/blockedfromgroup.php:93 +#: lib/webcolor.php:123 #, php-format -msgid "%s blocked profiles, page %d" -msgstr "" - -#: actions/blockedfromgroup.php:108 -msgid "A list of the users blocked from joining this group." -msgstr "" - -#: actions/blockedfromgroup.php:281 -msgid "Unblock user from group" -msgstr "" - -#: actions/conversation.php:99 -msgid "Conversation" +msgid "%s is not a valid color! Use 3 or 6 hex chars." msgstr "" -#: actions/deletenotice.php:115 actions/deletenotice.php:145 -msgid "Do not delete this notice" +#: scripts/maildaemon.php:48 +msgid "Could not parse message." msgstr "" -#: actions/editgroup.php:214 actions/newgroup.php:164 -#: actions/apigroupcreate.php:291 actions/editgroup.php:215 -#: actions/newgroup.php:159 -#, php-format -msgid "Too many aliases! Maximum %d." +#: scripts/maildaemon.php:53 +msgid "Not a registered user." msgstr "" -#: actions/editgroup.php:223 actions/newgroup.php:173 -#: actions/apigroupcreate.php:312 actions/editgroup.php:224 -#: actions/newgroup.php:168 -#, php-format -msgid "Invalid alias: \"%s\"" +#: scripts/maildaemon.php:57 +msgid "Sorry, that is not your incoming email address." msgstr "" -#: actions/editgroup.php:227 actions/newgroup.php:177 -#: actions/apigroupcreate.php:321 actions/editgroup.php:228 -#: actions/newgroup.php:172 -#, php-format -msgid "Alias \"%s\" already in use. Try another one." -msgstr "" - -#: actions/editgroup.php:233 actions/newgroup.php:183 -#: actions/apigroupcreate.php:334 actions/editgroup.php:234 -#: actions/newgroup.php:178 -msgid "Alias can't be the same as nickname." -msgstr "" - -#: actions/editgroup.php:259 actions/newgroup.php:215 -#: actions/apigroupcreate.php:147 actions/newgroup.php:210 -msgid "Could not create aliases." -msgstr "" - -#: actions/favorited.php:150 -msgid "Favorite notices appear on this page but no one has favorited one yet." -msgstr "" - -#: actions/favorited.php:153 -msgid "" -"Be the first to add a notice to your favorites by clicking the fave button " -"next to any notice you like." -msgstr "" - -#: actions/favorited.php:156 -#, php-format -msgid "" -"Why not [register an account](%%action.register%%) and be the first to add a " -"notice to your favorites!" -msgstr "" - -#: actions/file.php:34 -msgid "No notice id" -msgstr "" - -#: actions/file.php:38 -msgid "No notice" -msgstr "" - -#: actions/file.php:42 -msgid "No attachments" -msgstr "" - -#: actions/file.php:51 -msgid "No uploaded attachments" -msgstr "" - -#: actions/finishopenidlogin.php:211 -msgid "Not a valid invitation code." -msgstr "" - -#: actions/groupblock.php:81 actions/groupunblock.php:81 -#: actions/makeadmin.php:81 -msgid "No group specified." -msgstr "" - -#: actions/groupblock.php:91 -msgid "Only an admin can block group members." -msgstr "" - -#: actions/groupblock.php:95 -msgid "User is already blocked from group." -msgstr "" - -#: actions/groupblock.php:100 -msgid "User is not a member of group." -msgstr "" - -#: actions/groupblock.php:136 actions/groupmembers.php:311 -#: actions/groupmembers.php:314 -msgid "Block user from group" -msgstr "" - -#: actions/groupblock.php:155 -#, php-format -msgid "" -"Are you sure you want to block user \"%s\" from the group \"%s\"? They will " -"be removed from the group, unable to post, and unable to subscribe to the " -"group in the future." -msgstr "" - -#: actions/groupblock.php:193 -msgid "Database error blocking user from group." -msgstr "" - -#: actions/groupdesignsettings.php:73 actions/groupdesignsettings.php:68 -msgid "You must be logged in to edit a group." -msgstr "" - -#: actions/groupdesignsettings.php:146 actions/groupdesignsettings.php:141 -msgid "Group design" -msgstr "" - -#: actions/groupdesignsettings.php:157 actions/groupdesignsettings.php:152 -msgid "" -"Customize the way your group looks with a background image and a colour " -"palette of your choice." -msgstr "" - -#: actions/groupdesignsettings.php:267 actions/userdesignsettings.php:186 -#: lib/designsettings.php:440 lib/designsettings.php:470 -#: actions/groupdesignsettings.php:262 lib/designsettings.php:431 -#: lib/designsettings.php:461 lib/designsettings.php:434 -#: lib/designsettings.php:464 -msgid "Couldn't update your design." -msgstr "" - -#: actions/groupdesignsettings.php:291 actions/groupdesignsettings.php:301 -#: actions/userdesignsettings.php:210 actions/userdesignsettings.php:220 -#: actions/userdesignsettings.php:263 actions/userdesignsettings.php:273 -#: actions/groupdesignsettings.php:286 actions/groupdesignsettings.php:296 -msgid "Unable to save your design settings!" -msgstr "" - -#: actions/groupdesignsettings.php:312 actions/userdesignsettings.php:231 -#: actions/groupdesignsettings.php:307 -msgid "Design preferences saved." -msgstr "" - -#: actions/groupmembers.php:438 actions/groupmembers.php:441 -msgid "Make user an admin of the group" -msgstr "" - -#: actions/groupmembers.php:470 actions/groupmembers.php:473 -msgid "Make Admin" -msgstr "" - -#: actions/groupmembers.php:470 actions/groupmembers.php:473 -msgid "Make this user an admin" -msgstr "" - -#: actions/groupsearch.php:79 actions/noticesearch.php:117 -#: actions/peoplesearch.php:83 -msgid "No results." -msgstr "" - -#: actions/groupsearch.php:82 -#, php-format -msgid "" -"If you can't find the group you're looking for, you can [create it](%%action." -"newgroup%%) yourself." -msgstr "" - -#: actions/groupsearch.php:85 -#, php-format -msgid "" -"Why not [register an account](%%action.register%%) and [create the group](%%" -"action.newgroup%%) yourself!" -msgstr "" - -#: actions/groupunblock.php:91 -msgid "Only an admin can unblock group members." -msgstr "" - -#: actions/groupunblock.php:95 -msgid "User is not blocked from group." -msgstr "" - -#: actions/invite.php:39 -msgid "Invites have been disabled." -msgstr "" - -#: actions/joingroup.php:100 actions/apigroupjoin.php:119 -#: actions/joingroup.php:95 lib/command.php:221 -msgid "You have been blocked from that group by the admin." -msgstr "" - -#: actions/makeadmin.php:91 -msgid "Only an admin can make another user an admin." -msgstr "" - -#: actions/makeadmin.php:95 -#, php-format -msgid "%s is already an admin for group \"%s\"." -msgstr "" - -#: actions/makeadmin.php:132 -#, php-format -msgid "Can't get membership record for %s in group %s" -msgstr "" - -#: actions/makeadmin.php:145 -#, php-format -msgid "Can't make %s an admin for group %s" -msgstr "" - -#: actions/newmessage.php:178 actions/newmessage.php:181 -msgid "Message sent" -msgstr "" - -#: actions/newnotice.php:93 lib/designsettings.php:281 -#: actions/newnotice.php:94 actions/apiaccountupdateprofileimage.php:97 -#: actions/apistatusesupdate.php:122 actions/avatarsettings.php:254 -#: lib/designsettings.php:283 -#, php-format -msgid "" -"The server was unable to handle that much POST data (%s bytes) due to its " -"current configuration." -msgstr "" - -#: actions/newnotice.php:128 scripts/maildaemon.php:185 lib/mediafile.php:270 -#, php-format -msgid " Try using another %s format." -msgstr "" - -#: actions/newnotice.php:133 scripts/maildaemon.php:190 lib/mediafile.php:275 -#, php-format -msgid "%s is not a supported filetype on this server." -msgstr "" - -#: actions/newnotice.php:205 lib/mediafile.php:142 -msgid "The uploaded file exceeds the upload_max_filesize directive in php.ini." -msgstr "" - -#: actions/newnotice.php:208 lib/mediafile.php:147 -msgid "" -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in " -"the HTML form." -msgstr "" - -#: actions/newnotice.php:211 lib/mediafile.php:152 -msgid "The uploaded file was only partially uploaded." -msgstr "" - -#: actions/newnotice.php:214 lib/mediafile.php:159 -msgid "Missing a temporary folder." -msgstr "" - -#: actions/newnotice.php:217 lib/mediafile.php:162 -msgid "Failed to write file to disk." -msgstr "" - -#: actions/newnotice.php:220 lib/mediafile.php:165 -msgid "File upload stopped by extension." -msgstr "" - -#: actions/newnotice.php:230 scripts/maildaemon.php:85 -msgid "Couldn't save file." -msgstr "" - -#: actions/newnotice.php:246 scripts/maildaemon.php:101 -msgid "Max notice size is 140 chars, including attachment URL." -msgstr "" - -#: actions/newnotice.php:297 -msgid "Somehow lost the login in saveFile" -msgstr "" - -#: actions/newnotice.php:309 scripts/maildaemon.php:127 lib/mediafile.php:196 -#: lib/mediafile.php:233 -msgid "File could not be moved to destination directory." -msgstr "" - -#: actions/newnotice.php:336 actions/newnotice.php:360 -#: scripts/maildaemon.php:148 scripts/maildaemon.php:167 lib/mediafile.php:98 -#: lib/mediafile.php:123 -msgid "There was a database error while saving your file. Please try again." -msgstr "" - -#: actions/noticesearch.php:121 -#, php-format -msgid "" -"Be the first to [post on this topic](%%%%action.newnotice%%%%?" -"status_textarea=%s)!" -msgstr "" - -#: actions/noticesearch.php:124 -#, php-format -msgid "" -"Why not [register an account](%%%%action.register%%%%) and be the first to " -"[post on this topic](%%%%action.newnotice%%%%?status_textarea=%s)!" -msgstr "" - -#: actions/openidsettings.php:70 -#, php-format -msgid "" -"[OpenID](%%doc.openid%%) lets you log into many sites with the same user " -"account. Manage your associated OpenIDs from here." -msgstr "" - -#: actions/othersettings.php:110 actions/othersettings.php:117 -msgid "Shorten URLs with" -msgstr "" - -#: actions/othersettings.php:115 actions/othersettings.php:122 -msgid "View profile designs" -msgstr "" - -#: actions/othersettings.php:116 actions/othersettings.php:123 -msgid "Show or hide profile designs." -msgstr "" - -#: actions/public.php:82 actions/public.php:83 -#, php-format -msgid "Beyond the page limit (%s)" -msgstr "" - -#: actions/public.php:179 -#, php-format -msgid "" -"This is the public timeline for %%site.name%% but no one has posted anything " -"yet." -msgstr "" - -#: actions/public.php:182 -msgid "Be the first to post!" -msgstr "" - -#: actions/public.php:186 -#, php-format -msgid "" -"Why not [register an account](%%action.register%%) and be the first to post!" -msgstr "" - -#: actions/public.php:245 actions/public.php:238 -#, php-format -msgid "" -"This is %%site.name%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-" -"blogging) service based on the Free Software [StatusNet](http://status.net/) " -"tool." -msgstr "" - -#: actions/publictagcloud.php:69 -#, php-format -msgid "No one has posted a notice with a [hashtag](%%doc.tags%%) yet." -msgstr "" - -#: actions/publictagcloud.php:72 -msgid "Be the first to post one!" -msgstr "" - -#: actions/publictagcloud.php:75 -#, php-format -msgid "" -"Why not [register an account](%%action.register%%) and be the first to post " -"one!" -msgstr "" - -#: actions/recoverpassword.php:152 -msgid "" -"If you've forgotten or lost your password, you can get a new one sent to the " -"email address you have stored in your account." -msgstr "" - -#: actions/recoverpassword.php:158 -msgid "You've been identified. Enter a new password below. " -msgstr "" - -#: actions/recoverpassword.php:188 -msgid "Password recover" -msgstr "" - -#: actions/register.php:86 actions/register.php:92 -msgid "Sorry, invalid invitation code." -msgstr "" - -#: actions/remotesubscribe.php:100 actions/remotesubscribe.php:124 -msgid "Subscribe to a remote user" -msgstr "" - -#: actions/replies.php:179 actions/replies.php:198 -#, php-format -msgid "" -"This is the timeline showing replies to %s but %s hasn't received a notice " -"to his attention yet." -msgstr "" - -#: actions/replies.php:184 actions/replies.php:203 -#, php-format -msgid "" -"You can engage other users in a conversation, subscribe to more people or " -"[join groups](%%action.groups%%)." -msgstr "" - -#: actions/replies.php:186 actions/replies.php:205 -#, php-format -msgid "" -"You can try to [nudge %s](../%s) or [post something to his or her attention]" -"(%%%%action.newnotice%%%%?status_textarea=%s)." -msgstr "" - -#: actions/showfavorites.php:79 -#, php-format -msgid "%s's favorite notices, page %d" -msgstr "" - -#: actions/showfavorites.php:170 actions/showfavorites.php:205 -msgid "" -"You haven't chosen any favorite notices yet. Click the fave button on " -"notices you like to bookmark them for later or shed a spotlight on them." -msgstr "" - -#: actions/showfavorites.php:172 actions/showfavorites.php:207 -#, php-format -msgid "" -"%s hasn't added any notices to his favorites yet. Post something interesting " -"they would add to their favorites :)" -msgstr "" - -#: actions/showfavorites.php:176 -#, php-format -msgid "" -"%s hasn't added any notices to his favorites yet. Why not [register an " -"account](%%%%action.register%%%%) and then post something interesting they " -"would add to thier favorites :)" -msgstr "" - -#: actions/showfavorites.php:226 actions/showfavorites.php:242 -msgid "This is a way to share what you like." -msgstr "" - -#: actions/showgroup.php:279 lib/groupeditform.php:178 -#: actions/showgroup.php:284 lib/groupeditform.php:184 -msgid "Aliases" -msgstr "" - -#: actions/showgroup.php:323 actions/showgroup.php:328 -#, php-format -msgid "Notice feed for %s group (RSS 1.0)" -msgstr "" - -#: actions/showgroup.php:330 actions/tag.php:84 actions/showgroup.php:334 -#, php-format -msgid "Notice feed for %s group (RSS 2.0)" -msgstr "" - -#: actions/showgroup.php:337 actions/showgroup.php:340 -#, php-format -msgid "Notice feed for %s group (Atom)" -msgstr "" - -#: actions/showgroup.php:446 actions/showgroup.php:454 -#, php-format -msgid "" -"**%s** is a user group on %%%%site.name%%%%, a [micro-blogging](http://en." -"wikipedia.org/wiki/Micro-blogging) service based on the Free Software " -"[StatusNet](http://status.net/) tool. Its members share short messages about " -"their life and interests. " -msgstr "" - -#: actions/showgroup.php:474 actions/showgroup.php:482 -msgid "Admins" -msgstr "" - -#: actions/shownotice.php:101 -msgid "Not a local notice" -msgstr "" - -#: actions/showstream.php:72 actions/showstream.php:73 -#, php-format -msgid " tagged %s" -msgstr "" - -#: actions/showstream.php:121 actions/showstream.php:122 -#, php-format -msgid "Notice feed for %s tagged %s (RSS 1.0)" -msgstr "" - -#: actions/showstream.php:350 actions/showstream.php:444 -#: actions/showstream.php:191 -#, php-format -msgid "This is the timeline for %s but %s hasn't posted anything yet." -msgstr "" - -#: actions/showstream.php:355 actions/showstream.php:449 -#: actions/showstream.php:196 -msgid "" -"Seen anything interesting recently? You haven't posted any notices yet, now " -"would be a good time to start :)" -msgstr "" - -#: actions/showstream.php:357 actions/showstream.php:451 -#: actions/showstream.php:198 -#, php-format -msgid "" -"You can try to nudge %s or [post something to his or her attention](%%%%" -"action.newnotice%%%%?status_textarea=%s)." -msgstr "" - -#: actions/showstream.php:393 actions/showstream.php:492 -#: actions/showstream.php:239 -#, php-format -msgid "" -"**%s** has an account on %%%%site.name%%%%, a [micro-blogging](http://en." -"wikipedia.org/wiki/Micro-blogging) service based on the Free Software " -"[StatusNet](http://status.net/) tool. " -msgstr "" - -#: actions/subscribers.php:108 -msgid "" -"You have no subscribers. Try subscribing to people you know and they might " -"return the favor" -msgstr "" - -#: actions/subscribers.php:110 -#, php-format -msgid "%s has no subscribers. Want to be the first?" -msgstr "" - -#: actions/subscribers.php:114 -#, php-format -msgid "" -"%s has no subscribers. Why not [register an account](%%%%action.register%%%" -"%) and be the first?" -msgstr "" - -#: actions/subscriptions.php:115 actions/subscriptions.php:121 -#, php-format -msgid "" -"You're not listening to anyone's notices right now, try subscribing to " -"people you know. Try [people search](%%action.peoplesearch%%), look for " -"members in groups you're interested in and in our [featured users](%%action." -"featured%%). If you're a [Twitter user](%%action.twittersettings%%), you can " -"automatically subscribe to people you already follow there." -msgstr "" - -#: actions/subscriptions.php:117 actions/subscriptions.php:121 -#: actions/subscriptions.php:123 actions/subscriptions.php:127 -#, php-format -msgid "%s is not listening to anyone." -msgstr "" - -#: actions/tag.php:77 actions/tag.php:86 -#, php-format -msgid "Notice feed for tag %s (RSS 1.0)" -msgstr "" - -#: actions/tag.php:91 actions/tag.php:98 -#, php-format -msgid "Notice feed for tag %s (Atom)" -msgstr "" - -#: actions/twitapifavorites.php:125 actions/apifavoritecreate.php:119 -msgid "This status is already a favorite!" -msgstr "" - -#: actions/twitapifavorites.php:179 actions/apifavoritedestroy.php:122 -msgid "That status is not a favorite!" -msgstr "" - -#: actions/twitapifriendships.php:180 actions/twitapifriendships.php:200 -#: actions/apifriendshipsshow.php:135 -msgid "Could not determine source user." -msgstr "" - -#: actions/twitapifriendships.php:215 -msgid "Target user not specified." -msgstr "" - -#: actions/twitapifriendships.php:221 actions/apifriendshipsshow.php:143 -msgid "Could not find target user." -msgstr "" - -#: actions/twitapistatuses.php:322 actions/apitimelinementions.php:116 -#, php-format -msgid "%1$s / Updates mentioning %2$s" -msgstr "" - -#: actions/twitapitags.php:74 actions/apitimelinetag.php:107 -#: actions/tagrss.php:64 -#, php-format -msgid "Updates tagged with %1$s on %2$s!" -msgstr "" - -#: actions/twittersettings.php:165 -msgid "Import my Friends Timeline." -msgstr "" - -#: actions/userauthorization.php:158 actions/userauthorization.php:188 -msgid "License" -msgstr "" - -#: actions/userauthorization.php:179 actions/userauthorization.php:212 -msgid "Reject this subscription" -msgstr "" - -#: actions/userdesignsettings.php:76 lib/designsettings.php:65 -msgid "Profile design" -msgstr "" - -#: actions/userdesignsettings.php:87 lib/designsettings.php:76 -msgid "" -"Customize the way your profile looks with a background image and a colour " -"palette of your choice." -msgstr "" - -#: actions/userdesignsettings.php:282 -msgid "Enjoy your hotdog!" -msgstr "" - -#: actions/usergroups.php:153 -#, php-format -msgid "%s is not a member of any group." -msgstr "" - -#: actions/usergroups.php:158 -#, php-format -msgid "Try [searching for groups](%%action.groupsearch%%) and joining them." -msgstr "" - -#: classes/File.php:127 classes/File.php:137 -#, php-format -msgid "" -"No file may be larger than %d bytes and the file you sent was %d bytes. Try " -"to upload a smaller version." -msgstr "" - -#: classes/File.php:137 classes/File.php:147 -#, php-format -msgid "A file this large would exceed your user quota of %d bytes." -msgstr "" - -#: classes/File.php:145 classes/File.php:154 -#, php-format -msgid "A file this large would exceed your monthly quota of %d bytes." -msgstr "" - -#: classes/Notice.php:139 classes/Notice.php:179 -msgid "Problem saving notice. Too long." -msgstr "" - -#: classes/User.php:319 classes/User.php:327 classes/User.php:334 -#: classes/User.php:333 -#, php-format -msgid "Welcome to %1$s, @%2$s!" -msgstr "" - -#: lib/accountsettingsaction.php:119 lib/groupnav.php:118 -#: lib/accountsettingsaction.php:120 -msgid "Design" -msgstr "" - -#: lib/accountsettingsaction.php:120 lib/accountsettingsaction.php:121 -msgid "Design your profile" -msgstr "" - -#: lib/action.php:712 lib/action.php:727 -msgid "TOS" -msgstr "" - -#: lib/attachmentlist.php:87 -msgid "Attachments" -msgstr "" - -#: lib/attachmentlist.php:265 -msgid "Author" -msgstr "" - -#: lib/attachmentlist.php:278 -msgid "Provider" -msgstr "" - -#: lib/attachmentnoticesection.php:67 -msgid "Notices where this attachment appears" -msgstr "" - -#: lib/attachmenttagcloudsection.php:48 -msgid "Tags for this attachment" -msgstr "" - -#: lib/designsettings.php:101 -msgid "Change background image" -msgstr "" - -#: lib/designsettings.php:105 -msgid "Upload file" -msgstr "" - -#: lib/designsettings.php:109 -msgid "" -"You can upload your personal background image. The maximum file size is 2Mb." -msgstr "" - -#: lib/designsettings.php:139 -msgid "On" -msgstr "" - -#: lib/designsettings.php:155 -msgid "Off" -msgstr "" - -#: lib/designsettings.php:156 -msgid "Turn background image on or off." -msgstr "" - -#: lib/designsettings.php:161 -msgid "Tile background image" -msgstr "" - -#: lib/designsettings.php:170 -msgid "Change colours" -msgstr "" - -#: lib/designsettings.php:178 -msgid "Background" -msgstr "" - -#: lib/designsettings.php:191 -msgid "Content" -msgstr "" - -#: lib/designsettings.php:204 -msgid "Sidebar" -msgstr "" - -#: lib/designsettings.php:230 -msgid "Links" -msgstr "" - -#: lib/designsettings.php:247 -msgid "Use defaults" -msgstr "" - -#: lib/designsettings.php:248 -msgid "Restore default designs" -msgstr "" - -#: lib/designsettings.php:254 -msgid "Reset back to default" -msgstr "" - -#: lib/designsettings.php:257 -msgid "Save design" -msgstr "" - -#: lib/designsettings.php:378 lib/designsettings.php:369 -#: lib/designsettings.php:372 -msgid "Bad default color settings: " -msgstr "" - -#: lib/designsettings.php:474 lib/designsettings.php:465 -#: lib/designsettings.php:468 -msgid "Design defaults restored." -msgstr "" - -#: lib/groupeditform.php:181 lib/groupeditform.php:187 -#, php-format -msgid "Extra nicknames for the group, comma- or space- separated, max %d" -msgstr "" - -#: lib/groupnav.php:100 -msgid "Blocked" -msgstr "" - -#: lib/groupnav.php:101 -#, php-format -msgid "%s blocked users" -msgstr "" - -#: lib/groupnav.php:119 -#, php-format -msgid "Add or edit %s design" -msgstr "" - -#: lib/mail.php:556 -#, php-format -msgid "" -"%1$s just added your notice from %2$s as one of their favorites.\n" -"\n" -"The URL of your notice is:\n" -"\n" -"%3$s\n" -"\n" -"The text of your notice is:\n" -"\n" -"%4$s\n" -"\n" -"You can see the list of %1$s's favorites here:\n" -"\n" -"%5$s\n" -"\n" -"Faithfully yours,\n" -"%6$s\n" -msgstr "" - -#: lib/mail.php:646 -#, php-format -msgid "Your Twitter bridge has been disabled." -msgstr "" - -#: lib/mail.php:648 -#, php-format -msgid "" -"Hi, %1$s. We're sorry to inform you that your link to Twitter has been " -"disabled. Your Twitter credentials have either changed (did you recently " -"change your Twitter password?) or you have otherwise revoked our access to " -"your Twitter account.\n" -"\n" -"You can re-enable your Twitter bridge by visiting your Twitter settings " -"page:\n" -"\n" -"\t%2$s\n" -"\n" -"Regards,\n" -"%3$s\n" -msgstr "" - -#: lib/mail.php:682 -#, php-format -msgid "Your %s Facebook application access has been disabled." -msgstr "" - -#: lib/mail.php:685 -#, php-format -msgid "" -"Hi, %1$s. We're sorry to inform you that we are unable to update your " -"Facebook status from %s, and have disabled the Facebook application for your " -"account. This may be because you have removed the Facebook application's " -"authorization, or have deleted your Facebook account. You can re-enable the " -"Facebook application and automatic status updating by re-installing the %1$s " -"Facebook application.\n" -"\n" -"Regards,\n" -"\n" -"%1$s" -msgstr "" - -#: lib/mailbox.php:139 -msgid "" -"You have no private messages. You can send private message to engage other " -"users in conversation. People can send you messages for your eyes only." -msgstr "" - -#: lib/noticeform.php:154 lib/noticeform.php:180 -msgid "Attach" -msgstr "" - -#: lib/noticeform.php:158 lib/noticeform.php:184 -msgid "Attach a file" -msgstr "" - -#: lib/noticelist.php:436 lib/noticelist.php:478 -msgid "in context" -msgstr "" - -#: lib/profileaction.php:177 -msgid "User ID" -msgstr "" - -#: lib/searchaction.php:156 lib/searchaction.php:162 -msgid "Search help" -msgstr "" - -#: lib/subscriberspeopleselftagcloudsection.php:48 -#: lib/subscriptionspeopleselftagcloudsection.php:48 -msgid "People Tagcloud as self-tagged" -msgstr "" - -#: lib/subscriberspeopletagcloudsection.php:48 -#: lib/subscriptionspeopletagcloudsection.php:48 -msgid "People Tagcloud as tagged" -msgstr "" - -#: lib/webcolor.php:82 -#, php-format -msgid "%s is not a valid color!" -msgstr "" - -#: lib/webcolor.php:123 -#, php-format -msgid "%s is not a valid color! Use 3 or 6 hex chars." -msgstr "" - -#: actions/all.php:63 actions/public.php:97 actions/replies.php:92 -#: actions/showfavorites.php:137 actions/tag.php:51 -msgid "No such page" -msgstr "" - -#: actions/apidirectmessage.php:89 -#, php-format -msgid "Direct messages from %s" -msgstr "" - -#: actions/apidirectmessagenew.php:135 actions/newmessage.php:150 -#, php-format -msgid "That's too long. Max message size is %d chars." -msgstr "" - -#: actions/apifriendshipsdestroy.php:109 -msgid "Could not unfollow user: User not found." -msgstr "" - -#: actions/apifriendshipsdestroy.php:120 -msgid "You cannot unfollow yourself!" -msgstr "" - -#: actions/apigroupcreate.php:261 -#, php-format -msgid "Description is too long (max %d chars)." -msgstr "" - -#: actions/apigroupjoin.php:110 -msgid "You are already a member of that group." -msgstr "" - -#: actions/apigroupjoin.php:138 -#, php-format -msgid "Could not join user %s to group %s." -msgstr "" - -#: actions/apigroupleave.php:114 -msgid "You are not a member of this group." -msgstr "" - -#: actions/apigroupleave.php:124 -#, php-format -msgid "Could not remove user %s to group %s." -msgstr "" - -#: actions/apigrouplist.php:95 -#, php-format -msgid "%s's groups" -msgstr "" - -#: actions/apigrouplist.php:103 -#, php-format -msgid "Groups %s is a member of on %s." -msgstr "" - -#: actions/apigrouplistall.php:94 -#, php-format -msgid "groups on %s" -msgstr "" - -#: actions/apistatusesshow.php:138 -msgid "Status deleted." -msgstr "" - -#: actions/apistatusesupdate.php:132 -#: actions/apiaccountupdateprofileimage.php:99 -msgid "Unable to handle that much POST data!" -msgstr "" - -#: actions/apistatusesupdate.php:145 actions/newnotice.php:155 -#: scripts/maildaemon.php:71 actions/apistatusesupdate.php:152 -#, php-format -msgid "That's too long. Max notice size is %d chars." -msgstr "" - -#: actions/apistatusesupdate.php:209 actions/newnotice.php:178 -#: actions/apistatusesupdate.php:216 -#, php-format -msgid "Max notice size is %d chars, including attachment URL." -msgstr "" - -#: actions/apisubscriptions.php:231 actions/apisubscriptions.php:261 -msgid "Unsupported format." -msgstr "" - -#: actions/bookmarklet.php:50 -msgid "Post to " -msgstr "" - -#: actions/editgroup.php:201 actions/newgroup.php:145 -#, php-format -msgid "description is too long (max %d chars)." -msgstr "" - -#: actions/favoritesrss.php:115 -#, php-format -msgid "Updates favored by %1$s on %2$s!" -msgstr "" - -#: actions/finishremotesubscribe.php:80 -msgid "User being listened to does not exist." -msgstr "" - -#: actions/finishremotesubscribe.php:106 -msgid "You are not authorized." -msgstr "" - -#: actions/finishremotesubscribe.php:109 -msgid "Could not convert request token to access token." -msgstr "" - -#: actions/finishremotesubscribe.php:114 -msgid "Remote service uses unknown version of OMB protocol." -msgstr "" - -#: actions/getfile.php:75 -msgid "No such file." -msgstr "" - -#: actions/getfile.php:79 -msgid "Cannot read file." -msgstr "" - -#: actions/grouprss.php:133 -#, php-format -msgid "Updates from members of %1$s on %2$s!" -msgstr "" - -#: actions/imsettings.php:89 -msgid "IM is not available." -msgstr "" - -#: actions/login.php:259 actions/login.php:286 -#, php-format -msgid "" -"Login with your username and password. Don't have a username yet? [Register]" -"(%%action.register%%) a new account." -msgstr "" - -#: actions/noticesearchrss.php:89 -#, php-format -msgid "Updates with \"%s\"" -msgstr "" - -#: actions/noticesearchrss.php:91 -#, php-format -msgid "Updates matching search term \"%1$s\" on %2$s!" -msgstr "" - -#: actions/oembed.php:157 -msgid "content type " -msgstr "" - -#: actions/oembed.php:160 -msgid "Only " -msgstr "" - -#: actions/postnotice.php:90 -#, php-format -msgid "Notice license ‘%s’ is not compatible with site license ‘%s’." -msgstr "" - -#: actions/profilesettings.php:122 actions/register.php:454 -#: actions/register.php:460 -#, php-format -msgid "Describe yourself and your interests in %d chars" -msgstr "" - -#: actions/profilesettings.php:125 actions/register.php:457 -#: actions/register.php:463 -msgid "Describe yourself and your interests" -msgstr "" - -#: actions/profilesettings.php:221 actions/register.php:217 -#: actions/register.php:223 -#, php-format -msgid "Bio is too long (max %d chars)." -msgstr "" - -#: actions/register.php:336 actions/register.php:342 -msgid "" -"With this form you can create a new account. You can then post notices and " -"link up to friends and colleagues. " -msgstr "" - -#: actions/remotesubscribe.php:168 -msgid "" -"Not a valid profile URL (no YADIS document or no or invalid XRDS defined)." -msgstr "" - -#: actions/remotesubscribe.php:176 -msgid "That’s a local profile! Login to subscribe." -msgstr "" - -#: actions/remotesubscribe.php:183 -msgid "Couldn’t get a request token." -msgstr "" - -#: actions/replies.php:144 -#, php-format -msgid "Replies feed for %s (RSS 1.0)" -msgstr "" - -#: actions/replies.php:151 -#, php-format -msgid "Replies feed for %s (RSS 2.0)" -msgstr "" - -#: actions/replies.php:158 -#, php-format -msgid "Replies feed for %s (Atom)" -msgstr "" - -#: actions/repliesrss.php:72 -#, php-format -msgid "Replies to %1$s on %2$s!" -msgstr "" - -#: actions/showfavorites.php:170 -#, php-format -msgid "Feed for favorites of %s (RSS 1.0)" -msgstr "" - -#: actions/showfavorites.php:177 -#, php-format -msgid "Feed for favorites of %s (RSS 2.0)" -msgstr "" - -#: actions/showfavorites.php:184 -#, php-format -msgid "Feed for favorites of %s (Atom)" -msgstr "" - -#: actions/showfavorites.php:211 -#, php-format -msgid "" -"%s hasn't added any notices to his favorites yet. Why not [register an " -"account](%%%%action.register%%%%) and then post something interesting they " -"would add to their favorites :)" -msgstr "" - -#: actions/showgroup.php:345 -#, php-format -msgid "FOAF for %s group" -msgstr "" - -#: actions/shownotice.php:90 -msgid "Notice deleted." -msgstr "" - -#: actions/smssettings.php:91 -msgid "SMS is not available." -msgstr "" - -#: actions/tag.php:92 -#, php-format -msgid "Notice feed for tag %s (RSS 2.0)" -msgstr "" - -#: actions/updateprofile.php:62 actions/userauthorization.php:330 -#, php-format -msgid "Listenee stream license ‘%s’ is not compatible with site license ‘%s’." -msgstr "" - -#: actions/userauthorization.php:110 -msgid "" -"Please check these details to make sure that you want to subscribe to this " -"user’s notices. If you didn’t just ask to subscribe to someone’s notices, " -"click “Reject”." -msgstr "" - -#: actions/userauthorization.php:249 -msgid "" -"The subscription has been authorized, but no callback URL was passed. Check " -"with the site’s instructions for details on how to authorize the " -"subscription. Your subscription token is:" -msgstr "" - -#: actions/userauthorization.php:261 -msgid "" -"The subscription has been rejected, but no callback URL was passed. Check " -"with the site’s instructions for details on how to fully reject the " -"subscription." -msgstr "" - -#: actions/userauthorization.php:296 -#, php-format -msgid "Listener URI ‘%s’ not found here" -msgstr "" - -#: actions/userauthorization.php:301 -#, php-format -msgid "Listenee URI ‘%s’ is too long." -msgstr "" - -#: actions/userauthorization.php:307 -#, php-format -msgid "Listenee URI ‘%s’ is a local user." -msgstr "" - -#: actions/userauthorization.php:322 -#, php-format -msgid "Profile URL ‘%s’ is for a local user." -msgstr "" - -#: actions/userauthorization.php:338 -#, php-format -msgid "Avatar URL ‘%s’ is not valid." -msgstr "" - -#: actions/userauthorization.php:343 -#, php-format -msgid "Can’t read avatar URL ‘%s’." -msgstr "" - -#: actions/userauthorization.php:348 -#, php-format -msgid "Wrong image type for avatar URL ‘%s’." -msgstr "" - -#: lib/action.php:435 -msgid "Connect to services" -msgstr "" - -#: lib/action.php:785 -msgid "Site content license" -msgstr "" - -#: lib/command.php:88 -#, php-format -msgid "Could not find a user with nickname %s" -msgstr "" - -#: lib/command.php:92 -msgid "It does not make a lot of sense to nudge yourself!" -msgstr "" - -#: lib/command.php:99 -#, php-format -msgid "Nudge sent to %s" -msgstr "" - -#: lib/command.php:152 lib/command.php:400 -msgid "Notice with that id does not exist" -msgstr "" - -#: lib/command.php:358 scripts/xmppdaemon.php:321 -#, php-format -msgid "Message too long - maximum is %d characters, you sent %d" -msgstr "" - -#: lib/command.php:431 -#, php-format -msgid "Notice too long - maximum is %d characters, you sent %d" -msgstr "" - -#: lib/command.php:439 -#, php-format -msgid "Reply to %s sent" -msgstr "" - -#: lib/command.php:441 -msgid "Error saving notice." -msgstr "" - -#: lib/common.php:191 -msgid "No configuration file found. " -msgstr "" - -#: lib/common.php:192 -msgid "I looked for configuration files in the following places: " -msgstr "" - -#: lib/common.php:193 -msgid "You may wish to run the installer to fix this." -msgstr "" - -#: lib/common.php:194 -msgid "Go to the installer." -msgstr "" - -#: lib/galleryaction.php:139 -msgid "Select tag to filter" -msgstr "" - -#: lib/groupeditform.php:168 -msgid "Describe the group or topic" -msgstr "" - -#: lib/groupeditform.php:170 -#, php-format -msgid "Describe the group or topic in %d characters" -msgstr "" - -#: lib/jabber.php:192 -#, php-format -msgid "notice id: %s" -msgstr "" - -#: lib/mail.php:554 -#, php-format -msgid "%s (@%s) added your notice as a favorite" -msgstr "" - -#: lib/mail.php:556 -#, php-format -msgid "" -"%1$s (@%7$s) just added your notice from %2$s as one of their favorites.\n" -"\n" -"The URL of your notice is:\n" -"\n" -"%3$s\n" -"\n" -"The text of your notice is:\n" -"\n" -"%4$s\n" -"\n" -"You can see the list of %1$s's favorites here:\n" -"\n" -"%5$s\n" -"\n" -"Faithfully yours,\n" -"%6$s\n" -msgstr "" - -#: lib/mail.php:611 -#, php-format -msgid "%s (@%s) sent a notice to your attention" -msgstr "" - -#: lib/mail.php:613 -#, php-format -msgid "" -"%1$s (@%9$s) just sent a notice to your attention (an '@-reply') on %2$s.\n" -"\n" -"The notice is here:\n" -"\n" -"\t%3$s\n" -"\n" -"It reads:\n" -"\n" -"\t%4$s\n" -"\n" -msgstr "" - -#: lib/mailbox.php:227 lib/noticelist.php:424 -msgid "from" -msgstr "" - -#: lib/mediafile.php:179 lib/mediafile.php:216 -msgid "File exceeds user's quota!" -msgstr "" - -#: lib/mediafile.php:201 lib/mediafile.php:237 -msgid "Could not determine file's mime-type!" -msgstr "" - -#: lib/oauthstore.php:345 -msgid "Duplicate notice" -msgstr "" - -#: actions/login.php:110 actions/login.php:120 -msgid "Invalid or expired token." -msgstr "" - -#: lib/command.php:597 -#, php-format -msgid "Could not create login token for %s" -msgstr "" - -#: lib/command.php:602 -#, php-format -msgid "This link is useable only once, and is good for only 2 minutes: %s" -msgstr "" - -#: lib/imagefile.php:75 -#, php-format -msgid "That file is too big. The maximum file size is %s." -msgstr "" - -#: lib/command.php:613 -msgid "" -"Commands:\n" -"on - turn on notifications\n" -"off - turn off notifications\n" -"help - show this help\n" -"follow - subscribe to user\n" -"leave - unsubscribe from user\n" -"d - direct message to user\n" -"get - get last notice from user\n" -"whois - get profile info on user\n" -"fav - add user's last notice as a 'fave'\n" -"fav # - add notice with the given id as a 'fave'\n" -"reply # - reply to notice with a given id\n" -"reply - reply to the last notice from user\n" -"join - join group\n" -"login - Get a link to login to the web interface\n" -"drop - leave group\n" -"stats - get your stats\n" -"stop - same as 'off'\n" -"quit - same as 'off'\n" -"sub - same as 'follow'\n" -"unsub - same as 'leave'\n" -"last - same as 'get'\n" -"on - not yet implemented.\n" -"off - not yet implemented.\n" -"nudge - remind a user to update.\n" -"invite - not yet implemented.\n" -"track - not yet implemented.\n" -"untrack - not yet implemented.\n" -"track off - not yet implemented.\n" -"untrack all - not yet implemented.\n" -"tracks - not yet implemented.\n" -"tracking - not yet implemented.\n" +#: scripts/maildaemon.php:61 +msgid "Sorry, no incoming email allowed." msgstr "" diff --git a/plugins/Facebook/facebook/facebookapi_php5_restlib.php b/plugins/Facebook/facebook/facebookapi_php5_restlib.php index 55cb7fb86..e2a6fe88b 100755 --- a/plugins/Facebook/facebook/facebookapi_php5_restlib.php +++ b/plugins/Facebook/facebook/facebookapi_php5_restlib.php @@ -2951,7 +2951,7 @@ function toggleDisplay(id, type) { /** - * Bans a list of users from the app. Banned users can't + * Bans a list of users from the app. Banned users cannot * access the app's canvas page and forums. * * @param array $uids an array of user ids diff --git a/plugins/Facebook/facebook/jsonwrapper/JSON/JSON.php b/plugins/Facebook/facebook/jsonwrapper/JSON/JSON.php index 0cddbddb4..92542b47d 100644 --- a/plugins/Facebook/facebook/jsonwrapper/JSON/JSON.php +++ b/plugins/Facebook/facebook/jsonwrapper/JSON/JSON.php @@ -124,7 +124,7 @@ class Services_JSON * "{...}" syntax creates associative arrays * instead of objects in decode(). * - SERVICES_JSON_SUPPRESS_ERRORS: error suppression. - * Values which can't be encoded (e.g. resources) + * Values which cannot be encoded (e.g. resources) * appear as NULL instead of throwing errors. * By default, a deeply-nested resource will * bubble up with an error, so all return values diff --git a/plugins/Facebook/facebookaction.php b/plugins/Facebook/facebookaction.php index a10fdf90d..1d8b5217b 100644 --- a/plugins/Facebook/facebookaction.php +++ b/plugins/Facebook/facebookaction.php @@ -513,7 +513,7 @@ class FacebookNoticeList extends NoticeList /** * show the list of notices * - * "Uses up" the stream by looping through it. So, probably can't + * "Uses up" the stream by looping through it. So, probably cannot * be called twice on the same list. * * @return int count of notices listed. diff --git a/plugins/Facebook/facebookhome.php b/plugins/Facebook/facebookhome.php index 91c0cc6b8..ee6e6620b 100644 --- a/plugins/Facebook/facebookhome.php +++ b/plugins/Facebook/facebookhome.php @@ -108,7 +108,7 @@ class FacebookhomeAction extends FacebookAction $user = User::staticGet('nickname', $nickname); if (!$user) { - $this->showLoginForm(_("Server error - couldn't get user!")); + $this->showLoginForm(_("Server error. Could not get user.")); } $flink = DB_DataObject::factory('foreign_link'); diff --git a/plugins/LinkbackPlugin.php b/plugins/LinkbackPlugin.php index 915d15c07..bc433b896 100644 --- a/plugins/LinkbackPlugin.php +++ b/plugins/LinkbackPlugin.php @@ -125,7 +125,7 @@ class LinkbackPlugin extends Plugin if (!extension_loaded('xmlrpc')) { if (!dl('xmlrpc.so')) { - common_log(LOG_ERR, "Can't pingback; xmlrpc extension not available."); + common_log(LOG_ERR, "Cannot pingback; xmlrpc extension not available."); } } diff --git a/plugins/Meteor/MeteorPlugin.php b/plugins/Meteor/MeteorPlugin.php index 5b345d7c2..f3cbc3eea 100644 --- a/plugins/Meteor/MeteorPlugin.php +++ b/plugins/Meteor/MeteorPlugin.php @@ -85,7 +85,7 @@ class MeteorPlugin extends RealtimePlugin // May throw an exception. $this->_socket = stream_socket_client("tcp://{$controlserver}:{$this->controlport}"); if (!$this->_socket) { - throw new Exception("Couldn't connect to {$controlserver} on {$this->controlport}"); + throw new Exception("Could not connect to {$controlserver} on {$this->controlport}"); } } diff --git a/plugins/OpenID/openid.php b/plugins/OpenID/openid.php index ff7a93899..cd042226b 100644 --- a/plugins/OpenID/openid.php +++ b/plugins/OpenID/openid.php @@ -36,7 +36,7 @@ function oid_store() { static $store = null; if (!$store) { - # Can't be called statically + # Cannot be called statically $user = new User(); $conn = $user->getDatabaseConnection(); $store = new Auth_OpenID_MySQLStore($conn); @@ -192,7 +192,7 @@ function oid_authenticate($openid_url, $returnto, $immediate=false) $form_html = preg_replace('/&/', '&', $form_html); - // Display an error if the form markup couldn't be generated; + // Display an error if the form markup could not be generated; // otherwise, render the HTML. if (Auth_OpenID::isFailure($form_html)) { common_server_error(sprintf(_('Could not create OpenID form: %s'), $form_html->message)); diff --git a/plugins/TwitterBridge/daemons/synctwitterfriends.php b/plugins/TwitterBridge/daemons/synctwitterfriends.php index 671e3c7af..6a155b301 100755 --- a/plugins/TwitterBridge/daemons/synctwitterfriends.php +++ b/plugins/TwitterBridge/daemons/synctwitterfriends.php @@ -126,7 +126,7 @@ class SyncTwitterFriendsDaemon extends ParallelizingDaemon $conn->disconnect(); - // XXX: Couldn't find a less brutal way to blow + // XXX: Could not find a less brutal way to blow // away a cached connection global $_DB_DATAOBJECT; @@ -188,7 +188,7 @@ class SyncTwitterFriendsDaemon extends ParallelizingDaemon if (empty($more_friends)) { common_log(LOG_WARNING, $this->name() . - " - Couldn't retrieve page $i " . + " - Could not retrieve page $i " . "of Twitter user $flink->foreign_id friends."); continue; } else { @@ -222,11 +222,11 @@ class SyncTwitterFriendsDaemon extends ParallelizingDaemon if (!save_twitter_user($friend_id, $friend_name)) { common_log(LOG_WARNING, $this-name() . - " - Couldn't save $screen_name's friend, $friend_name."); + " - Could not save $screen_name's friend, $friend_name."); continue; } - // Check to see if there's a related local user + // Check to see if there is a related local user $friend_flink = Foreign_link::getByForeignID($friend_id, TWITTER_SERVICE); diff --git a/plugins/TwitterBridge/daemons/twitterstatusfetcher.php b/plugins/TwitterBridge/daemons/twitterstatusfetcher.php index b5428316b..ab610e553 100755 --- a/plugins/TwitterBridge/daemons/twitterstatusfetcher.php +++ b/plugins/TwitterBridge/daemons/twitterstatusfetcher.php @@ -147,7 +147,7 @@ class TwitterStatusFetcher extends ParallelizingDaemon $conn->disconnect(); - // XXX: Couldn't find a less brutal way to blow + // XXX: Could not find a less brutal way to blow // away a cached connection global $_DB_DATAOBJECT; @@ -158,7 +158,7 @@ class TwitterStatusFetcher extends ParallelizingDaemon { if (empty($flink)) { common_log(LOG_WARNING, $this->name() . - " - Can't retrieve Foreign_link for foreign ID $fid"); + " - Cannot retrieve Foreign_link for foreign ID $fid"); return; } @@ -458,7 +458,7 @@ class TwitterStatusFetcher extends ParallelizingDaemon $profile = Profile::staticGet($profile_id); if (empty($profile)) { - common_debug($this->name() . " - Couldn't get profile: $profile_id!"); + common_debug($this->name() . " - Could not get profile: $profile_id!"); return; } @@ -537,7 +537,7 @@ class TwitterStatusFetcher extends ParallelizingDaemon $ok = file_put_contents($avatarfile, $response->getBody()); if (!$ok) { common_log(LOG_WARNING, $this->name() . - " - Couldn't open file $filename"); + " - Could not open file $filename"); return false; } } else { diff --git a/plugins/UserFlag/flagprofile.php b/plugins/UserFlag/flagprofile.php index c72b74c6a..84c343c48 100644 --- a/plugins/UserFlag/flagprofile.php +++ b/plugins/UserFlag/flagprofile.php @@ -135,7 +135,7 @@ class FlagprofileAction extends Action $ufp->created = common_sql_now(); if (!$ufp->insert()) { - throw new ServerException(sprintf(_("Couldn't flag profile '%s' with flag '%s'."), + throw new ServerException(sprintf(_("Could not flag profile '%s' with flag '%s'."), $this->profile->nickname, $this->flag)); } diff --git a/scripts/console.php b/scripts/console.php index 41dd43f28..2413f5079 100755 --- a/scripts/console.php +++ b/scripts/console.php @@ -90,7 +90,7 @@ function readline_emulation($prompt) if ($retval == 0) { return $line; } elseif ($retval == 127) { - // Couldn't execute bash even though we thought we saw it. + // Could not execute bash even though we thought we saw it. // Shell probably spit out an error message, sorry :( // Fall through to fgets()... } else { diff --git a/scripts/createsim.php b/scripts/createsim.php index 1266a9700..592853f86 100644 --- a/scripts/createsim.php +++ b/scripts/createsim.php @@ -85,7 +85,7 @@ function newSub($i) $from = User::staticGet('nickname', $fromnick); if (empty($from)) { - throw new Exception("Can't find user '$fromnick'."); + throw new Exception("Cannot find user '$fromnick'."); } $t = rand(0, $i - 1); @@ -102,7 +102,7 @@ function newSub($i) $to = User::staticGet('nickname', $tunic); if (empty($to)) { - throw new Exception("Can't find user '$tunic'."); + throw new Exception("Cannot find user '$tunic'."); } subs_subscribe_to($from, $to); diff --git a/scripts/deleteuser.php b/scripts/deleteuser.php index 52389123c..39331f1a8 100644 --- a/scripts/deleteuser.php +++ b/scripts/deleteuser.php @@ -39,14 +39,14 @@ if (have_option('i', 'id')) { $id = get_option_value('i', 'id'); $user = User::staticGet('id', $id); if (empty($user)) { - print "Can't find user with ID $id\n"; + print "Cannot find user with ID $id\n"; exit(1); } } else if (have_option('n', 'nickname')) { $nickname = get_option_value('n', 'nickname'); $user = User::staticGet('nickname', $nickname); if (empty($user)) { - print "Can't find user with nickname '$nickname'\n"; + print "Cannot find user with nickname '$nickname'\n"; exit(1); } } else { diff --git a/scripts/fixup_utf8.php b/scripts/fixup_utf8.php index 5a9fba7c3..5581633ec 100755 --- a/scripts/fixup_utf8.php +++ b/scripts/fixup_utf8.php @@ -76,7 +76,7 @@ class UTF8FixerUpper $succ = mysqli_set_charset($conn, $charset); if (!$succ) { - echo "ERROR: couldn't set charset\n"; + echo "ERROR: Could not set charset\n"; $db->disconnect(); return NULL; } diff --git a/scripts/makegroupadmin.php b/scripts/makegroupadmin.php index a68798451..07f980d58 100644 --- a/scripts/makegroupadmin.php +++ b/scripts/makegroupadmin.php @@ -67,7 +67,7 @@ try { $member->created = common_sql_now(); if (!$member->insert()) { - throw new Exception("Can't add '$nickname' to '$groupname'."); + throw new Exception("Cannot add '$nickname' to '$groupname'."); } } @@ -80,7 +80,7 @@ try { $member->is_admin = 1; if (!$member->update($orig)) { - throw new Exception("Can't make '$nickname' admin of '$groupname'."); + throw new Exception("Cannot make '$nickname' admin of '$groupname'."); } } catch (Exception $e) { diff --git a/scripts/registeruser.php b/scripts/registeruser.php index 5d9c8862d..8aab325b7 100644 --- a/scripts/registeruser.php +++ b/scripts/registeruser.php @@ -60,7 +60,7 @@ try { 'fullname' => $fullname)); if (empty($user)) { - throw new Exception("Can't register user '$nickname' with password '$password' and fullname '$fullname'."); + throw new Exception("Cannot register user '$nickname' with password '$password' and fullname '$fullname'."); } if (!empty($email)) { @@ -71,7 +71,7 @@ try { if (!$user->updateKeys($orig)) { print "Failed!\n"; - throw new Exception("Can't update email address."); + throw new Exception("Cannot update email address."); } } diff --git a/scripts/showcache.php b/scripts/showcache.php index f17979572..6b00a8f7b 100644 --- a/scripts/showcache.php +++ b/scripts/showcache.php @@ -58,7 +58,7 @@ print "Checking key '$k'...\n"; $c = common_memcache(); if (empty($c)) { - die("Can't initialize cache object!\n"); + die("Cannot initialize cache object!\n"); } $obj = $c->get($k); diff --git a/scripts/sitemap.php b/scripts/sitemap.php index f8c392146..ee5d33e1e 100755 --- a/scripts/sitemap.php +++ b/scripts/sitemap.php @@ -377,11 +377,11 @@ function write_file($path, $data) } if (($fh_out = fopen($path,'w')) === false) { - error("couldn't open $path for writing."); + error("Could not open $path for writing."); } if (fwrite($fh_out, $data) === false) { - error("couldn't write to $path."); + error("Could not write to $path."); } } diff --git a/scripts/update_translations.php b/scripts/update_translations.php index 580c472ee..8d4c9d3d2 100755 --- a/scripts/update_translations.php +++ b/scripts/update_translations.php @@ -98,7 +98,7 @@ foreach ($languages as $language) { $new_file = curl_get_file($file_url); if ($new_file === FALSE) { - echo "Couldn't retrieve .po file for $code: $file_url\n"; + echo "Could not retrieve .po file for $code: $file_url\n"; continue; } -- cgit v1.2.3-54-g00ecf From fc5002015b2a9e16a3c6b9992d55b45c73a8d2fb Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Sun, 8 Nov 2009 23:28:51 +0100 Subject: Revert "* [Cc]an't -> [Cc]annot" This reverts commit 0ab17f382b9993ada3d12d4cdace72cca53fb545. --- actions/emailsettings.php | 4 +- actions/smssettings.php | 2 +- classes/File.php | 2 +- classes/Notice.php | 4 +- extlib/Auth/OpenID/Consumer.php | 2 +- extlib/Auth/OpenID/Discover.php | 4 +- extlib/Auth/OpenID/FileStore.php | 2 +- extlib/DB.php | 2 +- extlib/DB/DataObject/Generator.php | 4 +- extlib/DB/dbase.php | 6 +- extlib/DB/fbsql.php | 8 +- extlib/DB/ibase.php | 6 +- extlib/DB/ifx.php | 12 +- extlib/DB/msql.php | 8 +- extlib/DB/mssql.php | 10 +- extlib/DB/mysql.php | 14 +- extlib/DB/mysqli.php | 14 +- extlib/DB/oci8.php | 10 +- extlib/DB/odbc.php | 8 +- extlib/DB/pgsql.php | 10 +- extlib/DB/sqlite.php | 8 +- extlib/DB/sybase.php | 12 +- extlib/HTTP/Request2/Adapter/Socket.php | 1940 ++--- extlib/MIME/Type.php | 4 +- extlib/MIME/Type/Extension.php | 4 +- extlib/Mail/mail.php | 2 +- extlib/Mail/sendmail.php | 2 +- extlib/Net/LDAP2/Entry.php | 2 +- extlib/Net/LDAP2/Filter.php | 2 +- extlib/System/Command.php | 2 +- extlib/markdown.php | 2 +- install.php | 16 +- lib/attachmentlist.php | 2 +- lib/noticelist.php | 2 +- lib/profilelist.php | 2 +- lib/serverexception.php | 2 +- lib/settingsaction.php | 2 +- lib/util.php | 2 +- lib/xmppqueuehandler.php | 2 +- locale/statusnet.po | 7824 +++++++++++++------- .../Facebook/facebook/facebookapi_php5_restlib.php | 2 +- .../Facebook/facebook/jsonwrapper/JSON/JSON.php | 2 +- plugins/Facebook/facebookaction.php | 2 +- plugins/Facebook/facebookhome.php | 2 +- plugins/LinkbackPlugin.php | 2 +- plugins/Meteor/MeteorPlugin.php | 2 +- plugins/OpenID/openid.php | 4 +- .../TwitterBridge/daemons/synctwitterfriends.php | 8 +- .../TwitterBridge/daemons/twitterstatusfetcher.php | 8 +- plugins/UserFlag/flagprofile.php | 2 +- scripts/console.php | 2 +- scripts/createsim.php | 4 +- scripts/deleteuser.php | 4 +- scripts/fixup_utf8.php | 2 +- scripts/makegroupadmin.php | 4 +- scripts/registeruser.php | 4 +- scripts/showcache.php | 2 +- scripts/sitemap.php | 4 +- scripts/update_translations.php | 2 +- 59 files changed, 6448 insertions(+), 3580 deletions(-) (limited to 'plugins/TwitterBridge/daemons') diff --git a/actions/emailsettings.php b/actions/emailsettings.php index 715457eab..67b991cdc 100644 --- a/actions/emailsettings.php +++ b/actions/emailsettings.php @@ -452,7 +452,7 @@ class EmailsettingsAction extends AccountSettingsAction if (!$user->updateKeys($orig)) { common_log_db_error($user, 'UPDATE', __FILE__); - $this->serverError(_("Could not update user record.")); + $this->serverError(_("Couldn't update user record.")); } $this->showForm(_('Incoming email address removed.'), true); @@ -474,7 +474,7 @@ class EmailsettingsAction extends AccountSettingsAction if (!$user->updateKeys($orig)) { common_log_db_error($user, 'UPDATE', __FILE__); - $this->serverError(_("Could not update user record.")); + $this->serverError(_("Couldn't update user record.")); } $this->showForm(_('New incoming email address added.'), true); diff --git a/actions/smssettings.php b/actions/smssettings.php index 4debe1967..9fa7f62fb 100644 --- a/actions/smssettings.php +++ b/actions/smssettings.php @@ -525,7 +525,7 @@ class SmssettingsAction extends ConnectSettingsAction if (!$user->updateKeys($orig)) { common_log_db_error($user, 'UPDATE', __FILE__); - $this->serverError(_("Could not update user record.")); + $this->serverError(_("Couldn't update user record.")); } $this->showForm(_('Incoming email address removed.'), true); diff --git a/classes/File.php b/classes/File.php index dd0c3227e..e04a9d525 100644 --- a/classes/File.php +++ b/classes/File.php @@ -99,7 +99,7 @@ class File extends Memcached_DataObject } elseif (is_string($redir_data)) { $redir_url = $redir_data; } else { - throw new ServerException("Cannot process url '$given_url'"); + throw new ServerException("Can't process url '$given_url'"); } // TODO: max field length if ($redir_url === $given_url || strlen($redir_url) > 255) { diff --git a/classes/Notice.php b/classes/Notice.php index 862d4c762..9886875cb 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -680,7 +680,7 @@ class Notice extends Memcached_DataObject return Notice::getStreamDirect($qry, $offset, $limit, null, null, $order, null); } - # Get the cache; if we cannot, just go to the DB + # Get the cache; if we can't, just go to the DB $cache = common_memcache(); @@ -1364,7 +1364,7 @@ class Notice extends Memcached_DataObject } } - // If it's not a "low bandwidth" source (one where you cannot set + // If it's not a "low bandwidth" source (one where you can't set // a reply_to argument), we return. This is mostly web and API // clients. diff --git a/extlib/Auth/OpenID/Consumer.php b/extlib/Auth/OpenID/Consumer.php index c75ef4c06..500890b65 100644 --- a/extlib/Auth/OpenID/Consumer.php +++ b/extlib/Auth/OpenID/Consumer.php @@ -1059,7 +1059,7 @@ class Auth_OpenID_GenericConsumer { } } - // Fragments do not influence discovery, so we cannot compare a + // Fragments do not influence discovery, so we can't compare a // claimed identifier with a fragment to discovered // information. list($defragged_claimed_id, $_) = diff --git a/extlib/Auth/OpenID/Discover.php b/extlib/Auth/OpenID/Discover.php index 9bb3ee357..62aeb1d2b 100644 --- a/extlib/Auth/OpenID/Discover.php +++ b/extlib/Auth/OpenID/Discover.php @@ -515,7 +515,7 @@ function Auth_OpenID_discoverXRI($iname, &$fetcher) function Auth_OpenID_discover($uri, &$fetcher) { - // If the fetcher (i.e., PHP) doesn't support SSL, we cannot do + // If the fetcher (i.e., PHP) doesn't support SSL, we can't do // discovery on an HTTPS URL. if ($fetcher->isHTTPS($uri) && !$fetcher->supportsSSL()) { return array($uri, array()); @@ -527,7 +527,7 @@ function Auth_OpenID_discover($uri, &$fetcher) $result = Auth_OpenID_discoverURI($uri, $fetcher); } - // If the fetcher doesn't support SSL, we cannot interact with + // If the fetcher doesn't support SSL, we can't interact with // HTTPS server URLs; remove those endpoints from the list. if (!$fetcher->supportsSSL()) { $http_endpoints = array(); diff --git a/extlib/Auth/OpenID/FileStore.php b/extlib/Auth/OpenID/FileStore.php index d9962e153..29d8d20e7 100644 --- a/extlib/Auth/OpenID/FileStore.php +++ b/extlib/Auth/OpenID/FileStore.php @@ -496,7 +496,7 @@ class Auth_OpenID_FileStore extends Auth_OpenID_OpenIDStore { return true; } else { - // Could not open directory. + // Couldn't open directory. return false; } } diff --git a/extlib/DB.php b/extlib/DB.php index 4ef66f66f..a511979e6 100644 --- a/extlib/DB.php +++ b/extlib/DB.php @@ -1341,7 +1341,7 @@ class DB_result * returning the total number of rows that would have been returned, * rather than the real number. As a result, we'll just do the limit * calculations for fbsql in the same way as a database with emulated - * limits. Unfortunately, we cannot just do this in DB_fbsql::numRows() + * limits. Unfortunately, we can't just do this in DB_fbsql::numRows() * because that only gets the result resource, rather than the full * DB_Result object. */ if (($this->dbh->features['limit'] === 'emulate' diff --git a/extlib/DB/DataObject/Generator.php b/extlib/DB/DataObject/Generator.php index e14e3ef7f..ff6e42c7d 100644 --- a/extlib/DB/DataObject/Generator.php +++ b/extlib/DB/DataObject/Generator.php @@ -632,7 +632,7 @@ class DB_DataObject_Generator extends DB_DataObject echo "*****************************************************************\n". "** WARNING COLUMN NAME UNUSABLE **\n". "** Found column '{$t->name}', of type '{$t->type}' **\n". - "** Since this column name cannot be converted to a php variable **\n". + "** Since this column name can't be converted to a php variable **\n". "** name, and the whole idea of mapping would result in a mess **\n". "** This column has been ignored... **\n". "*****************************************************************\n"; @@ -910,7 +910,7 @@ class DB_DataObject_Generator extends DB_DataObject echo "*****************************************************************\n". "** WARNING COLUMN NAME UNUSABLE **\n". "** Found column '{$t->name}', of type '{$t->type}' **\n". - "** Since this column name cannot be converted to a php variable **\n". + "** Since this column name can't be converted to a php variable **\n". "** name, and the whole idea of mapping would result in a mess **\n". "** This column has been ignored... **\n". "*****************************************************************\n"; diff --git a/extlib/DB/dbase.php b/extlib/DB/dbase.php index 15d259c4d..67afc897d 100644 --- a/extlib/DB/dbase.php +++ b/extlib/DB/dbase.php @@ -287,7 +287,7 @@ class DB_dbase extends DB_common * See DB_result::fetchInto() for more information. * * This method is not meant to be called directly. Use - * DB_result::fetchInto() instead. It cannot be declared "protected" + * DB_result::fetchInto() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result the query result resource @@ -352,7 +352,7 @@ class DB_dbase extends DB_common * Gets the number of columns in a result set * * This method is not meant to be called directly. Use - * DB_result::numCols() instead. It cannot be declared "protected" + * DB_result::numCols() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -373,7 +373,7 @@ class DB_dbase extends DB_common * Gets the number of rows in a result set * * This method is not meant to be called directly. Use - * DB_result::numRows() instead. It cannot be declared "protected" + * DB_result::numRows() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource diff --git a/extlib/DB/fbsql.php b/extlib/DB/fbsql.php index 48ff705cf..4de4078f7 100644 --- a/extlib/DB/fbsql.php +++ b/extlib/DB/fbsql.php @@ -262,7 +262,7 @@ class DB_fbsql extends DB_common * See DB_result::fetchInto() for more information. * * This method is not meant to be called directly. Use - * DB_result::fetchInto() instead. It cannot be declared "protected" + * DB_result::fetchInto() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result the query result resource @@ -309,7 +309,7 @@ class DB_fbsql extends DB_common * Deletes the result set and frees the memory occupied by the result set * * This method is not meant to be called directly. Use - * DB_result::free() instead. It cannot be declared "protected" + * DB_result::free() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -376,7 +376,7 @@ class DB_fbsql extends DB_common * Gets the number of columns in a result set * * This method is not meant to be called directly. Use - * DB_result::numCols() instead. It cannot be declared "protected" + * DB_result::numCols() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -401,7 +401,7 @@ class DB_fbsql extends DB_common * Gets the number of rows in a result set * * This method is not meant to be called directly. Use - * DB_result::numRows() instead. It cannot be declared "protected" + * DB_result::numRows() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource diff --git a/extlib/DB/ibase.php b/extlib/DB/ibase.php index 1e444d634..ee19c5589 100644 --- a/extlib/DB/ibase.php +++ b/extlib/DB/ibase.php @@ -353,7 +353,7 @@ class DB_ibase extends DB_common * See DB_result::fetchInto() for more information. * * This method is not meant to be called directly. Use - * DB_result::fetchInto() instead. It cannot be declared "protected" + * DB_result::fetchInto() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result the query result resource @@ -402,7 +402,7 @@ class DB_ibase extends DB_common * Deletes the result set and frees the memory occupied by the result set * * This method is not meant to be called directly. Use - * DB_result::free() instead. It cannot be declared "protected" + * DB_result::free() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -449,7 +449,7 @@ class DB_ibase extends DB_common * Gets the number of columns in a result set * * This method is not meant to be called directly. Use - * DB_result::numCols() instead. It cannot be declared "protected" + * DB_result::numCols() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource diff --git a/extlib/DB/ifx.php b/extlib/DB/ifx.php index dcb3dbd3e..baa6f2867 100644 --- a/extlib/DB/ifx.php +++ b/extlib/DB/ifx.php @@ -147,7 +147,7 @@ class DB_ifx extends DB_common /** * The quantity of transactions begun * - * {@internal While this is private, it cannot actually be designated + * {@internal While this is private, it can't actually be designated * private in PHP 5 because it is directly accessed in the test suite.}} * * @var integer @@ -328,7 +328,7 @@ class DB_ifx extends DB_common * See DB_result::fetchInto() for more information. * * This method is not meant to be called directly. Use - * DB_result::fetchInto() instead. It cannot be declared "protected" + * DB_result::fetchInto() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result the query result resource @@ -387,7 +387,7 @@ class DB_ifx extends DB_common * Gets the number of columns in a result set * * This method is not meant to be called directly. Use - * DB_result::numCols() instead. It cannot be declared "protected" + * DB_result::numCols() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -411,7 +411,7 @@ class DB_ifx extends DB_common * Deletes the result set and frees the memory occupied by the result set * * This method is not meant to be called directly. Use - * DB_result::free() instead. It cannot be declared "protected" + * DB_result::free() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -555,7 +555,7 @@ class DB_ifx extends DB_common * * If analyzing a query result and the result has duplicate field names, * an error will be raised saying - * cannot distinguish duplicate field names. + * can't distinguish duplicate field names. * * @param object|string $result DB_result object from a query or a * string containing the name of a table. @@ -604,7 +604,7 @@ class DB_ifx extends DB_common $count = @ifx_num_fields($id); if (count($flds) != $count) { - return $this->raiseError("cannot distinguish duplicate field names"); + return $this->raiseError("can't distinguish duplicate field names"); } if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { diff --git a/extlib/DB/msql.php b/extlib/DB/msql.php index ee64f932f..34854f472 100644 --- a/extlib/DB/msql.php +++ b/extlib/DB/msql.php @@ -288,7 +288,7 @@ class DB_msql extends DB_common * See DB_result::fetchInto() for more information. * * This method is not meant to be called directly. Use - * DB_result::fetchInto() instead. It cannot be declared "protected" + * DB_result::fetchInto() instead. It can't be declared "protected" * because DB_result is a separate object. * * PHP's mSQL extension did weird things with NULL values prior to PHP @@ -339,7 +339,7 @@ class DB_msql extends DB_common * Deletes the result set and frees the memory occupied by the result set * * This method is not meant to be called directly. Use - * DB_result::free() instead. It cannot be declared "protected" + * DB_result::free() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -360,7 +360,7 @@ class DB_msql extends DB_common * Gets the number of columns in a result set * * This method is not meant to be called directly. Use - * DB_result::numCols() instead. It cannot be declared "protected" + * DB_result::numCols() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -385,7 +385,7 @@ class DB_msql extends DB_common * Gets the number of rows in a result set * * This method is not meant to be called directly. Use - * DB_result::numRows() instead. It cannot be declared "protected" + * DB_result::numRows() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource diff --git a/extlib/DB/mssql.php b/extlib/DB/mssql.php index 1aad75671..511a2b686 100644 --- a/extlib/DB/mssql.php +++ b/extlib/DB/mssql.php @@ -156,7 +156,7 @@ class DB_mssql extends DB_common /** * The quantity of transactions begun * - * {@internal While this is private, it cannot actually be designated + * {@internal While this is private, it can't actually be designated * private in PHP 5 because it is directly accessed in the test suite.}} * * @var integer @@ -324,7 +324,7 @@ class DB_mssql extends DB_common * See DB_result::fetchInto() for more information. * * This method is not meant to be called directly. Use - * DB_result::fetchInto() instead. It cannot be declared "protected" + * DB_result::fetchInto() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result the query result resource @@ -371,7 +371,7 @@ class DB_mssql extends DB_common * Deletes the result set and frees the memory occupied by the result set * * This method is not meant to be called directly. Use - * DB_result::free() instead. It cannot be declared "protected" + * DB_result::free() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -392,7 +392,7 @@ class DB_mssql extends DB_common * Gets the number of columns in a result set * * This method is not meant to be called directly. Use - * DB_result::numCols() instead. It cannot be declared "protected" + * DB_result::numCols() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -417,7 +417,7 @@ class DB_mssql extends DB_common * Gets the number of rows in a result set * * This method is not meant to be called directly. Use - * DB_result::numRows() instead. It cannot be declared "protected" + * DB_result::numRows() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource diff --git a/extlib/DB/mysql.php b/extlib/DB/mysql.php index bfe34dbe8..c67254520 100644 --- a/extlib/DB/mysql.php +++ b/extlib/DB/mysql.php @@ -139,7 +139,7 @@ class DB_mysql extends DB_common /** * The quantity of transactions begun * - * {@internal While this is private, it cannot actually be designated + * {@internal While this is private, it can't actually be designated * private in PHP 5 because it is directly accessed in the test suite.}} * * @var integer @@ -359,7 +359,7 @@ class DB_mysql extends DB_common * See DB_result::fetchInto() for more information. * * This method is not meant to be called directly. Use - * DB_result::fetchInto() instead. It cannot be declared "protected" + * DB_result::fetchInto() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result the query result resource @@ -411,7 +411,7 @@ class DB_mysql extends DB_common * Deletes the result set and frees the memory occupied by the result set * * This method is not meant to be called directly. Use - * DB_result::free() instead. It cannot be declared "protected" + * DB_result::free() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -432,7 +432,7 @@ class DB_mysql extends DB_common * Gets the number of columns in a result set * * This method is not meant to be called directly. Use - * DB_result::numCols() instead. It cannot be declared "protected" + * DB_result::numCols() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -457,7 +457,7 @@ class DB_mysql extends DB_common * Gets the number of rows in a result set * * This method is not meant to be called directly. Use - * DB_result::numRows() instead. It cannot be declared "protected" + * DB_result::numRows() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -722,7 +722,7 @@ class DB_mysql extends DB_common return $result; } if ($result == 0) { - // Failed to get the lock, cannot do the conversion, bail + // Failed to get the lock, can't do the conversion, bail // with a DB_ERROR_NOT_LOCKED error return $this->mysqlRaiseError(DB_ERROR_NOT_LOCKED); } @@ -757,7 +757,7 @@ class DB_mysql extends DB_common * Quotes a string so it can be safely used as a table or column name * (WARNING: using names that require this is a REALLY BAD IDEA) * - * WARNING: Older versions of MySQL cannot handle the backtick + * WARNING: Older versions of MySQL can't handle the backtick * character (`) in table or column names. * * @param string $str identifier name to be quoted diff --git a/extlib/DB/mysqli.php b/extlib/DB/mysqli.php index b6196dfcc..c6941b170 100644 --- a/extlib/DB/mysqli.php +++ b/extlib/DB/mysqli.php @@ -142,7 +142,7 @@ class DB_mysqli extends DB_common /** * The quantity of transactions begun * - * {@internal While this is private, it cannot actually be designated + * {@internal While this is private, it can't actually be designated * private in PHP 5 because it is directly accessed in the test suite.}} * * @var integer @@ -434,7 +434,7 @@ class DB_mysqli extends DB_common * See DB_result::fetchInto() for more information. * * This method is not meant to be called directly. Use - * DB_result::fetchInto() instead. It cannot be declared "protected" + * DB_result::fetchInto() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result the query result resource @@ -486,7 +486,7 @@ class DB_mysqli extends DB_common * Deletes the result set and frees the memory occupied by the result set * * This method is not meant to be called directly. Use - * DB_result::free() instead. It cannot be declared "protected" + * DB_result::free() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -507,7 +507,7 @@ class DB_mysqli extends DB_common * Gets the number of columns in a result set * * This method is not meant to be called directly. Use - * DB_result::numCols() instead. It cannot be declared "protected" + * DB_result::numCols() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -532,7 +532,7 @@ class DB_mysqli extends DB_common * Gets the number of rows in a result set * * This method is not meant to be called directly. Use - * DB_result::numRows() instead. It cannot be declared "protected" + * DB_result::numRows() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -796,7 +796,7 @@ class DB_mysqli extends DB_common return $result; } if ($result == 0) { - // Failed to get the lock, cannot do the conversion, bail + // Failed to get the lock, can't do the conversion, bail // with a DB_ERROR_NOT_LOCKED error return $this->mysqliRaiseError(DB_ERROR_NOT_LOCKED); } @@ -832,7 +832,7 @@ class DB_mysqli extends DB_common * Quotes a string so it can be safely used as a table or column name * (WARNING: using names that require this is a REALLY BAD IDEA) * - * WARNING: Older versions of MySQL cannot handle the backtick + * WARNING: Older versions of MySQL can't handle the backtick * character (`) in table or column names. * * @param string $str identifier name to be quoted diff --git a/extlib/DB/oci8.php b/extlib/DB/oci8.php index 6ad36643a..d30794871 100644 --- a/extlib/DB/oci8.php +++ b/extlib/DB/oci8.php @@ -251,7 +251,7 @@ class DB_oci8 extends DB_common $char); $error = OCIError(); if (!empty($error) && $error['code'] == 12541) { - // Could not find TNS listener. Try direct connection. + // Couldn't find TNS listener. Try direct connection. $this->connection = @$connect_function($dsn['username'], $dsn['password'], null, @@ -368,7 +368,7 @@ class DB_oci8 extends DB_common * See DB_result::fetchInto() for more information. * * This method is not meant to be called directly. Use - * DB_result::fetchInto() instead. It cannot be declared "protected" + * DB_result::fetchInto() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result the query result resource @@ -415,7 +415,7 @@ class DB_oci8 extends DB_common * Deletes the result set and frees the memory occupied by the result set * * This method is not meant to be called directly. Use - * DB_result::free() instead. It cannot be declared "protected" + * DB_result::free() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -468,7 +468,7 @@ class DB_oci8 extends DB_common * is turned on. * * This method is not meant to be called directly. Use - * DB_result::numRows() instead. It cannot be declared "protected" + * DB_result::numRows() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -511,7 +511,7 @@ class DB_oci8 extends DB_common * Gets the number of columns in a result set * * This method is not meant to be called directly. Use - * DB_result::numCols() instead. It cannot be declared "protected" + * DB_result::numCols() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource diff --git a/extlib/DB/odbc.php b/extlib/DB/odbc.php index b0dc83ab5..eba43659a 100644 --- a/extlib/DB/odbc.php +++ b/extlib/DB/odbc.php @@ -301,7 +301,7 @@ class DB_odbc extends DB_common * See DB_result::fetchInto() for more information. * * This method is not meant to be called directly. Use - * DB_result::fetchInto() instead. It cannot be declared "protected" + * DB_result::fetchInto() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result the query result resource @@ -356,7 +356,7 @@ class DB_odbc extends DB_common * Deletes the result set and frees the memory occupied by the result set * * This method is not meant to be called directly. Use - * DB_result::free() instead. It cannot be declared "protected" + * DB_result::free() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -377,7 +377,7 @@ class DB_odbc extends DB_common * Gets the number of columns in a result set * * This method is not meant to be called directly. Use - * DB_result::numCols() instead. It cannot be declared "protected" + * DB_result::numCols() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -427,7 +427,7 @@ class DB_odbc extends DB_common * a DB_Error object for DB_ERROR_UNSUPPORTED is returned. * * This method is not meant to be called directly. Use - * DB_result::numRows() instead. It cannot be declared "protected" + * DB_result::numRows() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource diff --git a/extlib/DB/pgsql.php b/extlib/DB/pgsql.php index 498ef8ade..6030bb4c1 100644 --- a/extlib/DB/pgsql.php +++ b/extlib/DB/pgsql.php @@ -115,7 +115,7 @@ class DB_pgsql extends DB_common /** * The quantity of transactions begun * - * {@internal While this is private, it cannot actually be designated + * {@internal While this is private, it can't actually be designated * private in PHP 5 because it is directly accessed in the test suite.}} * * @var integer @@ -397,7 +397,7 @@ class DB_pgsql extends DB_common * See DB_result::fetchInto() for more information. * * This method is not meant to be called directly. Use - * DB_result::fetchInto() instead. It cannot be declared "protected" + * DB_result::fetchInto() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result the query result resource @@ -445,7 +445,7 @@ class DB_pgsql extends DB_common * Deletes the result set and frees the memory occupied by the result set * * This method is not meant to be called directly. Use - * DB_result::free() instead. It cannot be declared "protected" + * DB_result::free() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -535,7 +535,7 @@ class DB_pgsql extends DB_common * Gets the number of columns in a result set * * This method is not meant to be called directly. Use - * DB_result::numCols() instead. It cannot be declared "protected" + * DB_result::numCols() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -560,7 +560,7 @@ class DB_pgsql extends DB_common * Gets the number of rows in a result set * * This method is not meant to be called directly. Use - * DB_result::numRows() instead. It cannot be declared "protected" + * DB_result::numRows() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource diff --git a/extlib/DB/sqlite.php b/extlib/DB/sqlite.php index 96d5c934a..5c4b396e5 100644 --- a/extlib/DB/sqlite.php +++ b/extlib/DB/sqlite.php @@ -334,7 +334,7 @@ class DB_sqlite extends DB_common * See DB_result::fetchInto() for more information. * * This method is not meant to be called directly. Use - * DB_result::fetchInto() instead. It cannot be declared "protected" + * DB_result::fetchInto() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result the query result resource @@ -396,7 +396,7 @@ class DB_sqlite extends DB_common * Deletes the result set and frees the memory occupied by the result set * * This method is not meant to be called directly. Use - * DB_result::free() instead. It cannot be declared "protected" + * DB_result::free() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -422,7 +422,7 @@ class DB_sqlite extends DB_common * Gets the number of columns in a result set * * This method is not meant to be called directly. Use - * DB_result::numCols() instead. It cannot be declared "protected" + * DB_result::numCols() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -447,7 +447,7 @@ class DB_sqlite extends DB_common * Gets the number of rows in a result set * * This method is not meant to be called directly. Use - * DB_result::numRows() instead. It cannot be declared "protected" + * DB_result::numRows() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource diff --git a/extlib/DB/sybase.php b/extlib/DB/sybase.php index 97ab41a22..3befbf6ea 100644 --- a/extlib/DB/sybase.php +++ b/extlib/DB/sybase.php @@ -118,7 +118,7 @@ class DB_sybase extends DB_common /** * The quantity of transactions begun * - * {@internal While this is private, it cannot actually be designated + * {@internal While this is private, it can't actually be designated * private in PHP 5 because it is directly accessed in the test suite.}} * * @var integer @@ -302,7 +302,7 @@ class DB_sybase extends DB_common * See DB_result::fetchInto() for more information. * * This method is not meant to be called directly. Use - * DB_result::fetchInto() instead. It cannot be declared "protected" + * DB_result::fetchInto() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result the query result resource @@ -359,7 +359,7 @@ class DB_sybase extends DB_common * Deletes the result set and frees the memory occupied by the result set * * This method is not meant to be called directly. Use - * DB_result::free() instead. It cannot be declared "protected" + * DB_result::free() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -380,7 +380,7 @@ class DB_sybase extends DB_common * Gets the number of columns in a result set * * This method is not meant to be called directly. Use - * DB_result::numCols() instead. It cannot be declared "protected" + * DB_result::numCols() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -405,7 +405,7 @@ class DB_sybase extends DB_common * Gets the number of rows in a result set * * This method is not meant to be called directly. Use - * DB_result::numRows() instead. It cannot be declared "protected" + * DB_result::numRows() instead. It can't be declared "protected" * because DB_result is a separate object. * * @param resource $result PHP's query result resource @@ -835,7 +835,7 @@ class DB_sybase extends DB_common $tableName = $table; /* We're running sp_helpindex directly because it doesn't exist in - * older versions of ASE -- unfortunately, we cannot just use + * older versions of ASE -- unfortunately, we can't just use * DB::isError() because the user may be using callback error * handling. */ $res = @sybase_query("sp_helpindex $table", $this->connection); diff --git a/extlib/HTTP/Request2/Adapter/Socket.php b/extlib/HTTP/Request2/Adapter/Socket.php index 13cd6136f..ff44d4959 100644 --- a/extlib/HTTP/Request2/Adapter/Socket.php +++ b/extlib/HTTP/Request2/Adapter/Socket.php @@ -1,971 +1,971 @@ - - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * The names of the authors may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * @category HTTP - * @package HTTP_Request2 - * @author Alexey Borzov - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version CVS: $Id: Socket.php 279760 2009-05-03 10:46:42Z avb $ - * @link http://pear.php.net/package/HTTP_Request2 - */ - -/** - * Base class for HTTP_Request2 adapters - */ -require_once 'HTTP/Request2/Adapter.php'; - -/** - * Socket-based adapter for HTTP_Request2 - * - * This adapter uses only PHP sockets and will work on almost any PHP - * environment. Code is based on original HTTP_Request PEAR package. - * - * @category HTTP - * @package HTTP_Request2 - * @author Alexey Borzov - * @version Release: 0.4.1 - */ -class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter -{ - /** - * Regular expression for 'token' rule from RFC 2616 - */ - const REGEXP_TOKEN = '[^\x00-\x1f\x7f-\xff()<>@,;:\\\\"/\[\]?={}\s]+'; - - /** - * Regular expression for 'quoted-string' rule from RFC 2616 - */ - const REGEXP_QUOTED_STRING = '"(?:\\\\.|[^\\\\"])*"'; - - /** - * Connected sockets, needed for Keep-Alive support - * @var array - * @see connect() - */ - protected static $sockets = array(); - - /** - * Data for digest authentication scheme - * - * The keys for the array are URL prefixes. - * - * The values are associative arrays with data (realm, nonce, nonce-count, - * opaque...) needed for digest authentication. Stored here to prevent making - * duplicate requests to digest-protected resources after we have already - * received the challenge. - * - * @var array - */ - protected static $challenges = array(); - - /** - * Connected socket - * @var resource - * @see connect() - */ - protected $socket; - - /** - * Challenge used for server digest authentication - * @var array - */ - protected $serverChallenge; - - /** - * Challenge used for proxy digest authentication - * @var array - */ - protected $proxyChallenge; - - /** - * Global timeout, exception will be raised if request continues past this time - * @var integer - */ - protected $timeout = null; - - /** - * Remaining length of the current chunk, when reading chunked response - * @var integer - * @see readChunked() - */ - protected $chunkLength = 0; - - /** - * Sends request to the remote server and returns its response - * - * @param HTTP_Request2 - * @return HTTP_Request2_Response - * @throws HTTP_Request2_Exception - */ - public function sendRequest(HTTP_Request2 $request) - { - $this->request = $request; - $keepAlive = $this->connect(); - $headers = $this->prepareHeaders(); - - // Use global request timeout if given, see feature requests #5735, #8964 - if ($timeout = $request->getConfig('timeout')) { - $this->timeout = time() + $timeout; - } else { - $this->timeout = null; - } - - try { - if (false === @fwrite($this->socket, $headers, strlen($headers))) { - throw new HTTP_Request2_Exception('Error writing request'); - } - // provide request headers to the observer, see request #7633 - $this->request->setLastEvent('sentHeaders', $headers); - $this->writeBody(); - - if ($this->timeout && time() > $this->timeout) { - throw new HTTP_Request2_Exception( - 'Request timed out after ' . - $request->getConfig('timeout') . ' second(s)' - ); - } - - $response = $this->readResponse(); - - if (!$this->canKeepAlive($keepAlive, $response)) { - $this->disconnect(); - } - - if ($this->shouldUseProxyDigestAuth($response)) { - return $this->sendRequest($request); - } - if ($this->shouldUseServerDigestAuth($response)) { - return $this->sendRequest($request); - } - if ($authInfo = $response->getHeader('authentication-info')) { - $this->updateChallenge($this->serverChallenge, $authInfo); - } - if ($proxyInfo = $response->getHeader('proxy-authentication-info')) { - $this->updateChallenge($this->proxyChallenge, $proxyInfo); - } - - } catch (Exception $e) { - $this->disconnect(); - throw $e; - } - - return $response; - } - - /** - * Connects to the remote server - * - * @return bool whether the connection can be persistent - * @throws HTTP_Request2_Exception - */ - protected function connect() - { - $secure = 0 == strcasecmp($this->request->getUrl()->getScheme(), 'https'); - $tunnel = HTTP_Request2::METHOD_CONNECT == $this->request->getMethod(); - $headers = $this->request->getHeaders(); - $reqHost = $this->request->getUrl()->getHost(); - if (!($reqPort = $this->request->getUrl()->getPort())) { - $reqPort = $secure? 443: 80; - } - - if ($host = $this->request->getConfig('proxy_host')) { - if (!($port = $this->request->getConfig('proxy_port'))) { - throw new HTTP_Request2_Exception('Proxy port not provided'); - } - $proxy = true; - } else { - $host = $reqHost; - $port = $reqPort; - $proxy = false; - } - - if ($tunnel && !$proxy) { - throw new HTTP_Request2_Exception( - "Trying to perform CONNECT request without proxy" - ); - } - if ($secure && !in_array('ssl', stream_get_transports())) { - throw new HTTP_Request2_Exception( - 'Need OpenSSL support for https:// requests' - ); - } - - // RFC 2068, section 19.7.1: A client MUST NOT send the Keep-Alive - // connection token to a proxy server... - if ($proxy && !$secure && - !empty($headers['connection']) && 'Keep-Alive' == $headers['connection'] - ) { - $this->request->setHeader('connection'); - } - - $keepAlive = ('1.1' == $this->request->getConfig('protocol_version') && - empty($headers['connection'])) || - (!empty($headers['connection']) && - 'Keep-Alive' == $headers['connection']); - $host = ((!$secure || $proxy)? 'tcp://': 'ssl://') . $host; - - $options = array(); - if ($secure || $tunnel) { - foreach ($this->request->getConfig() as $name => $value) { - if ('ssl_' == substr($name, 0, 4) && null !== $value) { - if ('ssl_verify_host' == $name) { - if ($value) { - $options['CN_match'] = $reqHost; - } - } else { - $options[substr($name, 4)] = $value; - } - } - } - ksort($options); - } - - // Changing SSL context options after connection is established does *not* - // work, we need a new connection if options change - $remote = $host . ':' . $port; - $socketKey = $remote . (($secure && $proxy)? "->{$reqHost}:{$reqPort}": '') . - (empty($options)? '': ':' . serialize($options)); - unset($this->socket); - - // We use persistent connections and have a connected socket? - // Ensure that the socket is still connected, see bug #16149 - if ($keepAlive && !empty(self::$sockets[$socketKey]) && - !feof(self::$sockets[$socketKey]) - ) { - $this->socket =& self::$sockets[$socketKey]; - - } elseif ($secure && $proxy && !$tunnel) { - $this->establishTunnel(); - $this->request->setLastEvent( - 'connect', "ssl://{$reqHost}:{$reqPort} via {$host}:{$port}" - ); - self::$sockets[$socketKey] =& $this->socket; - - } else { - // Set SSL context options if doing HTTPS request or creating a tunnel - $context = stream_context_create(); - foreach ($options as $name => $value) { - if (!stream_context_set_option($context, 'ssl', $name, $value)) { - throw new HTTP_Request2_Exception( - "Error setting SSL context option '{$name}'" - ); - } - } - $this->socket = @stream_socket_client( - $remote, $errno, $errstr, - $this->request->getConfig('connect_timeout'), - STREAM_CLIENT_CONNECT, $context - ); - if (!$this->socket) { - throw new HTTP_Request2_Exception( - "Unable to connect to {$remote}. Error #{$errno}: {$errstr}" - ); - } - $this->request->setLastEvent('connect', $remote); - self::$sockets[$socketKey] =& $this->socket; - } - return $keepAlive; - } - - /** - * Establishes a tunnel to a secure remote server via HTTP CONNECT request - * - * This method will fail if 'ssl_verify_peer' is enabled. Probably because PHP - * sees that we are connected to a proxy server (duh!) rather than the server - * that presents its certificate. - * - * @link http://tools.ietf.org/html/rfc2817#section-5.2 - * @throws HTTP_Request2_Exception - */ - protected function establishTunnel() - { - $donor = new self; - $connect = new HTTP_Request2( - $this->request->getUrl(), HTTP_Request2::METHOD_CONNECT, - array_merge($this->request->getConfig(), - array('adapter' => $donor)) - ); - $response = $connect->send(); - // Need any successful (2XX) response - if (200 > $response->getStatus() || 300 <= $response->getStatus()) { - throw new HTTP_Request2_Exception( - 'Failed to connect via HTTPS proxy. Proxy response: ' . - $response->getStatus() . ' ' . $response->getReasonPhrase() - ); - } - $this->socket = $donor->socket; - - $modes = array( - STREAM_CRYPTO_METHOD_TLS_CLIENT, - STREAM_CRYPTO_METHOD_SSLv3_CLIENT, - STREAM_CRYPTO_METHOD_SSLv23_CLIENT, - STREAM_CRYPTO_METHOD_SSLv2_CLIENT - ); - - foreach ($modes as $mode) { - if (stream_socket_enable_crypto($this->socket, true, $mode)) { - return; - } - } - throw new HTTP_Request2_Exception( - 'Failed to enable secure connection when connecting through proxy' - ); - } - - /** - * Checks whether current connection may be reused or should be closed - * - * @param boolean whether connection could be persistent - * in the first place - * @param HTTP_Request2_Response response object to check - * @return boolean - */ - protected function canKeepAlive($requestKeepAlive, HTTP_Request2_Response $response) - { - // Do not close socket on successful CONNECT request - if (HTTP_Request2::METHOD_CONNECT == $this->request->getMethod() && - 200 <= $response->getStatus() && 300 > $response->getStatus() - ) { - return true; - } - - $lengthKnown = 'chunked' == strtolower($response->getHeader('transfer-encoding')) || - null !== $response->getHeader('content-length'); - $persistent = 'keep-alive' == strtolower($response->getHeader('connection')) || - (null === $response->getHeader('connection') && - '1.1' == $response->getVersion()); - return $requestKeepAlive && $lengthKnown && $persistent; - } - - /** - * Disconnects from the remote server - */ - protected function disconnect() - { - if (is_resource($this->socket)) { - fclose($this->socket); - $this->socket = null; - $this->request->setLastEvent('disconnect'); - } - } - - /** - * Checks whether another request should be performed with server digest auth - * - * Several conditions should be satisfied for it to return true: - * - response status should be 401 - * - auth credentials should be set in the request object - * - response should contain WWW-Authenticate header with digest challenge - * - there is either no challenge stored for this URL or new challenge - * contains stale=true parameter (in other case we probably just failed - * due to invalid username / password) - * - * The method stores challenge values in $challenges static property - * - * @param HTTP_Request2_Response response to check - * @return boolean whether another request should be performed - * @throws HTTP_Request2_Exception in case of unsupported challenge parameters - */ - protected function shouldUseServerDigestAuth(HTTP_Request2_Response $response) - { - // no sense repeating a request if we don't have credentials - if (401 != $response->getStatus() || !$this->request->getAuth()) { - return false; - } - if (!$challenge = $this->parseDigestChallenge($response->getHeader('www-authenticate'))) { - return false; - } - - $url = $this->request->getUrl(); - $scheme = $url->getScheme(); - $host = $scheme . '://' . $url->getHost(); - if ($port = $url->getPort()) { - if ((0 == strcasecmp($scheme, 'http') && 80 != $port) || - (0 == strcasecmp($scheme, 'https') && 443 != $port) - ) { - $host .= ':' . $port; - } - } - - if (!empty($challenge['domain'])) { - $prefixes = array(); - foreach (preg_split('/\\s+/', $challenge['domain']) as $prefix) { - // don't bother with different servers - if ('/' == substr($prefix, 0, 1)) { - $prefixes[] = $host . $prefix; - } - } - } - if (empty($prefixes)) { - $prefixes = array($host . '/'); - } - - $ret = true; - foreach ($prefixes as $prefix) { - if (!empty(self::$challenges[$prefix]) && - (empty($challenge['stale']) || strcasecmp('true', $challenge['stale'])) - ) { - // probably credentials are invalid - $ret = false; - } - self::$challenges[$prefix] =& $challenge; - } - return $ret; - } - - /** - * Checks whether another request should be performed with proxy digest auth - * - * Several conditions should be satisfied for it to return true: - * - response status should be 407 - * - proxy auth credentials should be set in the request object - * - response should contain Proxy-Authenticate header with digest challenge - * - there is either no challenge stored for this proxy or new challenge - * contains stale=true parameter (in other case we probably just failed - * due to invalid username / password) - * - * The method stores challenge values in $challenges static property - * - * @param HTTP_Request2_Response response to check - * @return boolean whether another request should be performed - * @throws HTTP_Request2_Exception in case of unsupported challenge parameters - */ - protected function shouldUseProxyDigestAuth(HTTP_Request2_Response $response) - { - if (407 != $response->getStatus() || !$this->request->getConfig('proxy_user')) { - return false; - } - if (!($challenge = $this->parseDigestChallenge($response->getHeader('proxy-authenticate')))) { - return false; - } - - $key = 'proxy://' . $this->request->getConfig('proxy_host') . - ':' . $this->request->getConfig('proxy_port'); - - if (!empty(self::$challenges[$key]) && - (empty($challenge['stale']) || strcasecmp('true', $challenge['stale'])) - ) { - $ret = false; - } else { - $ret = true; - } - self::$challenges[$key] = $challenge; - return $ret; - } - - /** - * Extracts digest method challenge from (WWW|Proxy)-Authenticate header value - * - * There is a problem with implementation of RFC 2617: several of the parameters - * here are defined as quoted-string and thus may contain backslash escaped - * double quotes (RFC 2616, section 2.2). However, RFC 2617 defines unq(X) as - * just value of quoted-string X without surrounding quotes, it doesn't speak - * about removing backslash escaping. - * - * Now realm parameter is user-defined and human-readable, strange things - * happen when it contains quotes: - * - Apache allows quotes in realm, but apparently uses realm value without - * backslashes for digest computation - * - Squid allows (manually escaped) quotes there, but it is impossible to - * authorize with either escaped or unescaped quotes used in digest, - * probably it cannot parse the response (?) - * - Both IE and Firefox display realm value with backslashes in - * the password popup and apparently use the same value for digest - * - * HTTP_Request2 follows IE and Firefox (and hopefully RFC 2617) in - * quoted-string handling, unfortunately that means failure to authorize - * sometimes - * - * @param string value of WWW-Authenticate or Proxy-Authenticate header - * @return mixed associative array with challenge parameters, false if - * no challenge is present in header value - * @throws HTTP_Request2_Exception in case of unsupported challenge parameters - */ - protected function parseDigestChallenge($headerValue) - { - $authParam = '(' . self::REGEXP_TOKEN . ')\\s*=\\s*(' . - self::REGEXP_TOKEN . '|' . self::REGEXP_QUOTED_STRING . ')'; - $challenge = "!(?<=^|\\s|,)Digest ({$authParam}\\s*(,\\s*|$))+!"; - if (!preg_match($challenge, $headerValue, $matches)) { - return false; - } - - preg_match_all('!' . $authParam . '!', $matches[0], $params); - $paramsAry = array(); - $knownParams = array('realm', 'domain', 'nonce', 'opaque', 'stale', - 'algorithm', 'qop'); - for ($i = 0; $i < count($params[0]); $i++) { - // section 3.2.1: Any unrecognized directive MUST be ignored. - if (in_array($params[1][$i], $knownParams)) { - if ('"' == substr($params[2][$i], 0, 1)) { - $paramsAry[$params[1][$i]] = substr($params[2][$i], 1, -1); - } else { - $paramsAry[$params[1][$i]] = $params[2][$i]; - } - } - } - // we only support qop=auth - if (!empty($paramsAry['qop']) && - !in_array('auth', array_map('trim', explode(',', $paramsAry['qop']))) - ) { - throw new HTTP_Request2_Exception( - "Only 'auth' qop is currently supported in digest authentication, " . - "server requested '{$paramsAry['qop']}'" - ); - } - // we only support algorithm=MD5 - if (!empty($paramsAry['algorithm']) && 'MD5' != $paramsAry['algorithm']) { - throw new HTTP_Request2_Exception( - "Only 'MD5' algorithm is currently supported in digest authentication, " . - "server requested '{$paramsAry['algorithm']}'" - ); - } - - return $paramsAry; - } - - /** - * Parses [Proxy-]Authentication-Info header value and updates challenge - * - * @param array challenge to update - * @param string value of [Proxy-]Authentication-Info header - * @todo validate server rspauth response - */ - protected function updateChallenge(&$challenge, $headerValue) - { - $authParam = '!(' . self::REGEXP_TOKEN . ')\\s*=\\s*(' . - self::REGEXP_TOKEN . '|' . self::REGEXP_QUOTED_STRING . ')!'; - $paramsAry = array(); - - preg_match_all($authParam, $headerValue, $params); - for ($i = 0; $i < count($params[0]); $i++) { - if ('"' == substr($params[2][$i], 0, 1)) { - $paramsAry[$params[1][$i]] = substr($params[2][$i], 1, -1); - } else { - $paramsAry[$params[1][$i]] = $params[2][$i]; - } - } - // for now, just update the nonce value - if (!empty($paramsAry['nextnonce'])) { - $challenge['nonce'] = $paramsAry['nextnonce']; - $challenge['nc'] = 1; - } - } - - /** - * Creates a value for [Proxy-]Authorization header when using digest authentication - * - * @param string user name - * @param string password - * @param string request URL - * @param array digest challenge parameters - * @return string value of [Proxy-]Authorization request header - * @link http://tools.ietf.org/html/rfc2617#section-3.2.2 - */ - protected function createDigestResponse($user, $password, $url, &$challenge) - { - if (false !== ($q = strpos($url, '?')) && - $this->request->getConfig('digest_compat_ie') - ) { - $url = substr($url, 0, $q); - } - - $a1 = md5($user . ':' . $challenge['realm'] . ':' . $password); - $a2 = md5($this->request->getMethod() . ':' . $url); - - if (empty($challenge['qop'])) { - $digest = md5($a1 . ':' . $challenge['nonce'] . ':' . $a2); - } else { - $challenge['cnonce'] = 'Req2.' . rand(); - if (empty($challenge['nc'])) { - $challenge['nc'] = 1; - } - $nc = sprintf('%08x', $challenge['nc']++); - $digest = md5($a1 . ':' . $challenge['nonce'] . ':' . $nc . ':' . - $challenge['cnonce'] . ':auth:' . $a2); - } - return 'Digest username="' . str_replace(array('\\', '"'), array('\\\\', '\\"'), $user) . '", ' . - 'realm="' . $challenge['realm'] . '", ' . - 'nonce="' . $challenge['nonce'] . '", ' . - 'uri="' . $url . '", ' . - 'response="' . $digest . '"' . - (!empty($challenge['opaque'])? - ', opaque="' . $challenge['opaque'] . '"': - '') . - (!empty($challenge['qop'])? - ', qop="auth", nc=' . $nc . ', cnonce="' . $challenge['cnonce'] . '"': - ''); - } - - /** - * Adds 'Authorization' header (if needed) to request headers array - * - * @param array request headers - * @param string request host (needed for digest authentication) - * @param string request URL (needed for digest authentication) - * @throws HTTP_Request2_Exception - */ - protected function addAuthorizationHeader(&$headers, $requestHost, $requestUrl) - { - if (!($auth = $this->request->getAuth())) { - return; - } - switch ($auth['scheme']) { - case HTTP_Request2::AUTH_BASIC: - $headers['authorization'] = - 'Basic ' . base64_encode($auth['user'] . ':' . $auth['password']); - break; - - case HTTP_Request2::AUTH_DIGEST: - unset($this->serverChallenge); - $fullUrl = ('/' == $requestUrl[0])? - $this->request->getUrl()->getScheme() . '://' . - $requestHost . $requestUrl: - $requestUrl; - foreach (array_keys(self::$challenges) as $key) { - if ($key == substr($fullUrl, 0, strlen($key))) { - $headers['authorization'] = $this->createDigestResponse( - $auth['user'], $auth['password'], - $requestUrl, self::$challenges[$key] - ); - $this->serverChallenge =& self::$challenges[$key]; - break; - } - } - break; - - default: - throw new HTTP_Request2_Exception( - "Unknown HTTP authentication scheme '{$auth['scheme']}'" - ); - } - } - - /** - * Adds 'Proxy-Authorization' header (if needed) to request headers array - * - * @param array request headers - * @param string request URL (needed for digest authentication) - * @throws HTTP_Request2_Exception - */ - protected function addProxyAuthorizationHeader(&$headers, $requestUrl) - { - if (!$this->request->getConfig('proxy_host') || - !($user = $this->request->getConfig('proxy_user')) || - (0 == strcasecmp('https', $this->request->getUrl()->getScheme()) && - HTTP_Request2::METHOD_CONNECT != $this->request->getMethod()) - ) { - return; - } - - $password = $this->request->getConfig('proxy_password'); - switch ($this->request->getConfig('proxy_auth_scheme')) { - case HTTP_Request2::AUTH_BASIC: - $headers['proxy-authorization'] = - 'Basic ' . base64_encode($user . ':' . $password); - break; - - case HTTP_Request2::AUTH_DIGEST: - unset($this->proxyChallenge); - $proxyUrl = 'proxy://' . $this->request->getConfig('proxy_host') . - ':' . $this->request->getConfig('proxy_port'); - if (!empty(self::$challenges[$proxyUrl])) { - $headers['proxy-authorization'] = $this->createDigestResponse( - $user, $password, - $requestUrl, self::$challenges[$proxyUrl] - ); - $this->proxyChallenge =& self::$challenges[$proxyUrl]; - } - break; - - default: - throw new HTTP_Request2_Exception( - "Unknown HTTP authentication scheme '" . - $this->request->getConfig('proxy_auth_scheme') . "'" - ); - } - } - - - /** - * Creates the string with the Request-Line and request headers - * - * @return string - * @throws HTTP_Request2_Exception - */ - protected function prepareHeaders() - { - $headers = $this->request->getHeaders(); - $url = $this->request->getUrl(); - $connect = HTTP_Request2::METHOD_CONNECT == $this->request->getMethod(); - $host = $url->getHost(); - - $defaultPort = 0 == strcasecmp($url->getScheme(), 'https')? 443: 80; - if (($port = $url->getPort()) && $port != $defaultPort || $connect) { - $host .= ':' . (empty($port)? $defaultPort: $port); - } - // Do not overwrite explicitly set 'Host' header, see bug #16146 - if (!isset($headers['host'])) { - $headers['host'] = $host; - } - - if ($connect) { - $requestUrl = $host; - - } else { - if (!$this->request->getConfig('proxy_host') || - 0 == strcasecmp($url->getScheme(), 'https') - ) { - $requestUrl = ''; - } else { - $requestUrl = $url->getScheme() . '://' . $host; - } - $path = $url->getPath(); - $query = $url->getQuery(); - $requestUrl .= (empty($path)? '/': $path) . (empty($query)? '': '?' . $query); - } - - if ('1.1' == $this->request->getConfig('protocol_version') && - extension_loaded('zlib') && !isset($headers['accept-encoding']) - ) { - $headers['accept-encoding'] = 'gzip, deflate'; - } - - $this->addAuthorizationHeader($headers, $host, $requestUrl); - $this->addProxyAuthorizationHeader($headers, $requestUrl); - $this->calculateRequestLength($headers); - - $headersStr = $this->request->getMethod() . ' ' . $requestUrl . ' HTTP/' . - $this->request->getConfig('protocol_version') . "\r\n"; - foreach ($headers as $name => $value) { - $canonicalName = implode('-', array_map('ucfirst', explode('-', $name))); - $headersStr .= $canonicalName . ': ' . $value . "\r\n"; - } - return $headersStr . "\r\n"; - } - - /** - * Sends the request body - * - * @throws HTTP_Request2_Exception - */ - protected function writeBody() - { - if (in_array($this->request->getMethod(), self::$bodyDisallowed) || - 0 == $this->contentLength - ) { - return; - } - - $position = 0; - $bufferSize = $this->request->getConfig('buffer_size'); - while ($position < $this->contentLength) { - if (is_string($this->requestBody)) { - $str = substr($this->requestBody, $position, $bufferSize); - } elseif (is_resource($this->requestBody)) { - $str = fread($this->requestBody, $bufferSize); - } else { - $str = $this->requestBody->read($bufferSize); - } - if (false === @fwrite($this->socket, $str, strlen($str))) { - throw new HTTP_Request2_Exception('Error writing request'); - } - // Provide the length of written string to the observer, request #7630 - $this->request->setLastEvent('sentBodyPart', strlen($str)); - $position += strlen($str); - } - } - - /** - * Reads the remote server's response - * - * @return HTTP_Request2_Response - * @throws HTTP_Request2_Exception - */ - protected function readResponse() - { - $bufferSize = $this->request->getConfig('buffer_size'); - - do { - $response = new HTTP_Request2_Response($this->readLine($bufferSize), true); - do { - $headerLine = $this->readLine($bufferSize); - $response->parseHeaderLine($headerLine); - } while ('' != $headerLine); - } while (in_array($response->getStatus(), array(100, 101))); - - $this->request->setLastEvent('receivedHeaders', $response); - - // No body possible in such responses - if (HTTP_Request2::METHOD_HEAD == $this->request->getMethod() || - (HTTP_Request2::METHOD_CONNECT == $this->request->getMethod() && - 200 <= $response->getStatus() && 300 > $response->getStatus()) || - in_array($response->getStatus(), array(204, 304)) - ) { - return $response; - } - - $chunked = 'chunked' == $response->getHeader('transfer-encoding'); - $length = $response->getHeader('content-length'); - $hasBody = false; - if ($chunked || null === $length || 0 < intval($length)) { - // RFC 2616, section 4.4: - // 3. ... If a message is received with both a - // Transfer-Encoding header field and a Content-Length header field, - // the latter MUST be ignored. - $toRead = ($chunked || null === $length)? null: $length; - $this->chunkLength = 0; - - while (!feof($this->socket) && (is_null($toRead) || 0 < $toRead)) { - if ($chunked) { - $data = $this->readChunked($bufferSize); - } elseif (is_null($toRead)) { - $data = $this->fread($bufferSize); - } else { - $data = $this->fread(min($toRead, $bufferSize)); - $toRead -= strlen($data); - } - if ('' == $data && (!$this->chunkLength || feof($this->socket))) { - break; - } - - $hasBody = true; - if ($this->request->getConfig('store_body')) { - $response->appendBody($data); - } - if (!in_array($response->getHeader('content-encoding'), array('identity', null))) { - $this->request->setLastEvent('receivedEncodedBodyPart', $data); - } else { - $this->request->setLastEvent('receivedBodyPart', $data); - } - } - } - - if ($hasBody) { - $this->request->setLastEvent('receivedBody', $response); - } - return $response; - } - - /** - * Reads until either the end of the socket or a newline, whichever comes first - * - * Strips the trailing newline from the returned data, handles global - * request timeout. Method idea borrowed from Net_Socket PEAR package. - * - * @param int buffer size to use for reading - * @return Available data up to the newline (not including newline) - * @throws HTTP_Request2_Exception In case of timeout - */ - protected function readLine($bufferSize) - { - $line = ''; - while (!feof($this->socket)) { - if ($this->timeout) { - stream_set_timeout($this->socket, max($this->timeout - time(), 1)); - } - $line .= @fgets($this->socket, $bufferSize); - $info = stream_get_meta_data($this->socket); - if ($info['timed_out'] || $this->timeout && time() > $this->timeout) { - throw new HTTP_Request2_Exception( - 'Request timed out after ' . - $this->request->getConfig('timeout') . ' second(s)' - ); - } - if (substr($line, -1) == "\n") { - return rtrim($line, "\r\n"); - } - } - return $line; - } - - /** - * Wrapper around fread(), handles global request timeout - * - * @param int Reads up to this number of bytes - * @return Data read from socket - * @throws HTTP_Request2_Exception In case of timeout - */ - protected function fread($length) - { - if ($this->timeout) { - stream_set_timeout($this->socket, max($this->timeout - time(), 1)); - } - $data = fread($this->socket, $length); - $info = stream_get_meta_data($this->socket); - if ($info['timed_out'] || $this->timeout && time() > $this->timeout) { - throw new HTTP_Request2_Exception( - 'Request timed out after ' . - $this->request->getConfig('timeout') . ' second(s)' - ); - } - return $data; - } - - /** - * Reads a part of response body encoded with chunked Transfer-Encoding - * - * @param int buffer size to use for reading - * @return string - * @throws HTTP_Request2_Exception - */ - protected function readChunked($bufferSize) - { - // at start of the next chunk? - if (0 == $this->chunkLength) { - $line = $this->readLine($bufferSize); - if (!preg_match('/^([0-9a-f]+)/i', $line, $matches)) { - throw new HTTP_Request2_Exception( - "Cannot decode chunked response, invalid chunk length '{$line}'" - ); - } else { - $this->chunkLength = hexdec($matches[1]); - // Chunk with zero length indicates the end - if (0 == $this->chunkLength) { - $this->readLine($bufferSize); - return ''; - } - } - } - $data = $this->fread(min($this->chunkLength, $bufferSize)); - $this->chunkLength -= strlen($data); - if (0 == $this->chunkLength) { - $this->readLine($bufferSize); // Trailing CRLF - } - return $data; - } -} - + + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version CVS: $Id: Socket.php 279760 2009-05-03 10:46:42Z avb $ + * @link http://pear.php.net/package/HTTP_Request2 + */ + +/** + * Base class for HTTP_Request2 adapters + */ +require_once 'HTTP/Request2/Adapter.php'; + +/** + * Socket-based adapter for HTTP_Request2 + * + * This adapter uses only PHP sockets and will work on almost any PHP + * environment. Code is based on original HTTP_Request PEAR package. + * + * @category HTTP + * @package HTTP_Request2 + * @author Alexey Borzov + * @version Release: 0.4.1 + */ +class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter +{ + /** + * Regular expression for 'token' rule from RFC 2616 + */ + const REGEXP_TOKEN = '[^\x00-\x1f\x7f-\xff()<>@,;:\\\\"/\[\]?={}\s]+'; + + /** + * Regular expression for 'quoted-string' rule from RFC 2616 + */ + const REGEXP_QUOTED_STRING = '"(?:\\\\.|[^\\\\"])*"'; + + /** + * Connected sockets, needed for Keep-Alive support + * @var array + * @see connect() + */ + protected static $sockets = array(); + + /** + * Data for digest authentication scheme + * + * The keys for the array are URL prefixes. + * + * The values are associative arrays with data (realm, nonce, nonce-count, + * opaque...) needed for digest authentication. Stored here to prevent making + * duplicate requests to digest-protected resources after we have already + * received the challenge. + * + * @var array + */ + protected static $challenges = array(); + + /** + * Connected socket + * @var resource + * @see connect() + */ + protected $socket; + + /** + * Challenge used for server digest authentication + * @var array + */ + protected $serverChallenge; + + /** + * Challenge used for proxy digest authentication + * @var array + */ + protected $proxyChallenge; + + /** + * Global timeout, exception will be raised if request continues past this time + * @var integer + */ + protected $timeout = null; + + /** + * Remaining length of the current chunk, when reading chunked response + * @var integer + * @see readChunked() + */ + protected $chunkLength = 0; + + /** + * Sends request to the remote server and returns its response + * + * @param HTTP_Request2 + * @return HTTP_Request2_Response + * @throws HTTP_Request2_Exception + */ + public function sendRequest(HTTP_Request2 $request) + { + $this->request = $request; + $keepAlive = $this->connect(); + $headers = $this->prepareHeaders(); + + // Use global request timeout if given, see feature requests #5735, #8964 + if ($timeout = $request->getConfig('timeout')) { + $this->timeout = time() + $timeout; + } else { + $this->timeout = null; + } + + try { + if (false === @fwrite($this->socket, $headers, strlen($headers))) { + throw new HTTP_Request2_Exception('Error writing request'); + } + // provide request headers to the observer, see request #7633 + $this->request->setLastEvent('sentHeaders', $headers); + $this->writeBody(); + + if ($this->timeout && time() > $this->timeout) { + throw new HTTP_Request2_Exception( + 'Request timed out after ' . + $request->getConfig('timeout') . ' second(s)' + ); + } + + $response = $this->readResponse(); + + if (!$this->canKeepAlive($keepAlive, $response)) { + $this->disconnect(); + } + + if ($this->shouldUseProxyDigestAuth($response)) { + return $this->sendRequest($request); + } + if ($this->shouldUseServerDigestAuth($response)) { + return $this->sendRequest($request); + } + if ($authInfo = $response->getHeader('authentication-info')) { + $this->updateChallenge($this->serverChallenge, $authInfo); + } + if ($proxyInfo = $response->getHeader('proxy-authentication-info')) { + $this->updateChallenge($this->proxyChallenge, $proxyInfo); + } + + } catch (Exception $e) { + $this->disconnect(); + throw $e; + } + + return $response; + } + + /** + * Connects to the remote server + * + * @return bool whether the connection can be persistent + * @throws HTTP_Request2_Exception + */ + protected function connect() + { + $secure = 0 == strcasecmp($this->request->getUrl()->getScheme(), 'https'); + $tunnel = HTTP_Request2::METHOD_CONNECT == $this->request->getMethod(); + $headers = $this->request->getHeaders(); + $reqHost = $this->request->getUrl()->getHost(); + if (!($reqPort = $this->request->getUrl()->getPort())) { + $reqPort = $secure? 443: 80; + } + + if ($host = $this->request->getConfig('proxy_host')) { + if (!($port = $this->request->getConfig('proxy_port'))) { + throw new HTTP_Request2_Exception('Proxy port not provided'); + } + $proxy = true; + } else { + $host = $reqHost; + $port = $reqPort; + $proxy = false; + } + + if ($tunnel && !$proxy) { + throw new HTTP_Request2_Exception( + "Trying to perform CONNECT request without proxy" + ); + } + if ($secure && !in_array('ssl', stream_get_transports())) { + throw new HTTP_Request2_Exception( + 'Need OpenSSL support for https:// requests' + ); + } + + // RFC 2068, section 19.7.1: A client MUST NOT send the Keep-Alive + // connection token to a proxy server... + if ($proxy && !$secure && + !empty($headers['connection']) && 'Keep-Alive' == $headers['connection'] + ) { + $this->request->setHeader('connection'); + } + + $keepAlive = ('1.1' == $this->request->getConfig('protocol_version') && + empty($headers['connection'])) || + (!empty($headers['connection']) && + 'Keep-Alive' == $headers['connection']); + $host = ((!$secure || $proxy)? 'tcp://': 'ssl://') . $host; + + $options = array(); + if ($secure || $tunnel) { + foreach ($this->request->getConfig() as $name => $value) { + if ('ssl_' == substr($name, 0, 4) && null !== $value) { + if ('ssl_verify_host' == $name) { + if ($value) { + $options['CN_match'] = $reqHost; + } + } else { + $options[substr($name, 4)] = $value; + } + } + } + ksort($options); + } + + // Changing SSL context options after connection is established does *not* + // work, we need a new connection if options change + $remote = $host . ':' . $port; + $socketKey = $remote . (($secure && $proxy)? "->{$reqHost}:{$reqPort}": '') . + (empty($options)? '': ':' . serialize($options)); + unset($this->socket); + + // We use persistent connections and have a connected socket? + // Ensure that the socket is still connected, see bug #16149 + if ($keepAlive && !empty(self::$sockets[$socketKey]) && + !feof(self::$sockets[$socketKey]) + ) { + $this->socket =& self::$sockets[$socketKey]; + + } elseif ($secure && $proxy && !$tunnel) { + $this->establishTunnel(); + $this->request->setLastEvent( + 'connect', "ssl://{$reqHost}:{$reqPort} via {$host}:{$port}" + ); + self::$sockets[$socketKey] =& $this->socket; + + } else { + // Set SSL context options if doing HTTPS request or creating a tunnel + $context = stream_context_create(); + foreach ($options as $name => $value) { + if (!stream_context_set_option($context, 'ssl', $name, $value)) { + throw new HTTP_Request2_Exception( + "Error setting SSL context option '{$name}'" + ); + } + } + $this->socket = @stream_socket_client( + $remote, $errno, $errstr, + $this->request->getConfig('connect_timeout'), + STREAM_CLIENT_CONNECT, $context + ); + if (!$this->socket) { + throw new HTTP_Request2_Exception( + "Unable to connect to {$remote}. Error #{$errno}: {$errstr}" + ); + } + $this->request->setLastEvent('connect', $remote); + self::$sockets[$socketKey] =& $this->socket; + } + return $keepAlive; + } + + /** + * Establishes a tunnel to a secure remote server via HTTP CONNECT request + * + * This method will fail if 'ssl_verify_peer' is enabled. Probably because PHP + * sees that we are connected to a proxy server (duh!) rather than the server + * that presents its certificate. + * + * @link http://tools.ietf.org/html/rfc2817#section-5.2 + * @throws HTTP_Request2_Exception + */ + protected function establishTunnel() + { + $donor = new self; + $connect = new HTTP_Request2( + $this->request->getUrl(), HTTP_Request2::METHOD_CONNECT, + array_merge($this->request->getConfig(), + array('adapter' => $donor)) + ); + $response = $connect->send(); + // Need any successful (2XX) response + if (200 > $response->getStatus() || 300 <= $response->getStatus()) { + throw new HTTP_Request2_Exception( + 'Failed to connect via HTTPS proxy. Proxy response: ' . + $response->getStatus() . ' ' . $response->getReasonPhrase() + ); + } + $this->socket = $donor->socket; + + $modes = array( + STREAM_CRYPTO_METHOD_TLS_CLIENT, + STREAM_CRYPTO_METHOD_SSLv3_CLIENT, + STREAM_CRYPTO_METHOD_SSLv23_CLIENT, + STREAM_CRYPTO_METHOD_SSLv2_CLIENT + ); + + foreach ($modes as $mode) { + if (stream_socket_enable_crypto($this->socket, true, $mode)) { + return; + } + } + throw new HTTP_Request2_Exception( + 'Failed to enable secure connection when connecting through proxy' + ); + } + + /** + * Checks whether current connection may be reused or should be closed + * + * @param boolean whether connection could be persistent + * in the first place + * @param HTTP_Request2_Response response object to check + * @return boolean + */ + protected function canKeepAlive($requestKeepAlive, HTTP_Request2_Response $response) + { + // Do not close socket on successful CONNECT request + if (HTTP_Request2::METHOD_CONNECT == $this->request->getMethod() && + 200 <= $response->getStatus() && 300 > $response->getStatus() + ) { + return true; + } + + $lengthKnown = 'chunked' == strtolower($response->getHeader('transfer-encoding')) || + null !== $response->getHeader('content-length'); + $persistent = 'keep-alive' == strtolower($response->getHeader('connection')) || + (null === $response->getHeader('connection') && + '1.1' == $response->getVersion()); + return $requestKeepAlive && $lengthKnown && $persistent; + } + + /** + * Disconnects from the remote server + */ + protected function disconnect() + { + if (is_resource($this->socket)) { + fclose($this->socket); + $this->socket = null; + $this->request->setLastEvent('disconnect'); + } + } + + /** + * Checks whether another request should be performed with server digest auth + * + * Several conditions should be satisfied for it to return true: + * - response status should be 401 + * - auth credentials should be set in the request object + * - response should contain WWW-Authenticate header with digest challenge + * - there is either no challenge stored for this URL or new challenge + * contains stale=true parameter (in other case we probably just failed + * due to invalid username / password) + * + * The method stores challenge values in $challenges static property + * + * @param HTTP_Request2_Response response to check + * @return boolean whether another request should be performed + * @throws HTTP_Request2_Exception in case of unsupported challenge parameters + */ + protected function shouldUseServerDigestAuth(HTTP_Request2_Response $response) + { + // no sense repeating a request if we don't have credentials + if (401 != $response->getStatus() || !$this->request->getAuth()) { + return false; + } + if (!$challenge = $this->parseDigestChallenge($response->getHeader('www-authenticate'))) { + return false; + } + + $url = $this->request->getUrl(); + $scheme = $url->getScheme(); + $host = $scheme . '://' . $url->getHost(); + if ($port = $url->getPort()) { + if ((0 == strcasecmp($scheme, 'http') && 80 != $port) || + (0 == strcasecmp($scheme, 'https') && 443 != $port) + ) { + $host .= ':' . $port; + } + } + + if (!empty($challenge['domain'])) { + $prefixes = array(); + foreach (preg_split('/\\s+/', $challenge['domain']) as $prefix) { + // don't bother with different servers + if ('/' == substr($prefix, 0, 1)) { + $prefixes[] = $host . $prefix; + } + } + } + if (empty($prefixes)) { + $prefixes = array($host . '/'); + } + + $ret = true; + foreach ($prefixes as $prefix) { + if (!empty(self::$challenges[$prefix]) && + (empty($challenge['stale']) || strcasecmp('true', $challenge['stale'])) + ) { + // probably credentials are invalid + $ret = false; + } + self::$challenges[$prefix] =& $challenge; + } + return $ret; + } + + /** + * Checks whether another request should be performed with proxy digest auth + * + * Several conditions should be satisfied for it to return true: + * - response status should be 407 + * - proxy auth credentials should be set in the request object + * - response should contain Proxy-Authenticate header with digest challenge + * - there is either no challenge stored for this proxy or new challenge + * contains stale=true parameter (in other case we probably just failed + * due to invalid username / password) + * + * The method stores challenge values in $challenges static property + * + * @param HTTP_Request2_Response response to check + * @return boolean whether another request should be performed + * @throws HTTP_Request2_Exception in case of unsupported challenge parameters + */ + protected function shouldUseProxyDigestAuth(HTTP_Request2_Response $response) + { + if (407 != $response->getStatus() || !$this->request->getConfig('proxy_user')) { + return false; + } + if (!($challenge = $this->parseDigestChallenge($response->getHeader('proxy-authenticate')))) { + return false; + } + + $key = 'proxy://' . $this->request->getConfig('proxy_host') . + ':' . $this->request->getConfig('proxy_port'); + + if (!empty(self::$challenges[$key]) && + (empty($challenge['stale']) || strcasecmp('true', $challenge['stale'])) + ) { + $ret = false; + } else { + $ret = true; + } + self::$challenges[$key] = $challenge; + return $ret; + } + + /** + * Extracts digest method challenge from (WWW|Proxy)-Authenticate header value + * + * There is a problem with implementation of RFC 2617: several of the parameters + * here are defined as quoted-string and thus may contain backslash escaped + * double quotes (RFC 2616, section 2.2). However, RFC 2617 defines unq(X) as + * just value of quoted-string X without surrounding quotes, it doesn't speak + * about removing backslash escaping. + * + * Now realm parameter is user-defined and human-readable, strange things + * happen when it contains quotes: + * - Apache allows quotes in realm, but apparently uses realm value without + * backslashes for digest computation + * - Squid allows (manually escaped) quotes there, but it is impossible to + * authorize with either escaped or unescaped quotes used in digest, + * probably it can't parse the response (?) + * - Both IE and Firefox display realm value with backslashes in + * the password popup and apparently use the same value for digest + * + * HTTP_Request2 follows IE and Firefox (and hopefully RFC 2617) in + * quoted-string handling, unfortunately that means failure to authorize + * sometimes + * + * @param string value of WWW-Authenticate or Proxy-Authenticate header + * @return mixed associative array with challenge parameters, false if + * no challenge is present in header value + * @throws HTTP_Request2_Exception in case of unsupported challenge parameters + */ + protected function parseDigestChallenge($headerValue) + { + $authParam = '(' . self::REGEXP_TOKEN . ')\\s*=\\s*(' . + self::REGEXP_TOKEN . '|' . self::REGEXP_QUOTED_STRING . ')'; + $challenge = "!(?<=^|\\s|,)Digest ({$authParam}\\s*(,\\s*|$))+!"; + if (!preg_match($challenge, $headerValue, $matches)) { + return false; + } + + preg_match_all('!' . $authParam . '!', $matches[0], $params); + $paramsAry = array(); + $knownParams = array('realm', 'domain', 'nonce', 'opaque', 'stale', + 'algorithm', 'qop'); + for ($i = 0; $i < count($params[0]); $i++) { + // section 3.2.1: Any unrecognized directive MUST be ignored. + if (in_array($params[1][$i], $knownParams)) { + if ('"' == substr($params[2][$i], 0, 1)) { + $paramsAry[$params[1][$i]] = substr($params[2][$i], 1, -1); + } else { + $paramsAry[$params[1][$i]] = $params[2][$i]; + } + } + } + // we only support qop=auth + if (!empty($paramsAry['qop']) && + !in_array('auth', array_map('trim', explode(',', $paramsAry['qop']))) + ) { + throw new HTTP_Request2_Exception( + "Only 'auth' qop is currently supported in digest authentication, " . + "server requested '{$paramsAry['qop']}'" + ); + } + // we only support algorithm=MD5 + if (!empty($paramsAry['algorithm']) && 'MD5' != $paramsAry['algorithm']) { + throw new HTTP_Request2_Exception( + "Only 'MD5' algorithm is currently supported in digest authentication, " . + "server requested '{$paramsAry['algorithm']}'" + ); + } + + return $paramsAry; + } + + /** + * Parses [Proxy-]Authentication-Info header value and updates challenge + * + * @param array challenge to update + * @param string value of [Proxy-]Authentication-Info header + * @todo validate server rspauth response + */ + protected function updateChallenge(&$challenge, $headerValue) + { + $authParam = '!(' . self::REGEXP_TOKEN . ')\\s*=\\s*(' . + self::REGEXP_TOKEN . '|' . self::REGEXP_QUOTED_STRING . ')!'; + $paramsAry = array(); + + preg_match_all($authParam, $headerValue, $params); + for ($i = 0; $i < count($params[0]); $i++) { + if ('"' == substr($params[2][$i], 0, 1)) { + $paramsAry[$params[1][$i]] = substr($params[2][$i], 1, -1); + } else { + $paramsAry[$params[1][$i]] = $params[2][$i]; + } + } + // for now, just update the nonce value + if (!empty($paramsAry['nextnonce'])) { + $challenge['nonce'] = $paramsAry['nextnonce']; + $challenge['nc'] = 1; + } + } + + /** + * Creates a value for [Proxy-]Authorization header when using digest authentication + * + * @param string user name + * @param string password + * @param string request URL + * @param array digest challenge parameters + * @return string value of [Proxy-]Authorization request header + * @link http://tools.ietf.org/html/rfc2617#section-3.2.2 + */ + protected function createDigestResponse($user, $password, $url, &$challenge) + { + if (false !== ($q = strpos($url, '?')) && + $this->request->getConfig('digest_compat_ie') + ) { + $url = substr($url, 0, $q); + } + + $a1 = md5($user . ':' . $challenge['realm'] . ':' . $password); + $a2 = md5($this->request->getMethod() . ':' . $url); + + if (empty($challenge['qop'])) { + $digest = md5($a1 . ':' . $challenge['nonce'] . ':' . $a2); + } else { + $challenge['cnonce'] = 'Req2.' . rand(); + if (empty($challenge['nc'])) { + $challenge['nc'] = 1; + } + $nc = sprintf('%08x', $challenge['nc']++); + $digest = md5($a1 . ':' . $challenge['nonce'] . ':' . $nc . ':' . + $challenge['cnonce'] . ':auth:' . $a2); + } + return 'Digest username="' . str_replace(array('\\', '"'), array('\\\\', '\\"'), $user) . '", ' . + 'realm="' . $challenge['realm'] . '", ' . + 'nonce="' . $challenge['nonce'] . '", ' . + 'uri="' . $url . '", ' . + 'response="' . $digest . '"' . + (!empty($challenge['opaque'])? + ', opaque="' . $challenge['opaque'] . '"': + '') . + (!empty($challenge['qop'])? + ', qop="auth", nc=' . $nc . ', cnonce="' . $challenge['cnonce'] . '"': + ''); + } + + /** + * Adds 'Authorization' header (if needed) to request headers array + * + * @param array request headers + * @param string request host (needed for digest authentication) + * @param string request URL (needed for digest authentication) + * @throws HTTP_Request2_Exception + */ + protected function addAuthorizationHeader(&$headers, $requestHost, $requestUrl) + { + if (!($auth = $this->request->getAuth())) { + return; + } + switch ($auth['scheme']) { + case HTTP_Request2::AUTH_BASIC: + $headers['authorization'] = + 'Basic ' . base64_encode($auth['user'] . ':' . $auth['password']); + break; + + case HTTP_Request2::AUTH_DIGEST: + unset($this->serverChallenge); + $fullUrl = ('/' == $requestUrl[0])? + $this->request->getUrl()->getScheme() . '://' . + $requestHost . $requestUrl: + $requestUrl; + foreach (array_keys(self::$challenges) as $key) { + if ($key == substr($fullUrl, 0, strlen($key))) { + $headers['authorization'] = $this->createDigestResponse( + $auth['user'], $auth['password'], + $requestUrl, self::$challenges[$key] + ); + $this->serverChallenge =& self::$challenges[$key]; + break; + } + } + break; + + default: + throw new HTTP_Request2_Exception( + "Unknown HTTP authentication scheme '{$auth['scheme']}'" + ); + } + } + + /** + * Adds 'Proxy-Authorization' header (if needed) to request headers array + * + * @param array request headers + * @param string request URL (needed for digest authentication) + * @throws HTTP_Request2_Exception + */ + protected function addProxyAuthorizationHeader(&$headers, $requestUrl) + { + if (!$this->request->getConfig('proxy_host') || + !($user = $this->request->getConfig('proxy_user')) || + (0 == strcasecmp('https', $this->request->getUrl()->getScheme()) && + HTTP_Request2::METHOD_CONNECT != $this->request->getMethod()) + ) { + return; + } + + $password = $this->request->getConfig('proxy_password'); + switch ($this->request->getConfig('proxy_auth_scheme')) { + case HTTP_Request2::AUTH_BASIC: + $headers['proxy-authorization'] = + 'Basic ' . base64_encode($user . ':' . $password); + break; + + case HTTP_Request2::AUTH_DIGEST: + unset($this->proxyChallenge); + $proxyUrl = 'proxy://' . $this->request->getConfig('proxy_host') . + ':' . $this->request->getConfig('proxy_port'); + if (!empty(self::$challenges[$proxyUrl])) { + $headers['proxy-authorization'] = $this->createDigestResponse( + $user, $password, + $requestUrl, self::$challenges[$proxyUrl] + ); + $this->proxyChallenge =& self::$challenges[$proxyUrl]; + } + break; + + default: + throw new HTTP_Request2_Exception( + "Unknown HTTP authentication scheme '" . + $this->request->getConfig('proxy_auth_scheme') . "'" + ); + } + } + + + /** + * Creates the string with the Request-Line and request headers + * + * @return string + * @throws HTTP_Request2_Exception + */ + protected function prepareHeaders() + { + $headers = $this->request->getHeaders(); + $url = $this->request->getUrl(); + $connect = HTTP_Request2::METHOD_CONNECT == $this->request->getMethod(); + $host = $url->getHost(); + + $defaultPort = 0 == strcasecmp($url->getScheme(), 'https')? 443: 80; + if (($port = $url->getPort()) && $port != $defaultPort || $connect) { + $host .= ':' . (empty($port)? $defaultPort: $port); + } + // Do not overwrite explicitly set 'Host' header, see bug #16146 + if (!isset($headers['host'])) { + $headers['host'] = $host; + } + + if ($connect) { + $requestUrl = $host; + + } else { + if (!$this->request->getConfig('proxy_host') || + 0 == strcasecmp($url->getScheme(), 'https') + ) { + $requestUrl = ''; + } else { + $requestUrl = $url->getScheme() . '://' . $host; + } + $path = $url->getPath(); + $query = $url->getQuery(); + $requestUrl .= (empty($path)? '/': $path) . (empty($query)? '': '?' . $query); + } + + if ('1.1' == $this->request->getConfig('protocol_version') && + extension_loaded('zlib') && !isset($headers['accept-encoding']) + ) { + $headers['accept-encoding'] = 'gzip, deflate'; + } + + $this->addAuthorizationHeader($headers, $host, $requestUrl); + $this->addProxyAuthorizationHeader($headers, $requestUrl); + $this->calculateRequestLength($headers); + + $headersStr = $this->request->getMethod() . ' ' . $requestUrl . ' HTTP/' . + $this->request->getConfig('protocol_version') . "\r\n"; + foreach ($headers as $name => $value) { + $canonicalName = implode('-', array_map('ucfirst', explode('-', $name))); + $headersStr .= $canonicalName . ': ' . $value . "\r\n"; + } + return $headersStr . "\r\n"; + } + + /** + * Sends the request body + * + * @throws HTTP_Request2_Exception + */ + protected function writeBody() + { + if (in_array($this->request->getMethod(), self::$bodyDisallowed) || + 0 == $this->contentLength + ) { + return; + } + + $position = 0; + $bufferSize = $this->request->getConfig('buffer_size'); + while ($position < $this->contentLength) { + if (is_string($this->requestBody)) { + $str = substr($this->requestBody, $position, $bufferSize); + } elseif (is_resource($this->requestBody)) { + $str = fread($this->requestBody, $bufferSize); + } else { + $str = $this->requestBody->read($bufferSize); + } + if (false === @fwrite($this->socket, $str, strlen($str))) { + throw new HTTP_Request2_Exception('Error writing request'); + } + // Provide the length of written string to the observer, request #7630 + $this->request->setLastEvent('sentBodyPart', strlen($str)); + $position += strlen($str); + } + } + + /** + * Reads the remote server's response + * + * @return HTTP_Request2_Response + * @throws HTTP_Request2_Exception + */ + protected function readResponse() + { + $bufferSize = $this->request->getConfig('buffer_size'); + + do { + $response = new HTTP_Request2_Response($this->readLine($bufferSize), true); + do { + $headerLine = $this->readLine($bufferSize); + $response->parseHeaderLine($headerLine); + } while ('' != $headerLine); + } while (in_array($response->getStatus(), array(100, 101))); + + $this->request->setLastEvent('receivedHeaders', $response); + + // No body possible in such responses + if (HTTP_Request2::METHOD_HEAD == $this->request->getMethod() || + (HTTP_Request2::METHOD_CONNECT == $this->request->getMethod() && + 200 <= $response->getStatus() && 300 > $response->getStatus()) || + in_array($response->getStatus(), array(204, 304)) + ) { + return $response; + } + + $chunked = 'chunked' == $response->getHeader('transfer-encoding'); + $length = $response->getHeader('content-length'); + $hasBody = false; + if ($chunked || null === $length || 0 < intval($length)) { + // RFC 2616, section 4.4: + // 3. ... If a message is received with both a + // Transfer-Encoding header field and a Content-Length header field, + // the latter MUST be ignored. + $toRead = ($chunked || null === $length)? null: $length; + $this->chunkLength = 0; + + while (!feof($this->socket) && (is_null($toRead) || 0 < $toRead)) { + if ($chunked) { + $data = $this->readChunked($bufferSize); + } elseif (is_null($toRead)) { + $data = $this->fread($bufferSize); + } else { + $data = $this->fread(min($toRead, $bufferSize)); + $toRead -= strlen($data); + } + if ('' == $data && (!$this->chunkLength || feof($this->socket))) { + break; + } + + $hasBody = true; + if ($this->request->getConfig('store_body')) { + $response->appendBody($data); + } + if (!in_array($response->getHeader('content-encoding'), array('identity', null))) { + $this->request->setLastEvent('receivedEncodedBodyPart', $data); + } else { + $this->request->setLastEvent('receivedBodyPart', $data); + } + } + } + + if ($hasBody) { + $this->request->setLastEvent('receivedBody', $response); + } + return $response; + } + + /** + * Reads until either the end of the socket or a newline, whichever comes first + * + * Strips the trailing newline from the returned data, handles global + * request timeout. Method idea borrowed from Net_Socket PEAR package. + * + * @param int buffer size to use for reading + * @return Available data up to the newline (not including newline) + * @throws HTTP_Request2_Exception In case of timeout + */ + protected function readLine($bufferSize) + { + $line = ''; + while (!feof($this->socket)) { + if ($this->timeout) { + stream_set_timeout($this->socket, max($this->timeout - time(), 1)); + } + $line .= @fgets($this->socket, $bufferSize); + $info = stream_get_meta_data($this->socket); + if ($info['timed_out'] || $this->timeout && time() > $this->timeout) { + throw new HTTP_Request2_Exception( + 'Request timed out after ' . + $this->request->getConfig('timeout') . ' second(s)' + ); + } + if (substr($line, -1) == "\n") { + return rtrim($line, "\r\n"); + } + } + return $line; + } + + /** + * Wrapper around fread(), handles global request timeout + * + * @param int Reads up to this number of bytes + * @return Data read from socket + * @throws HTTP_Request2_Exception In case of timeout + */ + protected function fread($length) + { + if ($this->timeout) { + stream_set_timeout($this->socket, max($this->timeout - time(), 1)); + } + $data = fread($this->socket, $length); + $info = stream_get_meta_data($this->socket); + if ($info['timed_out'] || $this->timeout && time() > $this->timeout) { + throw new HTTP_Request2_Exception( + 'Request timed out after ' . + $this->request->getConfig('timeout') . ' second(s)' + ); + } + return $data; + } + + /** + * Reads a part of response body encoded with chunked Transfer-Encoding + * + * @param int buffer size to use for reading + * @return string + * @throws HTTP_Request2_Exception + */ + protected function readChunked($bufferSize) + { + // at start of the next chunk? + if (0 == $this->chunkLength) { + $line = $this->readLine($bufferSize); + if (!preg_match('/^([0-9a-f]+)/i', $line, $matches)) { + throw new HTTP_Request2_Exception( + "Cannot decode chunked response, invalid chunk length '{$line}'" + ); + } else { + $this->chunkLength = hexdec($matches[1]); + // Chunk with zero length indicates the end + if (0 == $this->chunkLength) { + $this->readLine($bufferSize); + return ''; + } + } + } + $data = $this->fread(min($this->chunkLength, $bufferSize)); + $this->chunkLength -= strlen($data); + if (0 == $this->chunkLength) { + $this->readLine($bufferSize); // Trailing CRLF + } + return $data; + } +} + ?> \ No newline at end of file diff --git a/extlib/MIME/Type.php b/extlib/MIME/Type.php index 8653362d3..c335f8d92 100644 --- a/extlib/MIME/Type.php +++ b/extlib/MIME/Type.php @@ -478,7 +478,7 @@ class MIME_Type // Don't return an empty string if (!$type || !strlen($type)) { - return PEAR::raiseError("Sorry. Could not determine file type."); + return PEAR::raiseError("Sorry, couldn't determine file type."); } // Strip parameters if present & requested @@ -510,7 +510,7 @@ class MIME_Type $fileCmd = PEAR::getStaticProperty('MIME_Type', 'fileCmd'); if (!$cmd->which($fileCmd)) { unset($cmd); - return PEAR::raiseError("Cannot find file command \"{$fileCmd}\""); + return PEAR::raiseError("Can't find file command \"{$fileCmd}\""); } $cmd->pushCommand($fileCmd, "-bi " . escapeshellarg($file)); diff --git a/extlib/MIME/Type/Extension.php b/extlib/MIME/Type/Extension.php index 2ffdee9a9..1987e2a10 100644 --- a/extlib/MIME/Type/Extension.php +++ b/extlib/MIME/Type/Extension.php @@ -265,7 +265,7 @@ class MIME_Type_Extension } if (!isset($this->extensionToType[$extension])) { - return PEAR::raiseError("Sorry. Could not determine file type."); + return PEAR::raiseError("Sorry, couldn't determine file type."); } return $this->extensionToType[$extension]; @@ -288,7 +288,7 @@ class MIME_Type_Extension $extension = array_search($type, $this->extensionToType); if ($extension === false) { - return PEAR::raiseError("Sorry. Could not determine extension."); + return PEAR::raiseError("Sorry, couldn't determine extension."); } return $extension; } diff --git a/extlib/Mail/mail.php b/extlib/Mail/mail.php index 112ff940c..b13d69565 100644 --- a/extlib/Mail/mail.php +++ b/extlib/Mail/mail.php @@ -51,7 +51,7 @@ class Mail_mail extends Mail { } /* Because the mail() function may pass headers as command - * line arguments, we cannot guarantee the use of the standard + * line arguments, we can't guarantee the use of the standard * "\r\n" separator. Instead, we use the system's native line * separator. */ if (defined('PHP_EOL')) { diff --git a/extlib/Mail/sendmail.php b/extlib/Mail/sendmail.php index aea52081a..cd248e61d 100644 --- a/extlib/Mail/sendmail.php +++ b/extlib/Mail/sendmail.php @@ -67,7 +67,7 @@ class Mail_sendmail extends Mail { /* * Because we need to pass message headers to the sendmail program on - * the commandline, we cannot guarantee the use of the standard "\r\n" + * the commandline, we can't guarantee the use of the standard "\r\n" * separator. Instead, we use the system's native line separator. */ if (defined('PHP_EOL')) { diff --git a/extlib/Net/LDAP2/Entry.php b/extlib/Net/LDAP2/Entry.php index 5531bfa13..66de96678 100644 --- a/extlib/Net/LDAP2/Entry.php +++ b/extlib/Net/LDAP2/Entry.php @@ -665,7 +665,7 @@ class Net_LDAP2_Entry extends PEAR * To force replace mode instead of add, you can set $force to true. * * @param array $attr Attributes to replace - * @param bool $force Force replacing mode in case we cannot read the attr value but are allowed to replace it + * @param bool $force Force replacing mode in case we can't read the attr value but are allowed to replace it * * @access public * @return true|Net_LDAP2_Error diff --git a/extlib/Net/LDAP2/Filter.php b/extlib/Net/LDAP2/Filter.php index bd13d1ee4..0723edab2 100644 --- a/extlib/Net/LDAP2/Filter.php +++ b/extlib/Net/LDAP2/Filter.php @@ -439,7 +439,7 @@ class Net_LDAP2_Filter extends PEAR * * This method is only for compatibility to the perl interface. * However, the original method was called "print" but due to PHP language restrictions, - * we cannot have a print() method. + * we can't have a print() method. * * @param resource $FH (optional) A filehandle resource * diff --git a/extlib/System/Command.php b/extlib/System/Command.php index d2001a975..f5c3ec6b9 100644 --- a/extlib/System/Command.php +++ b/extlib/System/Command.php @@ -376,7 +376,7 @@ class System_Command { return $this->_initError; } - // if the command is empty or if the last element was a control operator, we cannot continue + // if the command is empty or if the last element was a control operator, we can't continue if (is_null($this->previousElement) || $this->commandStatus == -1 || in_array($this->previousElement, $this->controlOperators)) { return PEAR::raiseError(null, SYSTEM_COMMAND_INVALID_COMMAND, null, E_USER_WARNING, $this->systemCommand, 'System_Command_Error', true); } diff --git a/extlib/markdown.php b/extlib/markdown.php index 1bb1b6ce4..8179b568b 100644 --- a/extlib/markdown.php +++ b/extlib/markdown.php @@ -1348,7 +1348,7 @@ class Markdown_Parser { // { // list(, $div_open, , $div_content, $div_close) = $matches; // -// # We cannot call Markdown(), because that resets the hash; +// # We can't call Markdown(), because that resets the hash; // # that initialization code should be pulled into its own sub, though. // $div_content = $this->hashHTMLBlocks($div_content); // diff --git a/install.php b/install.php index 78a4b8763..e7f7cf318 100644 --- a/install.php +++ b/install.php @@ -391,7 +391,7 @@ function showLibs() libraries instead, as they tend to provide security updates faster, and may offer improved performance.

    On Debian based distributions, such as Ubuntu, use a package manager (such as "aptitude", "apt-get", and "synaptic") to install the package listed.

    On RPM based distributions, such as Red Hat, Fedora, CentOS, Scientific Linux, Yellow Dog Linux and Oracle Enterprise Linux, use a package manager (such as "yum", "apt-rpm", and "up2date") to install the package listed.

    -

    On servers without a package manager (such as Windows), or if the library is not packaged for your distribution, you can use PHP PEAR to install the library. Simply run "pear install <name>".

    +

    On servers without a package manager (such as Windows), or if the library is not packaged for your distribution, you can use PHP's PEAR to install the library. Simply run "pear install <name>".

    Absent Libraries

      @@ -570,7 +570,7 @@ STR; $res = writeConf($sitename, $server, $path, $fancy, $db); if (!$res) { - updateStatus("Cannot write config file.", true); + updateStatus("Can't write config file.", true); showForm(); return; } @@ -616,7 +616,7 @@ function Pgsql_Db_installer($host, $database, $username, $password) $res = runDbScript(INSTALLDIR.'/db/statusnet_pg.sql', $conn, 'pgsql'); if ($res === false) { - updateStatus("Cannot run database script.", true); + updateStatus("Can't run database script.", true); showForm(); return false; } @@ -627,7 +627,7 @@ function Pgsql_Db_installer($host, $database, $username, $password) updateStatus(sprintf("Adding %s data to database...", $name)); $res = runDbScript(INSTALLDIR.'/db/'.$scr.'.sql', $conn, 'pgsql'); if ($res === false) { - updateStatus(sprintf("Cannot run %d script.", $name), true); + updateStatus(sprintf("Can't run %d script.", $name), true); showForm(); return false; } @@ -652,21 +652,21 @@ function Mysql_Db_installer($host, $database, $username, $password) $conn = mysql_connect($host, $username, $password); if (!$conn) { - updateStatus("Cannot connect to server '$host' as '$username'.", true); + updateStatus("Can't connect to server '$host' as '$username'.", true); showForm(); return false; } updateStatus("Changing to database..."); $res = mysql_select_db($database, $conn); if (!$res) { - updateStatus("Cannot change to database.", true); + updateStatus("Can't change to database.", true); showForm(); return false; } updateStatus("Running database script..."); $res = runDbScript(INSTALLDIR.'/db/statusnet.sql', $conn); if ($res === false) { - updateStatus("Cannot run database script.", true); + updateStatus("Can't run database script.", true); showForm(); return false; } @@ -677,7 +677,7 @@ function Mysql_Db_installer($host, $database, $username, $password) updateStatus(sprintf("Adding %s data to database...", $name)); $res = runDbScript(INSTALLDIR.'/db/'.$scr.'.sql', $conn); if ($res === false) { - updateStatus(sprintf("Cannot run %d script.", $name), true); + updateStatus(sprintf("Can't run %d script.", $name), true); showForm(); return false; } diff --git a/lib/attachmentlist.php b/lib/attachmentlist.php index 60095dace..51ceca857 100644 --- a/lib/attachmentlist.php +++ b/lib/attachmentlist.php @@ -71,7 +71,7 @@ class AttachmentList extends Widget /** * show the list of notices * - * "Uses up" the stream by looping through it. So, probably cannot + * "Uses up" the stream by looping through it. So, probably can't * be called twice on the same list. * * @return int count of notices listed. diff --git a/lib/noticelist.php b/lib/noticelist.php index 027db2b3e..bf12bb73c 100644 --- a/lib/noticelist.php +++ b/lib/noticelist.php @@ -75,7 +75,7 @@ class NoticeList extends Widget /** * show the list of notices * - * "Uses up" the stream by looping through it. So, probably cannot + * "Uses up" the stream by looping through it. So, probably can't * be called twice on the same list. * * @return int count of notices listed. diff --git a/lib/profilelist.php b/lib/profilelist.php index f3eb66658..bbb722701 100644 --- a/lib/profilelist.php +++ b/lib/profilelist.php @@ -269,7 +269,7 @@ class ProfileListItem extends Widget $usf = new UnsubscribeForm($this->out, $this->profile); $usf->show(); } else { - // Is it a local user? cannot remote sub from a list + // Is it a local user? can't remote sub from a list // XXX: make that possible! $other = User::staticGet('id', $this->profile->id); if (!empty($other)) { diff --git a/lib/serverexception.php b/lib/serverexception.php index 6b2d55a0b..7dc9765ad 100644 --- a/lib/serverexception.php +++ b/lib/serverexception.php @@ -34,7 +34,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { /** * Class for server exceptions * - * Subclass of PHP Exception for server errors. The user typically cannot fix these. + * Subclass of PHP Exception for server errors. The user typically can't fix these. * * @category Exception * @package StatusNet diff --git a/lib/settingsaction.php b/lib/settingsaction.php index 4193ea521..c3669868d 100644 --- a/lib/settingsaction.php +++ b/lib/settingsaction.php @@ -72,7 +72,7 @@ class SettingsAction extends CurrentUserDesignAction $this->clientError(_('Not logged in.')); return; } else if (!common_is_real_login()) { - // Cookie theft means that automatic logins cannot + // Cookie theft means that automatic logins can't // change important settings or see private info, and // _all_ our settings are important common_set_returnto($this->selfUrl()); diff --git a/lib/util.php b/lib/util.php index dde3fb48f..a4865c46c 100644 --- a/lib/util.php +++ b/lib/util.php @@ -576,7 +576,7 @@ function common_linkify($url) { } elseif (is_string($longurl_data)) { $longurl = $longurl_data; } else { - throw new ServerException("Cannot linkify url '$url'"); + throw new ServerException("Can't linkify url '$url'"); } } $attrs = array('href' => $canon, 'title' => $longurl, 'rel' => 'external'); diff --git a/lib/xmppqueuehandler.php b/lib/xmppqueuehandler.php index 8acdcafe7..f28fc9088 100644 --- a/lib/xmppqueuehandler.php +++ b/lib/xmppqueuehandler.php @@ -43,7 +43,7 @@ class XmppQueueHandler extends QueueHandler $this->conn = jabber_connect($this->_id.$this->transport()); if (empty($this->conn)) { - $this->log(LOG_ERR, "Could not connect to server."); + $this->log(LOG_ERR, "Couldn't connect to server."); return false; } diff --git a/locale/statusnet.po b/locale/statusnet.po index 3ea314f34..4331b906e 100644 --- a/locale/statusnet.po +++ b/locale/statusnet.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-11-08 22:12+0000\n" +"POT-Creation-Date: 2009-11-08 11:53+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -16,4442 +16,7310 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: actions/all.php:63 actions/public.php:97 actions/replies.php:92 -#: actions/showfavorites.php:137 actions/tag.php:51 -msgid "No such page" -msgstr "" - -#: actions/all.php:74 actions/allrss.php:68 actions/avatarbynickname.php:75 -#: actions/favoritesrss.php:74 actions/foaf.php:40 actions/foaf.php:58 -#: actions/remotesubscribe.php:145 actions/replies.php:73 -#: actions/repliesrss.php:38 actions/showfavorites.php:105 -#: actions/userbyid.php:74 actions/usergroups.php:91 actions/userrss.php:38 -#: actions/xrds.php:71 lib/command.php:163 lib/command.php:311 -#: lib/command.php:364 lib/command.php:411 lib/command.php:466 -#: lib/galleryaction.php:59 lib/mailbox.php:82 lib/profileaction.php:77 -#: lib/subs.php:34 lib/subs.php:112 -msgid "No such user." -msgstr "" - -#: actions/all.php:84 +#: ../actions/noticesearchrss.php:64 actions/noticesearchrss.php:68 +#: actions/noticesearchrss.php:88 actions/noticesearchrss.php:89 #, php-format -msgid "%s and friends, page %d" +msgid " Search Stream for \"%s\"" msgstr "" -#: actions/all.php:86 actions/all.php:167 actions/allrss.php:115 -#: actions/apitimelinefriends.php:114 lib/personalgroupnav.php:100 -#, php-format -msgid "%s and friends" +#: ../actions/finishopenidlogin.php:82 ../actions/register.php:191 +#: actions/finishopenidlogin.php:88 actions/register.php:205 +#: actions/finishopenidlogin.php:110 actions/finishopenidlogin.php:109 +msgid "" +" except this private data: password, email address, IM address, phone number." msgstr "" -#: actions/all.php:99 -#, php-format -msgid "Feed for friends of %s (RSS 1.0)" +#: ../actions/showstream.php:400 ../lib/stream.php:109 +#: actions/showstream.php:418 lib/mailbox.php:164 lib/stream.php:76 +msgid " from " msgstr "" -#: actions/all.php:107 +#: ../actions/twitapistatuses.php:478 actions/twitapistatuses.php:412 +#: actions/twitapistatuses.php:347 actions/twitapistatuses.php:363 #, php-format -msgid "Feed for friends of %s (RSS 2.0)" +msgid "%1$s / Updates replying to %2$s" msgstr "" -#: actions/all.php:115 +#: ../actions/invite.php:168 actions/invite.php:176 actions/invite.php:211 +#: actions/invite.php:218 actions/invite.php:220 actions/invite.php:226 #, php-format -msgid "Feed for friends of %s (Atom)" +msgid "%1$s has invited you to join them on %2$s" msgstr "" -#: actions/all.php:127 +#: ../actions/invite.php:170 actions/invite.php:220 actions/invite.php:222 +#: actions/invite.php:228 #, php-format msgid "" -"This is the timeline for %s and friends but no one has posted anything yet." +"%1$s has invited you to join them on %2$s (%3$s).\n" +"\n" +"%2$s is a micro-blogging service that lets you keep up-to-date with people " +"you know and people who interest you.\n" +"\n" +"You can also share news about yourself, your thoughts, or your life online " +"with people who know about you. It's also great for meeting new people who " +"share your interests.\n" +"\n" +"%1$s said:\n" +"\n" +"%4$s\n" +"\n" +"You can see %1$s's profile page on %2$s here:\n" +"\n" +"%5$s\n" +"\n" +"If you'd like to try the service, click on the link below to accept the " +"invitation.\n" +"\n" +"%6$s\n" +"\n" +"If not, you can ignore this message. Thanks for your patience and your " +"time.\n" +"\n" +"Sincerely, %2$s\n" msgstr "" -#: actions/all.php:132 +#: ../lib/mail.php:124 lib/mail.php:124 lib/mail.php:126 lib/mail.php:241 +#: lib/mail.php:236 lib/mail.php:235 #, php-format -msgid "" -"Try subscribing to more users, [join a group](%%action.groups%%) or post " -"something yourself." +msgid "%1$s is now listening to your notices on %2$s." msgstr "" -#: actions/all.php:134 +#: ../lib/mail.php:126 #, php-format msgid "" -"You can try to [nudge %s](../%s) from his profile or [post something to his " -"or her attention](%%%%action.newnotice%%%%?status_textarea=%s)." +"%1$s is now listening to your notices on %2$s.\n" +"\n" +"\t%3$s\n" +"\n" +"Faithfully yours,\n" +"%4$s.\n" msgstr "" -#: actions/all.php:137 actions/replies.php:209 actions/showstream.php:202 +#: ../actions/twitapistatuses.php:482 actions/twitapistatuses.php:415 +#: actions/twitapistatuses.php:350 actions/twitapistatuses.php:367 +#: actions/twitapistatuses.php:328 actions/apitimelinementions.php:126 #, php-format -msgid "" -"Why not [register an account](%%%%action.register%%%%) and then nudge %s or " -"post a notice to his or her attention." +msgid "%1$s updates that reply to updates from %2$s / %3$s." msgstr "" -#: actions/all.php:165 -msgid "You and friends" +#: ../actions/shownotice.php:45 actions/shownotice.php:45 +#: actions/shownotice.php:161 actions/shownotice.php:174 actions/oembed.php:86 +#: actions/shownotice.php:180 +#, php-format +msgid "%1$s's status on %2$s" msgstr "" -#: actions/allrss.php:119 actions/apitimelinefriends.php:121 +#: ../actions/invite.php:84 ../actions/invite.php:92 actions/invite.php:91 +#: actions/invite.php:99 actions/invite.php:123 actions/invite.php:131 +#: actions/invite.php:125 actions/invite.php:133 actions/invite.php:139 #, php-format -msgid "Updates from %1$s and friends on %2$s!" +msgid "%s (%s)" msgstr "" -#: actions/apiaccountratelimitstatus.php:70 actions/apidirectmessage.php:156 -#: actions/apifavoritecreate.php:99 actions/apifavoritedestroy.php:100 -#: actions/apifriendshipscreate.php:100 actions/apifriendshipsdestroy.php:100 -#: actions/apifriendshipsshow.php:129 actions/apigroupcreate.php:184 -#: actions/apigroupismember.php:114 actions/apigroupjoin.php:155 -#: actions/apigroupleave.php:141 actions/apigrouplistall.php:120 -#: actions/apigrouplist.php:132 actions/apigroupmembership.php:101 -#: actions/apigroupshow.php:105 actions/apihelptest.php:88 -#: actions/apistatusesdestroy.php:102 actions/apistatusesshow.php:108 -#: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 -#: actions/apisubscriptions.php:111 actions/apitimelinefavorites.php:144 -#: actions/apitimelinefriends.php:154 actions/apitimelinegroup.php:141 -#: actions/apitimelinementions.php:149 actions/apitimelinepublic.php:130 -#: actions/apitimelinetag.php:139 actions/apitimelineuser.php:163 -#: actions/apiusershow.php:101 -msgid "API method not found!" +#: ../actions/publicrss.php:62 actions/publicrss.php:48 +#: actions/publicrss.php:90 actions/publicrss.php:89 +#, php-format +msgid "%s Public Stream" msgstr "" -#: actions/apiaccountupdateprofileimage.php:84 actions/apiblockcreate.php:89 -#: actions/apiblockdestroy.php:88 actions/apidirectmessagenew.php:117 -#: actions/apifavoritecreate.php:90 actions/apifavoritedestroy.php:91 -#: actions/apifriendshipscreate.php:91 actions/apifriendshipsdestroy.php:91 -#: actions/apigroupcreate.php:104 actions/apigroupjoin.php:91 -#: actions/apigroupleave.php:91 actions/apistatusesupdate.php:109 -msgid "This method requires a POST." +#: ../actions/all.php:47 ../actions/allrss.php:60 +#: ../actions/twitapistatuses.php:238 ../lib/stream.php:51 actions/all.php:47 +#: actions/allrss.php:60 actions/twitapistatuses.php:155 lib/personal.php:51 +#: actions/all.php:65 actions/allrss.php:103 actions/facebookhome.php:164 +#: actions/twitapistatuses.php:126 lib/personalgroupnav.php:99 +#: actions/all.php:68 actions/all.php:114 actions/allrss.php:106 +#: actions/facebookhome.php:163 actions/twitapistatuses.php:130 +#: actions/all.php:50 actions/all.php:127 actions/allrss.php:114 +#: actions/facebookhome.php:158 actions/twitapistatuses.php:89 +#: lib/personalgroupnav.php:100 actions/all.php:86 actions/all.php:167 +#: actions/allrss.php:115 actions/apitimelinefriends.php:114 +#, php-format +msgid "%s and friends" msgstr "" -#: actions/apiaccountupdateprofileimage.php:97 -#: actions/apistatusesupdate.php:122 actions/avatarsettings.php:254 -#: actions/newnotice.php:94 lib/designsettings.php:283 +#: ../actions/twitapistatuses.php:49 actions/twitapistatuses.php:49 +#: actions/twitapistatuses.php:33 actions/twitapistatuses.php:32 +#: actions/twitapistatuses.php:37 actions/apitimelinepublic.php:106 +#: actions/publicrss.php:103 #, php-format -msgid "" -"The server was unable to handle that much POST data (%s bytes) due to its " -"current configuration." +msgid "%s public timeline" msgstr "" -#: actions/apiaccountupdateprofileimage.php:105 actions/apiblockcreate.php:97 -#: actions/apiblockdestroy.php:96 actions/apidirectmessagenew.php:75 -#: actions/apidirectmessage.php:77 actions/apigroupcreate.php:112 -#: actions/apigroupismember.php:90 actions/apigroupjoin.php:99 -#: actions/apigroupleave.php:99 actions/apigrouplist.php:90 -#: actions/apistatusesupdate.php:139 actions/apisubscriptions.php:87 -#: actions/apitimelinefavorites.php:70 actions/apitimelinefriends.php:79 -#: actions/apitimelinementions.php:79 actions/apitimelineuser.php:81 -msgid "No such user!" +#: ../lib/mail.php:206 lib/mail.php:212 lib/mail.php:411 lib/mail.php:412 +#, php-format +msgid "%s status" msgstr "" -#: actions/apiaccountupdateprofileimage.php:130 actions/apiusershow.php:108 -#: actions/avatarbynickname.php:80 actions/foaf.php:65 actions/replies.php:80 -#: actions/usergroups.php:98 lib/galleryaction.php:66 lib/profileaction.php:84 -msgid "User has no profile." +#: ../actions/twitapistatuses.php:338 actions/twitapistatuses.php:265 +#: actions/twitapistatuses.php:199 actions/twitapistatuses.php:209 +#: actions/twitapigroups.php:69 actions/twitapistatuses.php:154 +#: actions/apitimelinegroup.php:102 actions/apitimelineuser.php:117 +#: actions/grouprss.php:131 actions/userrss.php:90 +#, php-format +msgid "%s timeline" msgstr "" -#: actions/apiblockcreate.php:108 -msgid "Block user failed." +#: ../actions/twitapistatuses.php:52 actions/twitapistatuses.php:52 +#: actions/twitapistatuses.php:36 actions/twitapistatuses.php:38 +#: actions/twitapistatuses.php:41 actions/apitimelinepublic.php:110 +#: actions/publicrss.php:105 +#, php-format +msgid "%s updates from everyone!" msgstr "" -#: actions/apiblockdestroy.php:107 -msgid "Unblock user failed." +#: ../actions/register.php:213 actions/register.php:497 +#: actions/register.php:545 actions/register.php:555 actions/register.php:561 +msgid "" +"(You should receive a message by email momentarily, with instructions on how " +"to confirm your email address.)" msgstr "" -#: actions/apidirectmessagenew.php:126 -msgid "No message text!" +#: ../lib/util.php:257 lib/util.php:273 lib/action.php:605 lib/action.php:702 +#: lib/action.php:752 lib/action.php:767 +#, php-format +msgid "" +"**%%site.name%%** is a microblogging service brought to you by [%%site." +"broughtby%%](%%site.broughtbyurl%%). " msgstr "" -#: actions/apidirectmessagenew.php:135 actions/newmessage.php:150 +#: ../lib/util.php:259 lib/util.php:275 lib/action.php:607 lib/action.php:704 +#: lib/action.php:754 lib/action.php:769 #, php-format -msgid "That's too long. Max message size is %d chars." +msgid "**%%site.name%%** is a microblogging service. " msgstr "" -#: actions/apidirectmessagenew.php:146 -msgid "Recipient user not found." +#: ../actions/finishopenidlogin.php:73 ../actions/profilesettings.php:43 +#: actions/finishopenidlogin.php:79 actions/profilesettings.php:76 +#: actions/finishopenidlogin.php:101 actions/profilesettings.php:100 +#: lib/groupeditform.php:139 actions/finishopenidlogin.php:100 +#: lib/groupeditform.php:154 actions/profilesettings.php:108 +msgid "1-64 lowercase letters or numbers, no punctuation or spaces" msgstr "" -#: actions/apidirectmessagenew.php:150 -msgid "Can't send direct messages to users who aren't your friend." +#: ../actions/register.php:152 actions/register.php:166 +#: actions/register.php:368 actions/register.php:414 actions/register.php:418 +#: actions/register.php:424 +msgid "1-64 lowercase letters or numbers, no punctuation or spaces. Required." msgstr "" -#: actions/apidirectmessage.php:89 -#, php-format -msgid "Direct messages from %s" +#: ../actions/password.php:42 actions/profilesettings.php:181 +#: actions/passwordsettings.php:102 actions/passwordsettings.php:108 +msgid "6 or more characters" msgstr "" -#: actions/apidirectmessage.php:93 -#, php-format -msgid "All the direct messages sent from %s" +#: ../actions/recoverpassword.php:180 actions/recoverpassword.php:186 +#: actions/recoverpassword.php:220 actions/recoverpassword.php:233 +#: actions/recoverpassword.php:236 +msgid "6 or more characters, and don't forget it!" msgstr "" -#: actions/apidirectmessage.php:101 -#, php-format -msgid "Direct messages to %s" +#: ../actions/register.php:154 actions/register.php:168 +#: actions/register.php:373 actions/register.php:419 actions/register.php:423 +#: actions/register.php:429 +msgid "6 or more characters. Required." msgstr "" -#: actions/apidirectmessage.php:105 +#: ../actions/imsettings.php:197 actions/imsettings.php:205 +#: actions/imsettings.php:321 actions/imsettings.php:327 #, php-format -msgid "All the direct messages sent to %s" +msgid "" +"A confirmation code was sent to the IM address you added. You must approve %" +"s for sending messages to you." msgstr "" -#: actions/apifavoritecreate.php:108 actions/apifavoritedestroy.php:109 -#: actions/apistatusesdestroy.php:113 -msgid "No status found with that ID." +#: ../actions/emailsettings.php:213 actions/emailsettings.php:231 +#: actions/emailsettings.php:350 actions/emailsettings.php:358 +msgid "" +"A confirmation code was sent to the email address you added. Check your " +"inbox (and spam box!) for the code and instructions on how to use it." msgstr "" -#: actions/apifavoritecreate.php:119 -msgid "This status is already a favorite!" +#: ../actions/smssettings.php:216 actions/smssettings.php:224 +msgid "" +"A confirmation code was sent to the phone number you added. Check your inbox " +"(and spam box!) for the code and instructions on how to use it." +msgstr "" + +#: ../actions/twitapiaccount.php:49 ../actions/twitapihelp.php:45 +#: ../actions/twitapistatuses.php:88 ../actions/twitapistatuses.php:259 +#: ../actions/twitapistatuses.php:370 ../actions/twitapistatuses.php:532 +#: ../actions/twitapiusers.php:122 actions/twitapiaccount.php:49 +#: actions/twitapidirect_messages.php:104 actions/twitapifavorites.php:111 +#: actions/twitapifavorites.php:120 actions/twitapifriendships.php:156 +#: actions/twitapihelp.php:46 actions/twitapistatuses.php:93 +#: actions/twitapistatuses.php:176 actions/twitapistatuses.php:288 +#: actions/twitapistatuses.php:298 actions/twitapistatuses.php:454 +#: actions/twitapistatuses.php:463 actions/twitapistatuses.php:504 +#: actions/twitapiusers.php:55 actions/twitapiaccount.php:37 +#: actions/twitapidirect_messages.php:111 actions/twitapifavorites.php:85 +#: actions/twitapifavorites.php:102 actions/twitapifriendships.php:121 +#: actions/twitapihelp.php:44 actions/twitapistatusnet.php:82 +#: actions/twitapistatusnet.php:151 actions/twitapistatuses.php:79 +#: actions/twitapistatuses.php:147 actions/twitapistatuses.php:228 +#: actions/twitapistatuses.php:239 actions/twitapistatuses.php:392 +#: actions/twitapistatuses.php:402 actions/twitapistatuses.php:429 +#: actions/twitapiusers.php:32 actions/twitapidirect_messages.php:120 +#: actions/twitapifavorites.php:91 actions/twitapifavorites.php:108 +#: actions/twitapistatuses.php:82 actions/twitapistatuses.php:159 +#: actions/twitapistatuses.php:246 actions/twitapistatuses.php:257 +#: actions/twitapistatuses.php:416 actions/twitapistatuses.php:426 +#: actions/twitapistatuses.php:453 actions/twitapidirect_messages.php:113 +#: actions/twitapifavorites.php:92 actions/twitapifavorites.php:109 +#: actions/twitapifavorites.php:160 actions/twitapifriendships.php:128 +#: actions/twitapifriendships.php:168 actions/twitapigroups.php:110 +#: actions/twitapistatuses.php:68 actions/twitapistatuses.php:134 +#: actions/twitapistatuses.php:201 actions/twitapistatuses.php:211 +#: actions/twitapistatuses.php:357 actions/twitapistatuses.php:372 +#: actions/twitapistatuses.php:409 actions/twitapitags.php:110 +#: actions/twitapiusers.php:34 actions/apiaccountratelimitstatus.php:70 +#: actions/apidirectmessage.php:156 actions/apifavoritecreate.php:99 +#: actions/apifavoritedestroy.php:100 actions/apifriendshipscreate.php:100 +#: actions/apifriendshipsdestroy.php:100 actions/apifriendshipsshow.php:129 +#: actions/apigroupcreate.php:184 actions/apigroupismember.php:114 +#: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 +#: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 +#: actions/apigroupmembership.php:101 actions/apigroupshow.php:105 +#: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 +#: actions/apistatusesshow.php:108 actions/apistatusnetconfig.php:133 +#: actions/apistatusnetversion.php:93 actions/apisubscriptions.php:111 +#: actions/apitimelinefavorites.php:144 actions/apitimelinefriends.php:154 +#: actions/apitimelinegroup.php:141 actions/apitimelinementions.php:149 +#: actions/apitimelinepublic.php:130 actions/apitimelinetag.php:139 +#: actions/apitimelineuser.php:163 actions/apiusershow.php:101 +msgid "API method not found!" msgstr "" -#: actions/apifavoritecreate.php:130 actions/favor.php:84 lib/command.php:176 -msgid "Could not create favorite." +#: ../actions/twitapiaccount.php:57 ../actions/twitapiaccount.php:113 +#: ../actions/twitapiaccount.php:119 ../actions/twitapiblocks.php:28 +#: ../actions/twitapiblocks.php:34 ../actions/twitapidirect_messages.php:43 +#: ../actions/twitapidirect_messages.php:49 +#: ../actions/twitapidirect_messages.php:56 +#: ../actions/twitapidirect_messages.php:62 ../actions/twitapifavorites.php:41 +#: ../actions/twitapifavorites.php:47 ../actions/twitapifavorites.php:53 +#: ../actions/twitapihelp.php:52 ../actions/twitapinotifications.php:29 +#: ../actions/twitapinotifications.php:35 ../actions/twitapistatuses.php:768 +#: actions/twitapiaccount.php:56 actions/twitapiaccount.php:109 +#: actions/twitapiaccount.php:114 actions/twitapiblocks.php:28 +#: actions/twitapiblocks.php:33 actions/twitapidirect_messages.php:170 +#: actions/twitapifavorites.php:168 actions/twitapihelp.php:53 +#: actions/twitapinotifications.php:29 actions/twitapinotifications.php:34 +#: actions/twitapistatuses.php:690 actions/twitapiaccount.php:45 +#: actions/twitapiaccount.php:97 actions/twitapiaccount.php:103 +#: actions/twitapidirect_messages.php:184 actions/twitapifavorites.php:143 +#: actions/twitapihelp.php:52 actions/twitapistatusnet.php:172 +#: actions/twitapinotifications.php:31 actions/twitapinotifications.php:37 +#: actions/twitapistatuses.php:562 actions/twitapiaccount.php:46 +#: actions/twitapiaccount.php:98 actions/twitapiaccount.php:104 +#: actions/twitapidirect_messages.php:193 actions/twitapifavorites.php:149 +#: actions/twitapistatuses.php:625 actions/twitapitrends.php:87 +#: actions/twitapiaccount.php:48 actions/twitapidirect_messages.php:189 +#: actions/twitapihelp.php:54 actions/twitapistatuses.php:582 +msgid "API method under construction." msgstr "" -#: actions/apifavoritedestroy.php:122 -msgid "That status is not a favorite!" +#: ../lib/util.php:324 lib/util.php:340 lib/action.php:568 lib/action.php:661 +#: lib/action.php:706 lib/action.php:721 +msgid "About" msgstr "" -#: actions/apifavoritedestroy.php:134 actions/disfavor.php:87 -msgid "Could not delete favorite." +#: ../actions/userauthorization.php:119 actions/userauthorization.php:126 +#: actions/userauthorization.php:143 actions/userauthorization.php:178 +#: actions/userauthorization.php:209 +msgid "Accept" msgstr "" -#: actions/apifriendshipscreate.php:109 -msgid "Could not follow user: User not found." +#: ../actions/emailsettings.php:62 ../actions/imsettings.php:63 +#: ../actions/openidsettings.php:57 ../actions/smssettings.php:71 +#: actions/emailsettings.php:63 actions/imsettings.php:64 +#: actions/openidsettings.php:58 actions/smssettings.php:71 +#: actions/twittersettings.php:85 actions/emailsettings.php:120 +#: actions/imsettings.php:127 actions/openidsettings.php:111 +#: actions/smssettings.php:133 actions/twittersettings.php:163 +#: actions/twittersettings.php:166 actions/twittersettings.php:182 +#: actions/emailsettings.php:126 actions/imsettings.php:133 +#: actions/smssettings.php:145 +msgid "Add" msgstr "" -#: actions/apifriendshipscreate.php:118 -#, php-format -msgid "Could not follow user: %s is already on your list." +#: ../actions/openidsettings.php:43 actions/openidsettings.php:44 +#: actions/openidsettings.php:93 +msgid "Add OpenID" msgstr "" -#: actions/apifriendshipsdestroy.php:109 -msgid "Could not unfollow user: User not found." +#: ../lib/settingsaction.php:97 lib/settingsaction.php:91 +#: lib/accountsettingsaction.php:117 +msgid "Add or remove OpenIDs" msgstr "" -#: actions/apifriendshipsdestroy.php:120 -msgid "You cannot unfollow yourself!" +#: ../actions/emailsettings.php:38 ../actions/imsettings.php:39 +#: ../actions/smssettings.php:39 actions/emailsettings.php:39 +#: actions/imsettings.php:40 actions/smssettings.php:39 +#: actions/emailsettings.php:94 actions/imsettings.php:94 +#: actions/smssettings.php:92 actions/emailsettings.php:100 +#: actions/imsettings.php:100 actions/smssettings.php:104 +msgid "Address" msgstr "" -#: actions/apifriendshipsexists.php:94 -msgid "Two user ids or screen_names must be supplied." +#: ../actions/invite.php:131 actions/invite.php:139 actions/invite.php:176 +#: actions/invite.php:181 actions/invite.php:183 actions/invite.php:189 +msgid "Addresses of friends to invite (one per line)" msgstr "" -#: actions/apifriendshipsshow.php:135 -msgid "Could not determine source user." +#: ../actions/showstream.php:273 actions/showstream.php:288 +#: actions/showstream.php:422 lib/profileaction.php:126 +msgid "All subscriptions" msgstr "" -#: actions/apifriendshipsshow.php:143 -msgid "Could not find target user." +#: ../actions/publicrss.php:64 actions/publicrss.php:50 +#: actions/publicrss.php:92 actions/publicrss.php:91 +#, php-format +msgid "All updates for %s" msgstr "" -#: actions/apigroupcreate.php:136 actions/newgroup.php:204 -msgid "Could not create group." +#: ../actions/noticesearchrss.php:66 actions/noticesearchrss.php:70 +#: actions/noticesearchrss.php:90 actions/noticesearchrss.php:91 +#, php-format +msgid "All updates matching search term \"%s\"" msgstr "" -#: actions/apigroupcreate.php:147 actions/editgroup.php:259 -#: actions/newgroup.php:210 -msgid "Could not create aliases." +#: ../actions/finishopenidlogin.php:29 ../actions/login.php:31 +#: ../actions/openidlogin.php:29 ../actions/register.php:30 +#: actions/finishopenidlogin.php:29 actions/login.php:31 +#: actions/openidlogin.php:29 actions/register.php:30 +#: actions/finishopenidlogin.php:34 actions/login.php:77 +#: actions/openidlogin.php:30 actions/register.php:92 actions/register.php:131 +#: actions/login.php:79 actions/register.php:137 +msgid "Already logged in." msgstr "" -#: actions/apigroupcreate.php:166 actions/newgroup.php:224 -msgid "Could not set group membership." +#: ../lib/subs.php:42 lib/subs.php:42 lib/subs.php:49 lib/subs.php:48 +msgid "Already subscribed!." msgstr "" -#: actions/apigroupcreate.php:212 actions/editgroup.php:182 -#: actions/newgroup.php:126 actions/profilesettings.php:208 -#: actions/register.php:205 -msgid "Nickname must have only lowercase letters and numbers and no spaces." +#: ../actions/deletenotice.php:54 actions/deletenotice.php:55 +#: actions/deletenotice.php:113 actions/deletenotice.php:114 +#: actions/deletenotice.php:144 +msgid "Are you sure you want to delete this notice?" msgstr "" -#: actions/apigroupcreate.php:221 actions/editgroup.php:186 -#: actions/newgroup.php:130 actions/profilesettings.php:231 -#: actions/register.php:208 -msgid "Nickname already in use. Try another one." +#: ../actions/userauthorization.php:77 actions/userauthorization.php:83 +#: actions/userauthorization.php:81 actions/userauthorization.php:76 +#: actions/userauthorization.php:105 +msgid "Authorize subscription" msgstr "" -#: actions/apigroupcreate.php:228 actions/editgroup.php:189 -#: actions/newgroup.php:133 actions/profilesettings.php:211 -#: actions/register.php:210 -msgid "Not a valid nickname." +#: ../actions/login.php:104 ../actions/register.php:178 +#: actions/register.php:192 actions/login.php:218 actions/openidlogin.php:117 +#: actions/register.php:416 actions/register.php:463 actions/login.php:226 +#: actions/register.php:473 actions/login.php:253 actions/register.php:479 +msgid "Automatically login in the future; not for shared computers!" msgstr "" -#: actions/apigroupcreate.php:244 actions/editgroup.php:195 -#: actions/newgroup.php:139 actions/profilesettings.php:215 -#: actions/register.php:217 -msgid "Homepage is not a valid URL." +#: ../actions/profilesettings.php:65 actions/profilesettings.php:98 +#: actions/profilesettings.php:144 actions/profilesettings.php:145 +#: actions/profilesettings.php:160 +msgid "" +"Automatically subscribe to whoever subscribes to me (best for non-humans)" msgstr "" -#: actions/apigroupcreate.php:253 actions/editgroup.php:198 -#: actions/newgroup.php:142 actions/profilesettings.php:218 -#: actions/register.php:220 -msgid "Full name is too long (max 255 chars)." +#: ../actions/avatar.php:32 ../lib/settingsaction.php:90 +#: actions/profilesettings.php:34 actions/avatarsettings.php:65 +#: actions/showgroup.php:209 lib/accountsettingsaction.php:107 +#: actions/avatarsettings.php:67 actions/showgroup.php:211 +#: actions/showgroup.php:216 actions/showgroup.php:221 +#: lib/accountsettingsaction.php:111 +msgid "Avatar" msgstr "" -#: actions/apigroupcreate.php:261 -#, php-format -msgid "Description is too long (max %d chars)." +#: ../actions/avatar.php:113 actions/profilesettings.php:350 +#: actions/avatarsettings.php:395 actions/avatarsettings.php:346 +#: actions/avatarsettings.php:360 +msgid "Avatar updated." msgstr "" -#: actions/apigroupcreate.php:272 actions/editgroup.php:204 -#: actions/newgroup.php:148 actions/profilesettings.php:225 -#: actions/register.php:227 -msgid "Location is too long (max 255 chars)." +#: ../actions/imsettings.php:55 actions/imsettings.php:56 +#: actions/imsettings.php:108 actions/imsettings.php:114 +#, php-format +msgid "" +"Awaiting confirmation on this address. Check your Jabber/GTalk account for a " +"message with further instructions. (Did you add %s to your buddy list?)" msgstr "" -#: actions/apigroupcreate.php:291 actions/editgroup.php:215 -#: actions/newgroup.php:159 -#, php-format -msgid "Too many aliases! Maximum %d." +#: ../actions/emailsettings.php:54 actions/emailsettings.php:55 +#: actions/emailsettings.php:107 actions/emailsettings.php:113 +msgid "" +"Awaiting confirmation on this address. Check your inbox (and spam box!) for " +"a message with further instructions." msgstr "" -#: actions/apigroupcreate.php:312 actions/editgroup.php:224 -#: actions/newgroup.php:168 -#, php-format -msgid "Invalid alias: \"%s\"" +#: ../actions/smssettings.php:58 actions/smssettings.php:58 +#: actions/smssettings.php:111 actions/smssettings.php:123 +msgid "Awaiting confirmation on this phone number." msgstr "" -#: actions/apigroupcreate.php:321 actions/editgroup.php:228 -#: actions/newgroup.php:172 -#, php-format -msgid "Alias \"%s\" already in use. Try another one." +#: ../lib/util.php:1318 lib/util.php:1452 +msgid "Before »" msgstr "" -#: actions/apigroupcreate.php:334 actions/editgroup.php:234 -#: actions/newgroup.php:178 -msgid "Alias can't be the same as nickname." +#: ../actions/profilesettings.php:49 ../actions/register.php:170 +#: actions/profilesettings.php:82 actions/register.php:184 +#: actions/profilesettings.php:112 actions/register.php:402 +#: actions/register.php:448 actions/profilesettings.php:127 +#: actions/register.php:459 actions/register.php:465 +msgid "Bio" msgstr "" -#: actions/apigroupjoin.php:110 -msgid "You are already a member of that group." +#: ../actions/profilesettings.php:101 ../actions/register.php:82 +#: ../actions/updateprofile.php:103 actions/profilesettings.php:216 +#: actions/register.php:89 actions/updateprofile.php:104 +#: actions/profilesettings.php:205 actions/register.php:174 +#: actions/updateprofile.php:107 actions/updateprofile.php:109 +#: actions/profilesettings.php:206 actions/register.php:211 +msgid "Bio is too long (max 140 chars)." msgstr "" -#: actions/apigroupjoin.php:119 actions/joingroup.php:95 lib/command.php:221 -msgid "You have been blocked from that group by the admin." +#: ../lib/deleteaction.php:41 lib/deleteaction.php:41 lib/deleteaction.php:69 +#: actions/deletenotice.php:71 +msgid "Can't delete this notice." msgstr "" -#: actions/apigroupjoin.php:138 +#: ../actions/updateprofile.php:119 actions/updateprofile.php:120 +#: actions/updateprofile.php:123 actions/updateprofile.php:125 #, php-format -msgid "Could not join user %s to group %s." +msgid "Can't read avatar URL '%s'" msgstr "" -#: actions/apigroupleave.php:114 -msgid "You are not a member of this group." +#: ../actions/password.php:85 ../actions/recoverpassword.php:300 +#: actions/profilesettings.php:404 actions/recoverpassword.php:313 +#: actions/passwordsettings.php:169 actions/recoverpassword.php:347 +#: actions/passwordsettings.php:174 actions/recoverpassword.php:365 +#: actions/passwordsettings.php:180 actions/recoverpassword.php:368 +#: actions/passwordsettings.php:185 +msgid "Can't save new password." msgstr "" -#: actions/apigroupleave.php:124 -#, php-format -msgid "Could not remove user %s to group %s." +#: ../actions/emailsettings.php:57 ../actions/imsettings.php:58 +#: ../actions/smssettings.php:62 actions/emailsettings.php:58 +#: actions/imsettings.php:59 actions/smssettings.php:62 +#: actions/emailsettings.php:111 actions/imsettings.php:114 +#: actions/smssettings.php:114 actions/emailsettings.php:117 +#: actions/imsettings.php:120 actions/smssettings.php:126 +msgid "Cancel" msgstr "" -#: actions/apigrouplistall.php:90 actions/usergroups.php:62 -#, php-format -msgid "%s groups" +#: ../lib/openid.php:121 lib/openid.php:121 lib/openid.php:130 +#: lib/openid.php:133 +msgid "Cannot instantiate OpenID consumer object." msgstr "" -#: actions/apigrouplistall.php:94 -#, php-format -msgid "groups on %s" +#: ../actions/imsettings.php:163 actions/imsettings.php:171 +#: actions/imsettings.php:286 actions/imsettings.php:292 +msgid "Cannot normalize that Jabber ID" msgstr "" -#: actions/apigrouplist.php:95 -#, php-format -msgid "%s's groups" +#: ../actions/emailsettings.php:181 actions/emailsettings.php:199 +#: actions/emailsettings.php:311 actions/emailsettings.php:318 +#: actions/emailsettings.php:326 +msgid "Cannot normalize that email address" msgstr "" -#: actions/apigrouplist.php:103 -#, php-format -msgid "Groups %s is a member of on %s." +#: ../actions/password.php:45 actions/profilesettings.php:184 +#: actions/passwordsettings.php:110 actions/passwordsettings.php:116 +msgid "Change" msgstr "" -#: actions/apistatusesdestroy.php:107 -msgid "This method requires a POST or DELETE." +#: ../lib/settingsaction.php:88 lib/settingsaction.php:88 +#: lib/accountsettingsaction.php:114 lib/accountsettingsaction.php:118 +msgid "Change email handling" msgstr "" -#: actions/apistatusesdestroy.php:130 -msgid "You may not delete another user's status." -msgstr "" - -#: actions/apistatusesshow.php:138 -msgid "Status deleted." +#: ../actions/password.php:32 actions/profilesettings.php:36 +#: actions/passwordsettings.php:58 +msgid "Change password" msgstr "" -#: actions/apistatusesshow.php:144 -msgid "No status with that ID found." +#: ../lib/settingsaction.php:94 lib/accountsettingsaction.php:111 +#: lib/accountsettingsaction.php:115 +msgid "Change your password" msgstr "" -#: actions/apistatusesupdate.php:152 actions/newnotice.php:155 -#: scripts/maildaemon.php:71 -#, php-format -msgid "That's too long. Max notice size is %d chars." +#: ../lib/settingsaction.php:85 lib/settingsaction.php:85 +#: lib/accountsettingsaction.php:105 lib/accountsettingsaction.php:109 +msgid "Change your profile settings" msgstr "" -#: actions/apistatusesupdate.php:193 -msgid "Not found" +#: ../actions/password.php:43 ../actions/recoverpassword.php:181 +#: ../actions/register.php:155 ../actions/smssettings.php:65 +#: actions/profilesettings.php:182 actions/recoverpassword.php:187 +#: actions/register.php:169 actions/smssettings.php:65 +#: actions/passwordsettings.php:105 actions/recoverpassword.php:221 +#: actions/register.php:376 actions/smssettings.php:122 +#: actions/recoverpassword.php:236 actions/register.php:422 +#: actions/passwordsettings.php:111 actions/recoverpassword.php:239 +#: actions/register.php:426 actions/smssettings.php:134 +#: actions/register.php:432 +msgid "Confirm" msgstr "" -#: actions/apistatusesupdate.php:216 actions/newnotice.php:178 -#, php-format -msgid "Max notice size is %d chars, including attachment URL." +#: ../actions/confirmaddress.php:90 actions/confirmaddress.php:90 +#: actions/confirmaddress.php:144 +msgid "Confirm Address" msgstr "" -#: actions/apisubscriptions.php:231 actions/apisubscriptions.php:261 -msgid "Unsupported format." +#: ../actions/emailsettings.php:238 ../actions/imsettings.php:222 +#: ../actions/smssettings.php:245 actions/emailsettings.php:256 +#: actions/imsettings.php:230 actions/smssettings.php:253 +#: actions/emailsettings.php:379 actions/imsettings.php:361 +#: actions/smssettings.php:374 actions/emailsettings.php:386 +#: actions/emailsettings.php:394 actions/imsettings.php:367 +#: actions/smssettings.php:386 +msgid "Confirmation cancelled." msgstr "" -#: actions/apitimelinefavorites.php:107 -#, php-format -msgid "%s / Favorites from %s" +#: ../actions/smssettings.php:63 actions/smssettings.php:63 +#: actions/smssettings.php:118 actions/smssettings.php:130 +msgid "Confirmation code" msgstr "" -#: actions/apitimelinefavorites.php:119 -#, php-format -msgid "%s updates favorited by %s / %s." +#: ../actions/confirmaddress.php:38 actions/confirmaddress.php:38 +#: actions/confirmaddress.php:80 +msgid "Confirmation code not found." msgstr "" -#: actions/apitimelinegroup.php:102 actions/apitimelineuser.php:117 -#: actions/grouprss.php:131 actions/userrss.php:90 +#: ../actions/register.php:202 actions/register.php:473 +#: actions/register.php:521 actions/register.php:531 actions/register.php:537 #, php-format -msgid "%s timeline" +msgid "" +"Congratulations, %s! And welcome to %%%%site.name%%%%. From here, you may " +"want to...\n" +"\n" +"* Go to [your profile](%s) and post your first message.\n" +"* Add a [Jabber/GTalk address](%%%%action.imsettings%%%%) so you can send " +"notices through instant messages.\n" +"* [Search for people](%%%%action.peoplesearch%%%%) that you may know or that " +"share your interests. \n" +"* Update your [profile settings](%%%%action.profilesettings%%%%) to tell " +"others more about you. \n" +"* Read over the [online docs](%%%%doc.help%%%%) for features you may have " +"missed. \n" +"\n" +"Thanks for signing up and we hope you enjoy using this service." msgstr "" -#: actions/apitimelinegroup.php:110 actions/apitimelineuser.php:125 -#: actions/userrss.php:92 -#, php-format -msgid "Updates from %1$s on %2$s!" +#: ../actions/finishopenidlogin.php:91 actions/finishopenidlogin.php:97 +#: actions/finishopenidlogin.php:119 lib/action.php:330 lib/action.php:403 +#: lib/action.php:406 actions/finishopenidlogin.php:118 lib/action.php:422 +#: lib/action.php:425 lib/action.php:435 +msgid "Connect" msgstr "" -#: actions/apitimelinementions.php:116 -#, php-format -msgid "%1$s / Updates mentioning %2$s" +#: ../actions/finishopenidlogin.php:86 actions/finishopenidlogin.php:92 +#: actions/finishopenidlogin.php:114 actions/finishopenidlogin.php:113 +msgid "Connect existing account" msgstr "" -#: actions/apitimelinementions.php:126 -#, php-format -msgid "%1$s updates that reply to updates from %2$s / %3$s." +#: ../lib/util.php:332 lib/util.php:348 lib/action.php:576 lib/action.php:669 +#: lib/action.php:719 lib/action.php:734 +msgid "Contact" msgstr "" -#: actions/apitimelinepublic.php:106 actions/publicrss.php:103 +#: ../lib/openid.php:178 lib/openid.php:178 lib/openid.php:187 +#: lib/openid.php:190 #, php-format -msgid "%s public timeline" +msgid "Could not create OpenID form: %s" msgstr "" -#: actions/apitimelinepublic.php:110 actions/publicrss.php:105 +#: ../actions/twitapifriendships.php:60 ../actions/twitapifriendships.php:76 +#: actions/twitapifriendships.php:60 actions/twitapifriendships.php:76 +#: actions/twitapifriendships.php:48 actions/twitapifriendships.php:64 +#: actions/twitapifriendships.php:51 actions/twitapifriendships.php:68 +#: actions/apifriendshipscreate.php:118 #, php-format -msgid "%s updates from everyone!" +msgid "Could not follow user: %s is already on your list." msgstr "" -#: actions/apitimelinetag.php:101 actions/tag.php:66 -#, php-format -msgid "Notices tagged with %s" +#: ../actions/twitapifriendships.php:53 actions/twitapifriendships.php:53 +#: actions/twitapifriendships.php:41 actions/twitapifriendships.php:43 +#: actions/apifriendshipscreate.php:109 +msgid "Could not follow user: User not found." msgstr "" -#: actions/apitimelinetag.php:107 actions/tagrss.php:64 +#: ../lib/openid.php:160 lib/openid.php:160 lib/openid.php:169 +#: lib/openid.php:172 #, php-format -msgid "Updates tagged with %1$s on %2$s!" +msgid "Could not redirect to server: %s" msgstr "" -#: actions/apiusershow.php:96 -msgid "Not found." +#: ../actions/updateprofile.php:162 actions/updateprofile.php:163 +#: actions/updateprofile.php:166 actions/updateprofile.php:176 +msgid "Could not save avatar info" msgstr "" -#: actions/attachment.php:73 -msgid "No such attachment." +#: ../actions/updateprofile.php:155 actions/updateprofile.php:156 +#: actions/updateprofile.php:159 actions/updateprofile.php:163 +msgid "Could not save new profile info" msgstr "" -#: actions/avatarbynickname.php:59 actions/leavegroup.php:76 -msgid "No nickname." +#: ../lib/subs.php:54 lib/subs.php:61 lib/subs.php:72 lib/subs.php:75 +msgid "Could not subscribe other to you." msgstr "" -#: actions/avatarbynickname.php:64 -msgid "No size." +#: ../lib/subs.php:46 lib/subs.php:46 lib/subs.php:57 lib/subs.php:56 +msgid "Could not subscribe." msgstr "" -#: actions/avatarbynickname.php:69 -msgid "Invalid size." +#: ../actions/recoverpassword.php:102 actions/recoverpassword.php:105 +#: actions/recoverpassword.php:111 +msgid "Could not update user with confirmed email address." msgstr "" -#: actions/avatarsettings.php:67 actions/showgroup.php:221 -#: lib/accountsettingsaction.php:111 -msgid "Avatar" +#: ../actions/finishremotesubscribe.php:99 +#: actions/finishremotesubscribe.php:101 actions/finishremotesubscribe.php:114 +msgid "Couldn't convert request tokens to access tokens." msgstr "" -#: actions/avatarsettings.php:78 -#, php-format -msgid "You can upload your personal avatar. The maximum file size is %s." +#: ../actions/confirmaddress.php:84 ../actions/emailsettings.php:234 +#: ../actions/imsettings.php:218 ../actions/smssettings.php:241 +#: actions/confirmaddress.php:84 actions/emailsettings.php:252 +#: actions/imsettings.php:226 actions/smssettings.php:249 +#: actions/confirmaddress.php:126 actions/emailsettings.php:375 +#: actions/imsettings.php:357 actions/smssettings.php:370 +#: actions/emailsettings.php:382 actions/emailsettings.php:390 +#: actions/imsettings.php:363 actions/smssettings.php:382 +msgid "Couldn't delete email confirmation." msgstr "" -#: actions/avatarsettings.php:106 actions/avatarsettings.php:182 -#: actions/grouplogo.php:178 actions/remotesubscribe.php:191 -#: actions/userauthorization.php:72 actions/userrss.php:103 -msgid "User without matching profile" +#: ../lib/subs.php:103 lib/subs.php:116 lib/subs.php:134 lib/subs.php:136 +msgid "Couldn't delete subscription." msgstr "" -#: actions/avatarsettings.php:119 actions/avatarsettings.php:194 -#: actions/grouplogo.php:251 -msgid "Avatar settings" +#: ../actions/twitapistatuses.php:93 actions/twitapistatuses.php:98 +#: actions/twitapistatuses.php:84 actions/twitapistatuses.php:87 +msgid "Couldn't find any statuses." msgstr "" -#: actions/avatarsettings.php:126 actions/avatarsettings.php:202 -#: actions/grouplogo.php:199 actions/grouplogo.php:259 -msgid "Original" +#: ../actions/remotesubscribe.php:127 actions/remotesubscribe.php:136 +#: actions/remotesubscribe.php:178 +msgid "Couldn't get a request token." msgstr "" -#: actions/avatarsettings.php:141 actions/avatarsettings.php:214 -#: actions/grouplogo.php:210 actions/grouplogo.php:271 -msgid "Preview" +#: ../actions/emailsettings.php:205 ../actions/imsettings.php:187 +#: ../actions/smssettings.php:206 actions/emailsettings.php:223 +#: actions/imsettings.php:195 actions/smssettings.php:214 +#: actions/emailsettings.php:337 actions/imsettings.php:311 +#: actions/smssettings.php:325 actions/emailsettings.php:344 +#: actions/emailsettings.php:352 actions/imsettings.php:317 +#: actions/smssettings.php:337 +msgid "Couldn't insert confirmation code." msgstr "" -#: actions/avatarsettings.php:148 lib/noticelist.php:522 -msgid "Delete" +#: ../actions/finishremotesubscribe.php:180 +#: actions/finishremotesubscribe.php:182 actions/finishremotesubscribe.php:218 +#: lib/oauthstore.php:487 +msgid "Couldn't insert new subscription." msgstr "" -#: actions/avatarsettings.php:165 actions/grouplogo.php:233 -msgid "Upload" +#: ../actions/profilesettings.php:184 ../actions/twitapiaccount.php:96 +#: actions/profilesettings.php:299 actions/twitapiaccount.php:94 +#: actions/profilesettings.php:302 actions/twitapiaccount.php:81 +#: actions/twitapiaccount.php:82 actions/profilesettings.php:328 +msgid "Couldn't save profile." msgstr "" -#: actions/avatarsettings.php:228 actions/grouplogo.php:286 -msgid "Crop" +#: ../actions/profilesettings.php:161 actions/profilesettings.php:276 +#: actions/profilesettings.php:279 actions/profilesettings.php:295 +msgid "Couldn't update user for autosubscribe." msgstr "" -#: actions/avatarsettings.php:265 actions/block.php:64 actions/disfavor.php:74 -#: actions/emailsettings.php:237 actions/favor.php:75 -#: actions/groupblock.php:66 actions/grouplogo.php:309 -#: actions/groupunblock.php:66 actions/imsettings.php:206 -#: actions/invite.php:56 actions/login.php:131 actions/makeadmin.php:66 -#: actions/newmessage.php:135 actions/newnotice.php:103 actions/nudge.php:80 -#: actions/othersettings.php:145 actions/passwordsettings.php:137 -#: actions/profilesettings.php:187 actions/recoverpassword.php:337 -#: actions/register.php:165 actions/remotesubscribe.php:77 -#: actions/smssettings.php:228 actions/subedit.php:38 actions/subscribe.php:46 -#: actions/tagother.php:166 actions/unblock.php:65 actions/unsubscribe.php:69 -#: actions/userauthorization.php:52 lib/designsettings.php:294 -msgid "There was a problem with your session token. Try again, please." +#: ../actions/emailsettings.php:280 ../actions/emailsettings.php:294 +#: actions/emailsettings.php:298 actions/emailsettings.php:312 +#: actions/emailsettings.php:440 actions/emailsettings.php:462 +#: actions/emailsettings.php:447 actions/emailsettings.php:469 +#: actions/smssettings.php:515 actions/smssettings.php:539 +#: actions/smssettings.php:516 actions/smssettings.php:540 +#: actions/emailsettings.php:455 actions/emailsettings.php:477 +#: actions/smssettings.php:528 actions/smssettings.php:552 +msgid "Couldn't update user record." msgstr "" -#: actions/avatarsettings.php:277 actions/emailsettings.php:255 -#: actions/grouplogo.php:319 actions/imsettings.php:220 -#: actions/recoverpassword.php:44 actions/smssettings.php:248 -#: lib/designsettings.php:304 -msgid "Unexpected form submission." +#: ../actions/confirmaddress.php:72 ../actions/emailsettings.php:156 +#: ../actions/emailsettings.php:259 ../actions/imsettings.php:138 +#: ../actions/imsettings.php:243 ../actions/profilesettings.php:141 +#: ../actions/smssettings.php:157 ../actions/smssettings.php:269 +#: actions/confirmaddress.php:72 actions/emailsettings.php:174 +#: actions/emailsettings.php:277 actions/imsettings.php:146 +#: actions/imsettings.php:251 actions/profilesettings.php:256 +#: actions/smssettings.php:165 actions/smssettings.php:277 +#: actions/confirmaddress.php:114 actions/emailsettings.php:280 +#: actions/emailsettings.php:411 actions/imsettings.php:252 +#: actions/imsettings.php:395 actions/othersettings.php:162 +#: actions/profilesettings.php:259 actions/smssettings.php:266 +#: actions/smssettings.php:408 actions/emailsettings.php:287 +#: actions/emailsettings.php:418 actions/othersettings.php:167 +#: actions/profilesettings.php:260 actions/emailsettings.php:295 +#: actions/emailsettings.php:426 actions/imsettings.php:258 +#: actions/imsettings.php:401 actions/othersettings.php:174 +#: actions/profilesettings.php:276 actions/smssettings.php:278 +#: actions/smssettings.php:420 +msgid "Couldn't update user." msgstr "" -#: actions/avatarsettings.php:322 -msgid "Pick a square area of the image to be your avatar" +#: ../actions/finishopenidlogin.php:84 actions/finishopenidlogin.php:90 +#: actions/finishopenidlogin.php:112 actions/finishopenidlogin.php:111 +msgid "Create" msgstr "" -#: actions/avatarsettings.php:337 actions/grouplogo.php:377 -msgid "Lost our file data." +#: ../actions/finishopenidlogin.php:70 actions/finishopenidlogin.php:76 +#: actions/finishopenidlogin.php:98 actions/finishopenidlogin.php:97 +msgid "Create a new user with this nickname." msgstr "" -#: actions/avatarsettings.php:360 -msgid "Avatar updated." +#: ../actions/finishopenidlogin.php:68 actions/finishopenidlogin.php:74 +#: actions/finishopenidlogin.php:96 actions/finishopenidlogin.php:95 +msgid "Create new account" msgstr "" -#: actions/avatarsettings.php:363 -msgid "Failed updating avatar." +#: ../actions/finishopenidlogin.php:191 actions/finishopenidlogin.php:197 +#: actions/finishopenidlogin.php:231 actions/finishopenidlogin.php:247 +msgid "Creating new account for OpenID that already has a user." msgstr "" -#: actions/avatarsettings.php:387 -msgid "Avatar deleted." +#: ../actions/imsettings.php:45 actions/imsettings.php:46 +#: actions/imsettings.php:100 actions/imsettings.php:106 +msgid "Current confirmed Jabber/GTalk address." msgstr "" -#: actions/blockedfromgroup.php:73 actions/editgroup.php:84 -#: actions/groupdesignsettings.php:84 actions/grouplogo.php:86 -#: actions/groupmembers.php:76 actions/grouprss.php:91 -#: actions/joingroup.php:76 actions/showgroup.php:121 -msgid "No nickname" +#: ../actions/smssettings.php:46 actions/smssettings.php:46 +#: actions/smssettings.php:100 actions/smssettings.php:112 +msgid "Current confirmed SMS-enabled phone number." msgstr "" -#: actions/blockedfromgroup.php:80 actions/editgroup.php:96 -#: actions/groupbyid.php:83 actions/groupdesignsettings.php:97 -#: actions/grouplogo.php:99 actions/groupmembers.php:83 -#: actions/grouprss.php:98 actions/joingroup.php:83 actions/showgroup.php:137 -msgid "No such group" +#: ../actions/emailsettings.php:44 actions/emailsettings.php:45 +#: actions/emailsettings.php:99 actions/emailsettings.php:105 +msgid "Current confirmed email address." msgstr "" -#: actions/blockedfromgroup.php:90 +#: ../classes/Notice.php:72 classes/Notice.php:86 classes/Notice.php:91 +#: classes/Notice.php:114 classes/Notice.php:124 classes/Notice.php:164 #, php-format -msgid "%s blocked profiles" +msgid "DB error inserting hashtag: %s" msgstr "" -#: actions/blockedfromgroup.php:93 +#: ../lib/util.php:1061 lib/util.php:1110 classes/Notice.php:698 +#: classes/Notice.php:757 classes/Notice.php:1042 classes/Notice.php:1117 +#: classes/Notice.php:1120 #, php-format -msgid "%s blocked profiles, page %d" +msgid "DB error inserting reply: %s" msgstr "" -#: actions/blockedfromgroup.php:108 -msgid "A list of the users blocked from joining this group." +#: ../actions/deletenotice.php:41 actions/deletenotice.php:41 +#: actions/deletenotice.php:79 actions/deletenotice.php:111 +#: actions/deletenotice.php:109 actions/deletenotice.php:141 +msgid "Delete notice" msgstr "" -#: actions/blockedfromgroup.php:281 -msgid "Unblock user from group" +#: ../actions/profilesettings.php:51 ../actions/register.php:172 +#: actions/profilesettings.php:84 actions/register.php:186 +#: actions/profilesettings.php:114 actions/register.php:404 +#: actions/register.php:450 +msgid "Describe yourself and your interests in 140 chars" msgstr "" -#: actions/blockedfromgroup.php:313 lib/unblockform.php:150 -msgid "Unblock" +#: ../actions/register.php:158 ../actions/register.php:161 +#: ../lib/settingsaction.php:87 actions/register.php:172 +#: actions/register.php:175 lib/settingsaction.php:87 actions/register.php:381 +#: actions/register.php:385 lib/accountsettingsaction.php:113 +#: actions/register.php:427 actions/register.php:431 actions/register.php:435 +#: lib/accountsettingsaction.php:117 actions/register.php:437 +#: actions/register.php:441 +msgid "Email" msgstr "" -#: actions/blockedfromgroup.php:313 lib/unblockform.php:120 -#: lib/unblockform.php:150 -msgid "Unblock this user" +#: ../actions/emailsettings.php:59 actions/emailsettings.php:60 +#: actions/emailsettings.php:115 actions/emailsettings.php:121 +msgid "Email Address" msgstr "" -#: actions/block.php:59 actions/deletenotice.php:67 actions/disfavor.php:61 -#: actions/favor.php:62 actions/groupblock.php:61 actions/groupunblock.php:61 -#: actions/logout.php:69 actions/makeadmin.php:61 actions/newmessage.php:87 -#: actions/newnotice.php:89 actions/nudge.php:63 actions/subedit.php:31 -#: actions/subscribe.php:30 actions/unblock.php:60 actions/unsubscribe.php:52 -#: lib/settingsaction.php:72 -msgid "Not logged in." +#: ../actions/emailsettings.php:32 actions/emailsettings.php:32 +#: actions/emailsettings.php:60 +msgid "Email Settings" msgstr "" -#: actions/block.php:69 actions/groupblock.php:71 actions/groupunblock.php:71 -#: actions/makeadmin.php:71 actions/subedit.php:46 actions/unblock.php:70 -msgid "No profile specified." +#: ../actions/register.php:73 actions/register.php:80 actions/register.php:163 +#: actions/register.php:200 actions/register.php:206 actions/register.php:212 +msgid "Email address already exists." msgstr "" -#: actions/block.php:74 actions/groupblock.php:76 actions/groupunblock.php:76 -#: actions/makeadmin.php:76 actions/subedit.php:53 actions/tagother.php:46 -#: actions/unblock.php:75 -msgid "No profile with that ID." +#: ../lib/mail.php:90 lib/mail.php:90 lib/mail.php:173 lib/mail.php:172 +msgid "Email address confirmation" msgstr "" -#: actions/block.php:111 actions/block.php:134 -msgid "Block user" +#: ../actions/emailsettings.php:61 actions/emailsettings.php:62 +#: actions/emailsettings.php:117 actions/emailsettings.php:123 +msgid "Email address, like \"UserName@example.org\"" msgstr "" -#: actions/block.php:136 -msgid "" -"Are you sure you want to block this user? Afterwards, they will be " -"unsubscribed from you, unable to subscribe to you in the future, and you " -"will not be notified of any @-replies from them." +#: ../actions/invite.php:129 actions/invite.php:137 actions/invite.php:174 +#: actions/invite.php:179 actions/invite.php:181 actions/invite.php:187 +msgid "Email addresses" msgstr "" -#: actions/block.php:149 actions/deletenotice.php:145 -#: actions/groupblock.php:176 -msgid "No" +#: ../actions/recoverpassword.php:191 actions/recoverpassword.php:197 +#: actions/recoverpassword.php:231 actions/recoverpassword.php:249 +#: actions/recoverpassword.php:252 +msgid "Enter a nickname or email address." msgstr "" -#: actions/block.php:149 -msgid "Do not block this user from this group" +#: ../actions/smssettings.php:64 actions/smssettings.php:64 +#: actions/smssettings.php:119 actions/smssettings.php:131 +msgid "Enter the code you received on your phone." msgstr "" -#: actions/block.php:150 actions/deletenotice.php:146 -#: actions/groupblock.php:177 -msgid "Yes" +#: ../actions/userauthorization.php:137 actions/userauthorization.php:144 +#: actions/userauthorization.php:161 actions/userauthorization.php:200 +msgid "Error authorizing token" msgstr "" -#: actions/block.php:150 -msgid "Block this user from this group" +#: ../actions/finishopenidlogin.php:253 actions/finishopenidlogin.php:259 +#: actions/finishopenidlogin.php:297 actions/finishopenidlogin.php:302 +#: actions/finishopenidlogin.php:325 +msgid "Error connecting user to OpenID." msgstr "" -#: actions/block.php:165 -msgid "You have already blocked this user." +#: ../actions/finishaddopenid.php:78 actions/finishaddopenid.php:78 +#: actions/finishaddopenid.php:126 +msgid "Error connecting user." msgstr "" -#: actions/block.php:170 -msgid "Failed to save block information." +#: ../actions/finishremotesubscribe.php:151 +#: actions/finishremotesubscribe.php:153 actions/finishremotesubscribe.php:166 +#: lib/oauthstore.php:291 +msgid "Error inserting avatar" msgstr "" -#: actions/bookmarklet.php:50 -msgid "Post to " +#: ../actions/finishremotesubscribe.php:143 +#: actions/finishremotesubscribe.php:145 actions/finishremotesubscribe.php:158 +#: lib/oauthstore.php:283 +msgid "Error inserting new profile" msgstr "" -#: actions/confirmaddress.php:75 -msgid "No confirmation code." +#: ../actions/finishremotesubscribe.php:167 +#: actions/finishremotesubscribe.php:169 actions/finishremotesubscribe.php:182 +#: lib/oauthstore.php:311 +msgid "Error inserting remote profile" msgstr "" -#: actions/confirmaddress.php:80 -msgid "Confirmation code not found." +#: ../actions/recoverpassword.php:240 actions/recoverpassword.php:246 +#: actions/recoverpassword.php:280 actions/recoverpassword.php:298 +#: actions/recoverpassword.php:301 +msgid "Error saving address confirmation." msgstr "" -#: actions/confirmaddress.php:85 -msgid "That confirmation code is not for you!" +#: ../actions/userauthorization.php:140 actions/userauthorization.php:147 +#: actions/userauthorization.php:164 actions/userauthorization.php:203 +msgid "Error saving remote profile" msgstr "" -#: actions/confirmaddress.php:90 -#, php-format -msgid "Unrecognized address type %s" +#: ../lib/openid.php:226 lib/openid.php:226 lib/openid.php:235 +#: lib/openid.php:238 +msgid "Error saving the profile." msgstr "" -#: actions/confirmaddress.php:94 -msgid "That address has already been confirmed." +#: ../lib/openid.php:237 lib/openid.php:237 lib/openid.php:246 +#: lib/openid.php:249 +msgid "Error saving the user." msgstr "" -#: actions/confirmaddress.php:114 actions/emailsettings.php:295 -#: actions/emailsettings.php:426 actions/imsettings.php:258 -#: actions/imsettings.php:401 actions/othersettings.php:174 -#: actions/profilesettings.php:276 actions/smssettings.php:278 -#: actions/smssettings.php:420 -msgid "Couldn't update user." +#: ../actions/password.php:80 actions/profilesettings.php:399 +#: actions/passwordsettings.php:164 actions/passwordsettings.php:169 +#: actions/passwordsettings.php:175 actions/passwordsettings.php:180 +msgid "Error saving user; invalid." msgstr "" -#: actions/confirmaddress.php:126 actions/emailsettings.php:390 -#: actions/imsettings.php:363 actions/smssettings.php:382 -msgid "Couldn't delete email confirmation." +#: ../actions/login.php:47 ../actions/login.php:73 +#: ../actions/recoverpassword.php:307 ../actions/register.php:98 +#: actions/login.php:47 actions/login.php:73 actions/recoverpassword.php:320 +#: actions/register.php:108 actions/login.php:112 actions/login.php:138 +#: actions/recoverpassword.php:354 actions/register.php:198 +#: actions/login.php:120 actions/recoverpassword.php:372 +#: actions/register.php:235 actions/login.php:122 +#: actions/recoverpassword.php:375 actions/register.php:242 +#: actions/login.php:149 actions/register.php:248 +msgid "Error setting user." msgstr "" -#: actions/confirmaddress.php:144 -msgid "Confirm Address" +#: ../actions/finishaddopenid.php:83 actions/finishaddopenid.php:83 +#: actions/finishaddopenid.php:131 +msgid "Error updating profile" msgstr "" -#: actions/confirmaddress.php:159 -#, php-format -msgid "The address \"%s\" has been confirmed for your account." +#: ../actions/finishremotesubscribe.php:161 +#: actions/finishremotesubscribe.php:163 actions/finishremotesubscribe.php:176 +#: actions/finishremotesubscribe.php:133 lib/oauthstore.php:306 +msgid "Error updating remote profile" msgstr "" -#: actions/conversation.php:99 -msgid "Conversation" +#: ../actions/recoverpassword.php:80 actions/recoverpassword.php:80 +#: actions/recoverpassword.php:86 +msgid "Error with confirmation code." msgstr "" -#: actions/conversation.php:154 lib/mailbox.php:116 lib/noticelist.php:87 -#: lib/profileaction.php:206 -msgid "Notices" +#: ../actions/finishopenidlogin.php:89 actions/finishopenidlogin.php:95 +#: actions/finishopenidlogin.php:117 actions/finishopenidlogin.php:116 +msgid "Existing nickname" msgstr "" -#: actions/deletenotice.php:52 actions/shownotice.php:92 -msgid "No such notice." +#: ../lib/util.php:326 lib/util.php:342 lib/action.php:570 lib/action.php:663 +#: lib/action.php:708 lib/action.php:723 +msgid "FAQ" msgstr "" -#: actions/deletenotice.php:71 -msgid "Can't delete this notice." +#: ../actions/avatar.php:115 actions/profilesettings.php:352 +#: actions/avatarsettings.php:397 actions/avatarsettings.php:349 +#: actions/avatarsettings.php:363 +msgid "Failed updating avatar." msgstr "" -#: actions/deletenotice.php:103 -msgid "" -"You are about to permanently delete a notice. Once this is done, it cannot " -"be undone." +#: ../actions/all.php:61 ../actions/allrss.php:64 actions/all.php:61 +#: actions/allrss.php:64 actions/all.php:75 actions/allrss.php:107 +#: actions/allrss.php:110 actions/allrss.php:118 +#, php-format +msgid "Feed for friends of %s" msgstr "" -#: actions/deletenotice.php:109 actions/deletenotice.php:141 -msgid "Delete notice" +#: ../actions/replies.php:65 ../actions/repliesrss.php:80 +#: actions/replies.php:65 actions/repliesrss.php:66 actions/replies.php:134 +#: actions/repliesrss.php:71 actions/replies.php:136 actions/replies.php:135 +#, php-format +msgid "Feed for replies to %s" msgstr "" -#: actions/deletenotice.php:144 -msgid "Are you sure you want to delete this notice?" +#: ../actions/tag.php:55 actions/tag.php:55 actions/tag.php:61 +#: actions/tag.php:68 +#, php-format +msgid "Feed for tag %s" msgstr "" -#: actions/deletenotice.php:145 -msgid "Do not delete this notice" +#: ../lib/searchaction.php:105 lib/searchaction.php:105 +#: lib/searchgroupnav.php:83 +msgid "Find content of notices" msgstr "" -#: actions/deletenotice.php:146 lib/noticelist.php:522 -msgid "Delete this notice" +#: ../lib/searchaction.php:101 lib/searchaction.php:101 +#: lib/searchgroupnav.php:81 +msgid "Find people on this site" msgstr "" -#: actions/deletenotice.php:157 -msgid "There was a problem with your session token. Try again, please." +#: ../actions/login.php:122 actions/login.php:247 actions/login.php:255 +#: actions/login.php:282 +msgid "" +"For security reasons, please re-enter your user name and password before " +"changing your settings." msgstr "" -#: actions/disfavor.php:81 -msgid "This notice is not a favorite!" +#: ../actions/profilesettings.php:44 ../actions/register.php:164 +#: actions/profilesettings.php:77 actions/register.php:178 +#: actions/profilesettings.php:103 actions/register.php:391 +#: actions/showgroup.php:235 actions/showstream.php:262 +#: actions/tagother.php:105 lib/groupeditform.php:142 +#: actions/showgroup.php:237 actions/showstream.php:255 +#: actions/tagother.php:104 actions/register.php:437 actions/showgroup.php:242 +#: actions/showstream.php:220 lib/groupeditform.php:157 +#: actions/profilesettings.php:111 actions/register.php:441 +#: actions/showgroup.php:247 actions/showstream.php:267 +#: actions/register.php:447 lib/userprofile.php:149 +msgid "Full name" msgstr "" -#: actions/disfavor.php:94 -msgid "Add to favorites" +#: ../actions/profilesettings.php:98 ../actions/register.php:79 +#: ../actions/updateprofile.php:93 actions/profilesettings.php:213 +#: actions/register.php:86 actions/updateprofile.php:94 +#: actions/editgroup.php:195 actions/newgroup.php:146 +#: actions/profilesettings.php:202 actions/register.php:171 +#: actions/updateprofile.php:97 actions/updateprofile.php:99 +#: actions/editgroup.php:197 actions/newgroup.php:147 +#: actions/profilesettings.php:203 actions/register.php:208 +#: actions/apigroupcreate.php:253 actions/editgroup.php:198 +#: actions/newgroup.php:142 actions/profilesettings.php:218 +#: actions/register.php:214 actions/register.php:220 +msgid "Full name is too long (max 255 chars)." msgstr "" -#: actions/doc.php:69 -msgid "No such document." +#: ../lib/util.php:322 lib/util.php:338 lib/action.php:344 lib/action.php:566 +#: lib/action.php:421 lib/action.php:659 lib/action.php:446 lib/action.php:704 +#: lib/action.php:456 lib/action.php:719 +msgid "Help" msgstr "" -#: actions/editgroup.php:56 -#, php-format -msgid "Edit %s group" +#: ../lib/util.php:298 lib/util.php:314 lib/action.php:322 +#: lib/facebookaction.php:200 lib/action.php:393 lib/facebookaction.php:213 +#: lib/action.php:417 lib/action.php:430 +msgid "Home" msgstr "" -#: actions/editgroup.php:68 actions/grouplogo.php:70 actions/newgroup.php:65 -msgid "You must be logged in to create a group." +#: ../actions/profilesettings.php:46 ../actions/register.php:167 +#: actions/profilesettings.php:79 actions/register.php:181 +#: actions/profilesettings.php:107 actions/register.php:396 +#: lib/groupeditform.php:146 actions/register.php:442 +#: lib/groupeditform.php:161 actions/profilesettings.php:115 +#: actions/register.php:446 actions/register.php:452 +msgid "Homepage" msgstr "" -#: actions/editgroup.php:103 actions/editgroup.php:168 -#: actions/groupdesignsettings.php:104 actions/grouplogo.php:106 -msgid "You must be an admin to edit the group" +#: ../actions/profilesettings.php:95 ../actions/register.php:76 +#: actions/profilesettings.php:210 actions/register.php:83 +#: actions/editgroup.php:192 actions/newgroup.php:143 +#: actions/profilesettings.php:199 actions/register.php:168 +#: actions/editgroup.php:194 actions/newgroup.php:144 +#: actions/profilesettings.php:200 actions/register.php:205 +#: actions/apigroupcreate.php:244 actions/editgroup.php:195 +#: actions/newgroup.php:139 actions/profilesettings.php:215 +#: actions/register.php:211 actions/register.php:217 +msgid "Homepage is not a valid URL." msgstr "" -#: actions/editgroup.php:154 -msgid "Use this form to edit the group." +#: ../actions/emailsettings.php:91 actions/emailsettings.php:98 +#: actions/emailsettings.php:173 actions/emailsettings.php:178 +#: actions/emailsettings.php:185 +msgid "I want to post notices by email." msgstr "" -#: actions/editgroup.php:201 actions/newgroup.php:145 -#, php-format -msgid "description is too long (max %d chars)." +#: ../lib/settingsaction.php:102 lib/settingsaction.php:96 +#: lib/connectsettingsaction.php:104 lib/connectsettingsaction.php:110 +msgid "IM" msgstr "" -#: actions/editgroup.php:253 -msgid "Could not update group." +#: ../actions/imsettings.php:60 actions/imsettings.php:61 +#: actions/imsettings.php:118 actions/imsettings.php:124 +msgid "IM Address" msgstr "" -#: actions/editgroup.php:269 -msgid "Options saved." +#: ../actions/imsettings.php:33 actions/imsettings.php:33 +#: actions/imsettings.php:59 +msgid "IM Settings" msgstr "" -#: actions/emailsettings.php:60 -msgid "Email Settings" +#: ../actions/finishopenidlogin.php:88 actions/finishopenidlogin.php:94 +#: actions/finishopenidlogin.php:116 actions/finishopenidlogin.php:115 +msgid "" +"If you already have an account, login with your username and password to " +"connect it to your OpenID." msgstr "" -#: actions/emailsettings.php:71 -#, php-format -msgid "Manage how you get email from %%site.name%%." +#: ../actions/openidsettings.php:45 actions/openidsettings.php:96 +msgid "" +"If you want to add an OpenID to your account, enter it in the box below and " +"click \"Add\"." msgstr "" -#: actions/emailsettings.php:100 -msgid "Address" +#: ../actions/emailsettings.php:67 ../actions/smssettings.php:76 +#: actions/emailsettings.php:68 actions/smssettings.php:76 +#: actions/emailsettings.php:127 actions/smssettings.php:140 +#: actions/emailsettings.php:133 actions/smssettings.php:152 +msgid "Incoming email" msgstr "" -#: actions/emailsettings.php:105 -msgid "Current confirmed email address." +#: ../actions/emailsettings.php:283 actions/emailsettings.php:301 +#: actions/emailsettings.php:443 actions/emailsettings.php:450 +#: actions/smssettings.php:518 actions/smssettings.php:519 +#: actions/emailsettings.php:458 actions/smssettings.php:531 +msgid "Incoming email address removed." msgstr "" -#: actions/emailsettings.php:107 actions/emailsettings.php:140 -#: actions/imsettings.php:108 actions/smssettings.php:115 -#: actions/smssettings.php:158 -msgid "Remove" +#: ../actions/password.php:69 actions/profilesettings.php:388 +#: actions/passwordsettings.php:153 actions/passwordsettings.php:158 +#: actions/passwordsettings.php:164 +msgid "Incorrect old password" +msgstr "" + +#: ../actions/login.php:67 actions/login.php:67 actions/facebookhome.php:131 +#: actions/login.php:132 actions/facebookhome.php:130 actions/login.php:114 +#: actions/facebookhome.php:129 actions/login.php:116 actions/login.php:143 +msgid "Incorrect username or password." msgstr "" -#: actions/emailsettings.php:113 +#: ../actions/recoverpassword.php:265 actions/recoverpassword.php:304 +#: actions/recoverpassword.php:322 actions/recoverpassword.php:325 msgid "" -"Awaiting confirmation on this address. Check your inbox (and spam box!) for " -"a message with further instructions." +"Instructions for recovering your password have been sent to the email " +"address registered to your account." msgstr "" -#: actions/emailsettings.php:117 actions/imsettings.php:120 -#: actions/smssettings.php:126 -msgid "Cancel" +#: ../actions/updateprofile.php:114 actions/updateprofile.php:115 +#: actions/updateprofile.php:118 actions/updateprofile.php:120 +#, php-format +msgid "Invalid avatar URL '%s'" msgstr "" -#: actions/emailsettings.php:121 -msgid "Email Address" +#: ../actions/invite.php:55 actions/invite.php:62 actions/invite.php:70 +#: actions/invite.php:72 +#, php-format +msgid "Invalid email address: %s" msgstr "" -#: actions/emailsettings.php:123 -msgid "Email address, like \"UserName@example.org\"" +#: ../actions/updateprofile.php:98 actions/updateprofile.php:99 +#: actions/updateprofile.php:102 actions/updateprofile.php:104 +#, php-format +msgid "Invalid homepage '%s'" msgstr "" -#: actions/emailsettings.php:126 actions/imsettings.php:133 -#: actions/smssettings.php:145 -msgid "Add" +#: ../actions/updateprofile.php:82 actions/updateprofile.php:83 +#: actions/updateprofile.php:86 actions/updateprofile.php:88 +#, php-format +msgid "Invalid license URL '%s'" msgstr "" -#: actions/emailsettings.php:133 actions/smssettings.php:152 -msgid "Incoming email" +#: ../actions/postnotice.php:61 actions/postnotice.php:62 +#: actions/postnotice.php:66 actions/postnotice.php:84 +msgid "Invalid notice content" msgstr "" -#: actions/emailsettings.php:138 actions/smssettings.php:157 -msgid "Send email to this address to post new notices." +#: ../actions/postnotice.php:67 actions/postnotice.php:68 +#: actions/postnotice.php:72 +msgid "Invalid notice uri" msgstr "" -#: actions/emailsettings.php:145 actions/smssettings.php:162 -msgid "Make a new email address for posting to; cancels the old one." +#: ../actions/postnotice.php:72 actions/postnotice.php:73 +#: actions/postnotice.php:77 +msgid "Invalid notice url" msgstr "" -#: actions/emailsettings.php:148 actions/smssettings.php:164 -msgid "New" +#: ../actions/updateprofile.php:87 actions/updateprofile.php:88 +#: actions/updateprofile.php:91 actions/updateprofile.php:93 +#, php-format +msgid "Invalid profile URL '%s'." msgstr "" -#: actions/emailsettings.php:153 actions/imsettings.php:139 -#: actions/smssettings.php:169 -msgid "Preferences" +#: ../actions/remotesubscribe.php:96 actions/remotesubscribe.php:105 +#: actions/remotesubscribe.php:135 actions/remotesubscribe.php:159 +msgid "Invalid profile URL (bad format)" msgstr "" -#: actions/emailsettings.php:158 -msgid "Send me notices of new subscriptions through email." +#: ../actions/finishremotesubscribe.php:77 +#: actions/finishremotesubscribe.php:79 actions/finishremotesubscribe.php:80 +msgid "Invalid profile URL returned by server." msgstr "" -#: actions/emailsettings.php:163 -msgid "Send me email when someone adds my notice as a favorite." +#: ../actions/avatarbynickname.php:37 actions/avatarbynickname.php:37 +#: actions/avatarbynickname.php:69 +msgid "Invalid size." msgstr "" -#: actions/emailsettings.php:169 -msgid "Send me email when someone sends me a private message." +#: ../actions/finishopenidlogin.php:235 ../actions/register.php:93 +#: ../actions/register.php:111 actions/finishopenidlogin.php:241 +#: actions/register.php:103 actions/register.php:121 +#: actions/finishopenidlogin.php:279 actions/register.php:193 +#: actions/register.php:211 actions/finishopenidlogin.php:284 +#: actions/finishopenidlogin.php:307 actions/register.php:230 +#: actions/register.php:251 actions/register.php:237 actions/register.php:258 +#: actions/register.php:243 actions/register.php:264 +msgid "Invalid username or password." msgstr "" -#: actions/emailsettings.php:174 -msgid "Send me email when someone sends me an \"@-reply\"." +#: ../actions/invite.php:79 actions/invite.php:86 actions/invite.php:102 +#: actions/invite.php:104 actions/invite.php:110 +msgid "Invitation(s) sent" msgstr "" -#: actions/emailsettings.php:179 -msgid "Allow friends to nudge me and send me an email." +#: ../actions/invite.php:97 actions/invite.php:104 actions/invite.php:136 +#: actions/invite.php:138 actions/invite.php:144 +msgid "Invitation(s) sent to the following people:" msgstr "" -#: actions/emailsettings.php:185 -msgid "I want to post notices by email." +#: ../lib/util.php:306 lib/util.php:322 lib/facebookaction.php:207 +#: lib/subgroupnav.php:103 lib/facebookaction.php:220 lib/action.php:429 +#: lib/facebookaction.php:221 lib/subgroupnav.php:105 lib/action.php:439 +msgid "Invite" msgstr "" -#: actions/emailsettings.php:191 -msgid "Publish a MicroID for my email address." +#: ../actions/invite.php:123 actions/invite.php:130 actions/invite.php:104 +#: actions/invite.php:106 actions/invite.php:112 +msgid "Invite new users" msgstr "" -#: actions/emailsettings.php:195 actions/imsettings.php:163 -#: actions/othersettings.php:126 actions/profilesettings.php:167 -#: actions/smssettings.php:181 actions/subscriptions.php:203 -#: actions/tagother.php:154 lib/designsettings.php:256 -#: lib/groupeditform.php:202 -msgid "Save" +#: ../lib/util.php:261 lib/util.php:277 lib/action.php:609 lib/action.php:706 +#: lib/action.php:756 lib/action.php:771 +#, php-format +msgid "" +"It runs the [StatusNet](http://status.net/) microblogging software, version %" +"s, available under the [GNU Affero General Public License](http://www.fsf." +"org/licensing/licenses/agpl-3.0.html)." msgstr "" -#: actions/emailsettings.php:301 actions/imsettings.php:264 -#: actions/othersettings.php:180 actions/smssettings.php:284 -msgid "Preferences saved." +#: ../actions/imsettings.php:173 actions/imsettings.php:181 +#: actions/imsettings.php:296 actions/imsettings.php:302 +msgid "Jabber ID already belongs to another user." msgstr "" -#: actions/emailsettings.php:319 -msgid "No email address." +#: ../actions/imsettings.php:62 actions/imsettings.php:63 +#: actions/imsettings.php:120 actions/imsettings.php:126 +#, php-format +msgid "" +"Jabber or GTalk address, like \"UserName@example.org\". First, make sure to " +"add %s to your buddy list in your IM client or on GTalk." msgstr "" -#: actions/emailsettings.php:326 -msgid "Cannot normalize that email address" +#: ../actions/profilesettings.php:57 actions/profilesettings.php:90 +#: actions/profilesettings.php:128 actions/profilesettings.php:129 +#: actions/profilesettings.php:144 +msgid "Language" msgstr "" -#: actions/emailsettings.php:330 -msgid "Not a valid email address" +#: ../actions/profilesettings.php:113 actions/profilesettings.php:228 +#: actions/profilesettings.php:217 actions/profilesettings.php:218 +#: actions/profilesettings.php:234 +msgid "Language is too long (max 50 chars)." msgstr "" -#: actions/emailsettings.php:333 -msgid "That is already your email address." +#: ../actions/profilesettings.php:52 ../actions/register.php:173 +#: actions/profilesettings.php:85 actions/register.php:187 +#: actions/profilesettings.php:117 actions/register.php:408 +#: actions/showgroup.php:244 actions/showstream.php:271 +#: actions/tagother.php:113 lib/groupeditform.php:156 lib/grouplist.php:126 +#: lib/profilelist.php:125 actions/showgroup.php:246 +#: actions/showstream.php:264 actions/tagother.php:112 lib/profilelist.php:123 +#: actions/register.php:454 actions/showgroup.php:251 +#: actions/showstream.php:229 actions/userauthorization.php:128 +#: lib/groupeditform.php:171 lib/profilelist.php:185 +#: actions/profilesettings.php:132 actions/register.php:464 +#: actions/showgroup.php:256 actions/showstream.php:282 +#: actions/userauthorization.php:158 lib/groupeditform.php:177 +#: lib/profilelist.php:218 actions/register.php:470 lib/userprofile.php:164 +msgid "Location" msgstr "" -#: actions/emailsettings.php:336 -msgid "That email address already belongs to another user." +#: ../actions/profilesettings.php:104 ../actions/register.php:85 +#: ../actions/updateprofile.php:108 actions/profilesettings.php:219 +#: actions/register.php:92 actions/updateprofile.php:109 +#: actions/editgroup.php:201 actions/newgroup.php:152 +#: actions/profilesettings.php:208 actions/register.php:177 +#: actions/updateprofile.php:112 actions/updateprofile.php:114 +#: actions/editgroup.php:203 actions/newgroup.php:153 +#: actions/profilesettings.php:209 actions/register.php:214 +#: actions/apigroupcreate.php:272 actions/editgroup.php:204 +#: actions/newgroup.php:148 actions/profilesettings.php:225 +#: actions/register.php:221 actions/register.php:227 +msgid "Location is too long (max 255 chars)." msgstr "" -#: actions/emailsettings.php:352 actions/imsettings.php:317 -#: actions/smssettings.php:337 -msgid "Couldn't insert confirmation code." +#: ../actions/login.php:97 ../actions/login.php:106 +#: ../actions/openidlogin.php:68 ../lib/util.php:310 actions/login.php:97 +#: actions/login.php:106 actions/openidlogin.php:77 lib/util.php:326 +#: actions/facebooklogin.php:93 actions/login.php:186 actions/login.php:239 +#: actions/openidlogin.php:112 lib/action.php:335 lib/facebookaction.php:288 +#: lib/facebookaction.php:315 lib/logingroupnav.php:75 actions/login.php:169 +#: actions/login.php:222 actions/openidlogin.php:121 lib/action.php:412 +#: lib/facebookaction.php:293 lib/facebookaction.php:319 lib/action.php:443 +#: lib/facebookaction.php:295 lib/facebookaction.php:321 actions/login.php:177 +#: actions/login.php:230 lib/action.php:453 lib/logingroupnav.php:79 +#: actions/login.php:204 actions/login.php:257 +#, php-format +msgid "Login" +msgstr "" + +#: ../actions/openidlogin.php:44 actions/openidlogin.php:52 +#: actions/openidlogin.php:62 actions/openidlogin.php:70 +#, php-format +msgid "Login with an [OpenID](%%doc.openid%%) account." msgstr "" -#: actions/emailsettings.php:358 +#: ../actions/login.php:126 actions/login.php:251 +#, php-format msgid "" -"A confirmation code was sent to the email address you added. Check your " -"inbox (and spam box!) for the code and instructions on how to use it." +"Login with your username and password. Don't have a username yet? [Register]" +"(%%action.register%%) a new account, or try [OpenID](%%action.openidlogin%" +"%). " msgstr "" -#: actions/emailsettings.php:378 actions/imsettings.php:351 -#: actions/smssettings.php:370 -msgid "No pending confirmation to cancel." +#: ../lib/util.php:308 lib/util.php:324 lib/action.php:332 lib/action.php:409 +#: lib/action.php:435 lib/action.php:445 +msgid "Logout" msgstr "" -#: actions/emailsettings.php:382 actions/imsettings.php:355 -msgid "That is the wrong IM address." +#: ../actions/register.php:166 actions/register.php:180 +#: actions/register.php:393 actions/register.php:439 actions/register.php:443 +#: actions/register.php:449 +msgid "Longer name, preferably your \"real\" name" msgstr "" -#: actions/emailsettings.php:394 actions/imsettings.php:367 -#: actions/smssettings.php:386 -msgid "Confirmation cancelled." +#: ../actions/login.php:110 actions/login.php:110 actions/login.php:245 +#: lib/facebookaction.php:320 actions/login.php:228 lib/facebookaction.php:325 +#: lib/facebookaction.php:327 actions/login.php:236 actions/login.php:263 +msgid "Lost or forgotten password?" msgstr "" -#: actions/emailsettings.php:412 -msgid "That is not your email address." +#: ../actions/emailsettings.php:80 ../actions/smssettings.php:89 +#: actions/emailsettings.php:81 actions/smssettings.php:89 +#: actions/emailsettings.php:139 actions/smssettings.php:150 +#: actions/emailsettings.php:145 actions/smssettings.php:162 +msgid "Make a new email address for posting to; cancels the old one." msgstr "" -#: actions/emailsettings.php:431 actions/imsettings.php:408 -#: actions/smssettings.php:425 -msgid "The address was removed." +#: ../actions/emailsettings.php:27 actions/emailsettings.php:27 +#: actions/emailsettings.php:71 +#, php-format +msgid "Manage how you get email from %%site.name%%." msgstr "" -#: actions/emailsettings.php:445 actions/smssettings.php:518 -msgid "No incoming email address." +#: ../actions/showstream.php:300 actions/showstream.php:315 +#: actions/showstream.php:480 lib/profileaction.php:182 +msgid "Member since" msgstr "" -#: actions/emailsettings.php:455 actions/emailsettings.php:477 -#: actions/smssettings.php:528 actions/smssettings.php:552 -msgid "Couldn't update user record." +#: ../actions/userrss.php:70 actions/userrss.php:67 actions/userrss.php:72 +#: actions/userrss.php:93 +#, php-format +msgid "Microblog by %s" msgstr "" -#: actions/emailsettings.php:458 actions/smssettings.php:531 -msgid "Incoming email address removed." +#: ../actions/smssettings.php:304 actions/smssettings.php:464 +#: actions/smssettings.php:476 +#, php-format +msgid "" +"Mobile carrier for your phone. If you know a carrier that accepts SMS over " +"email but isn't listed here, send email to let us know at %s." msgstr "" -#: actions/emailsettings.php:480 actions/smssettings.php:555 -msgid "New incoming email address added." +#: ../actions/finishopenidlogin.php:79 ../actions/register.php:188 +#: actions/finishopenidlogin.php:85 actions/register.php:202 +#: actions/finishopenidlogin.php:107 actions/register.php:429 +#: actions/register.php:430 actions/finishopenidlogin.php:106 +#: actions/register.php:477 actions/register.php:487 actions/register.php:493 +msgid "My text and files are available under " msgstr "" -#: actions/favorited.php:65 lib/popularnoticesection.php:87 -#: lib/publicgroupnav.php:93 -msgid "Popular notices" +#: ../actions/emailsettings.php:82 ../actions/smssettings.php:91 +#: actions/emailsettings.php:83 actions/smssettings.php:91 +#: actions/emailsettings.php:142 actions/smssettings.php:152 +#: actions/emailsettings.php:148 actions/smssettings.php:164 +msgid "New" msgstr "" -#: actions/favorited.php:67 +#: ../lib/mail.php:144 lib/mail.php:144 lib/mail.php:286 lib/mail.php:285 #, php-format -msgid "Popular notices, page %d" +msgid "New email address for posting to %s" msgstr "" -#: actions/favorited.php:79 -msgid "The most popular notices on the site right now." +#: ../actions/emailsettings.php:297 actions/emailsettings.php:315 +#: actions/emailsettings.php:465 actions/emailsettings.php:472 +#: actions/smssettings.php:542 actions/smssettings.php:543 +#: actions/emailsettings.php:480 actions/smssettings.php:555 +msgid "New incoming email address added." msgstr "" -#: actions/favorited.php:150 -msgid "Favorite notices appear on this page but no one has favorited one yet." +#: ../actions/finishopenidlogin.php:71 actions/finishopenidlogin.php:77 +#: actions/finishopenidlogin.php:99 actions/finishopenidlogin.php:98 +msgid "New nickname" msgstr "" -#: actions/favorited.php:153 -msgid "" -"Be the first to add a notice to your favorites by clicking the fave button " -"next to any notice you like." +#: ../actions/newnotice.php:87 actions/newnotice.php:96 +#: actions/newnotice.php:68 actions/newnotice.php:69 +msgid "New notice" msgstr "" -#: actions/favorited.php:156 -#, php-format -msgid "" -"Why not [register an account](%%action.register%%) and be the first to add a " -"notice to your favorites!" +#: ../actions/password.php:41 ../actions/recoverpassword.php:179 +#: actions/profilesettings.php:180 actions/recoverpassword.php:185 +#: actions/passwordsettings.php:101 actions/recoverpassword.php:219 +#: actions/recoverpassword.php:232 actions/passwordsettings.php:107 +#: actions/recoverpassword.php:235 +msgid "New password" msgstr "" -#: actions/favoritesrss.php:111 actions/showfavorites.php:77 -#: lib/personalgroupnav.php:115 -#, php-format -msgid "%s's favorite notices" +#: ../actions/recoverpassword.php:314 actions/recoverpassword.php:361 +#: actions/recoverpassword.php:379 actions/recoverpassword.php:382 +msgid "New password successfully saved. You are now logged in." msgstr "" -#: actions/favoritesrss.php:115 -#, php-format -msgid "Updates favored by %1$s on %2$s!" +#: ../actions/login.php:101 ../actions/profilesettings.php:41 +#: ../actions/register.php:151 actions/login.php:101 +#: actions/profilesettings.php:74 actions/register.php:165 +#: actions/login.php:228 actions/profilesettings.php:98 +#: actions/register.php:367 actions/showgroup.php:224 +#: actions/showstream.php:251 actions/tagother.php:95 +#: lib/facebookaction.php:308 lib/groupeditform.php:137 actions/login.php:211 +#: actions/showgroup.php:226 actions/showstream.php:244 +#: actions/tagother.php:94 lib/facebookaction.php:312 actions/register.php:413 +#: actions/showgroup.php:231 actions/showstream.php:209 +#: lib/facebookaction.php:314 lib/groupeditform.php:152 actions/login.php:219 +#: actions/profilesettings.php:106 actions/register.php:417 +#: actions/showgroup.php:236 actions/showstream.php:249 actions/login.php:246 +#: actions/register.php:423 lib/userprofile.php:131 +msgid "Nickname" msgstr "" -#: actions/favor.php:79 -msgid "This notice is already a favorite!" +#: ../actions/finishopenidlogin.php:175 ../actions/profilesettings.php:110 +#: ../actions/register.php:69 actions/finishopenidlogin.php:181 +#: actions/profilesettings.php:225 actions/register.php:76 +#: actions/editgroup.php:183 actions/finishopenidlogin.php:215 +#: actions/newgroup.php:134 actions/profilesettings.php:214 +#: actions/register.php:159 actions/editgroup.php:185 +#: actions/finishopenidlogin.php:231 actions/newgroup.php:135 +#: actions/profilesettings.php:215 actions/register.php:196 +#: actions/apigroupcreate.php:221 actions/editgroup.php:186 +#: actions/newgroup.php:130 actions/profilesettings.php:231 +#: actions/register.php:202 actions/register.php:208 +msgid "Nickname already in use. Try another one." msgstr "" -#: actions/favor.php:92 lib/disfavorform.php:140 -msgid "Disfavor favorite" +#: ../actions/finishopenidlogin.php:165 ../actions/profilesettings.php:88 +#: ../actions/register.php:67 ../actions/updateprofile.php:77 +#: actions/finishopenidlogin.php:171 actions/profilesettings.php:203 +#: actions/register.php:74 actions/updateprofile.php:78 +#: actions/finishopenidlogin.php:205 actions/profilesettings.php:192 +#: actions/updateprofile.php:81 actions/editgroup.php:179 +#: actions/newgroup.php:130 actions/register.php:156 +#: actions/updateprofile.php:83 actions/editgroup.php:181 +#: actions/finishopenidlogin.php:221 actions/newgroup.php:131 +#: actions/profilesettings.php:193 actions/register.php:193 +#: actions/apigroupcreate.php:212 actions/editgroup.php:182 +#: actions/newgroup.php:126 actions/profilesettings.php:208 +#: actions/register.php:199 actions/register.php:205 +msgid "Nickname must have only lowercase letters and numbers and no spaces." msgstr "" -#: actions/featured.php:69 lib/featureduserssection.php:87 -#: lib/publicgroupnav.php:89 -msgid "Featured users" +#: ../actions/finishopenidlogin.php:170 actions/finishopenidlogin.php:176 +#: actions/finishopenidlogin.php:210 actions/finishopenidlogin.php:226 +msgid "Nickname not allowed." msgstr "" -#: actions/featured.php:71 -#, php-format -msgid "Featured users, page %d" +#: ../actions/remotesubscribe.php:72 actions/remotesubscribe.php:81 +#: actions/remotesubscribe.php:106 actions/remotesubscribe.php:130 +msgid "Nickname of the user you want to follow" msgstr "" -#: actions/featured.php:99 -#, php-format -msgid "A selection of some of the great users on %s" +#: ../actions/recoverpassword.php:162 actions/recoverpassword.php:167 +#: actions/recoverpassword.php:186 actions/recoverpassword.php:191 +msgid "Nickname or email" msgstr "" -#: actions/file.php:34 -msgid "No notice id" +#: ../actions/deletenotice.php:59 actions/deletenotice.php:60 +#: actions/block.php:147 actions/deletenotice.php:118 +#: actions/deletenotice.php:116 actions/block.php:149 +#: actions/deletenotice.php:115 actions/groupblock.php:176 +#: actions/deletenotice.php:145 +msgid "No" msgstr "" -#: actions/file.php:38 -msgid "No notice" +#: ../actions/imsettings.php:156 actions/imsettings.php:164 +#: actions/imsettings.php:279 actions/imsettings.php:285 +msgid "No Jabber ID." msgstr "" -#: actions/file.php:42 -msgid "No attachments" +#: ../actions/userauthorization.php:129 actions/userauthorization.php:136 +#: actions/userauthorization.php:153 actions/userauthorization.php:192 +#: actions/userauthorization.php:225 +msgid "No authorization request!" msgstr "" -#: actions/file.php:51 -msgid "No uploaded attachments" +#: ../actions/smssettings.php:181 actions/smssettings.php:189 +#: actions/smssettings.php:299 actions/smssettings.php:311 +msgid "No carrier selected." msgstr "" -#: actions/finishremotesubscribe.php:69 -msgid "Not expecting this response!" +#: ../actions/smssettings.php:316 actions/smssettings.php:324 +#: actions/smssettings.php:486 actions/smssettings.php:498 +msgid "No code entered" msgstr "" -#: actions/finishremotesubscribe.php:80 -msgid "User being listened to does not exist." +#: ../actions/confirmaddress.php:33 actions/confirmaddress.php:33 +#: actions/confirmaddress.php:75 +msgid "No confirmation code." msgstr "" -#: actions/finishremotesubscribe.php:87 actions/remotesubscribe.php:59 -msgid "You can use the local subscription!" +#: ../actions/newnotice.php:44 actions/newmessage.php:53 +#: actions/newnotice.php:44 classes/Command.php:197 actions/newmessage.php:109 +#: actions/newnotice.php:126 classes/Command.php:223 +#: actions/newmessage.php:142 actions/newnotice.php:131 lib/command.php:223 +#: actions/newnotice.php:162 lib/command.php:216 actions/newmessage.php:144 +#: actions/newnotice.php:136 lib/command.php:351 lib/command.php:424 +msgid "No content!" msgstr "" -#: actions/finishremotesubscribe.php:96 -msgid "That user has blocked you from subscribing." +#: ../actions/emailsettings.php:174 actions/emailsettings.php:192 +#: actions/emailsettings.php:304 actions/emailsettings.php:311 +#: actions/emailsettings.php:319 +msgid "No email address." msgstr "" -#: actions/finishremotesubscribe.php:106 -msgid "You are not authorized." +#: ../actions/userbyid.php:32 actions/userbyid.php:32 actions/userbyid.php:70 +msgid "No id." msgstr "" -#: actions/finishremotesubscribe.php:109 -msgid "Could not convert request token to access token." -msgstr "" - -#: actions/finishremotesubscribe.php:114 -msgid "Remote service uses unknown version of OMB protocol." +#: ../actions/emailsettings.php:271 actions/emailsettings.php:289 +#: actions/emailsettings.php:430 actions/emailsettings.php:437 +#: actions/smssettings.php:505 actions/smssettings.php:506 +#: actions/emailsettings.php:445 actions/smssettings.php:518 +msgid "No incoming email address." msgstr "" -#: actions/finishremotesubscribe.php:133 lib/oauthstore.php:306 -msgid "Error updating remote profile" +#: ../actions/finishremotesubscribe.php:65 +#: actions/finishremotesubscribe.php:67 actions/finishremotesubscribe.php:68 +msgid "No nickname provided by remote server." msgstr "" -#: actions/foafgroup.php:44 actions/foafgroup.php:62 actions/groupblock.php:86 -#: actions/groupunblock.php:86 actions/leavegroup.php:83 -#: actions/makeadmin.php:86 lib/command.php:212 lib/command.php:263 -msgid "No such group." +#: ../actions/avatarbynickname.php:27 actions/avatarbynickname.php:27 +#: actions/avatarbynickname.php:59 actions/leavegroup.php:81 +#: actions/leavegroup.php:76 +msgid "No nickname." msgstr "" -#: actions/getfile.php:75 -msgid "No such file." +#: ../actions/emailsettings.php:222 ../actions/imsettings.php:206 +#: ../actions/smssettings.php:229 actions/emailsettings.php:240 +#: actions/imsettings.php:214 actions/smssettings.php:237 +#: actions/emailsettings.php:363 actions/imsettings.php:345 +#: actions/smssettings.php:358 actions/emailsettings.php:370 +#: actions/emailsettings.php:378 actions/imsettings.php:351 +#: actions/smssettings.php:370 +msgid "No pending confirmation to cancel." msgstr "" -#: actions/getfile.php:79 -msgid "Cannot read file." +#: ../actions/smssettings.php:176 actions/smssettings.php:184 +#: actions/smssettings.php:294 actions/smssettings.php:306 +msgid "No phone number." msgstr "" -#: actions/groupblock.php:81 actions/groupunblock.php:81 -#: actions/makeadmin.php:81 -msgid "No group specified." +#: ../actions/finishremotesubscribe.php:72 +#: actions/finishremotesubscribe.php:74 actions/finishremotesubscribe.php:75 +msgid "No profile URL returned by server." msgstr "" -#: actions/groupblock.php:91 -msgid "Only an admin can block group members." +#: ../actions/recoverpassword.php:226 actions/recoverpassword.php:232 +#: actions/recoverpassword.php:266 actions/recoverpassword.php:284 +#: actions/recoverpassword.php:287 +msgid "No registered email address for that user." msgstr "" -#: actions/groupblock.php:95 -msgid "User is already blocked from group." +#: ../actions/userauthorization.php:49 actions/userauthorization.php:55 +#: actions/userauthorization.php:57 +msgid "No request found!" msgstr "" -#: actions/groupblock.php:100 -msgid "User is not a member of group." +#: ../actions/noticesearch.php:64 ../actions/peoplesearch.php:64 +#: actions/noticesearch.php:69 actions/peoplesearch.php:69 +#: actions/groupsearch.php:81 actions/noticesearch.php:104 +#: actions/peoplesearch.php:85 actions/noticesearch.php:117 +msgid "No results" msgstr "" -#: actions/groupblock.php:136 actions/groupmembers.php:314 -msgid "Block user from group" +#: ../actions/avatarbynickname.php:32 actions/avatarbynickname.php:32 +#: actions/avatarbynickname.php:64 +msgid "No size." msgstr "" -#: actions/groupblock.php:155 -#, php-format -msgid "" -"Are you sure you want to block user \"%s\" from the group \"%s\"? They will " -"be removed from the group, unable to post, and unable to subscribe to the " -"group in the future." +#: ../actions/twitapistatuses.php:595 actions/twitapifavorites.php:136 +#: actions/twitapistatuses.php:520 actions/twitapifavorites.php:112 +#: actions/twitapistatuses.php:446 actions/twitapifavorites.php:118 +#: actions/twitapistatuses.php:470 actions/twitapifavorites.php:169 +#: actions/twitapistatuses.php:426 actions/apifavoritecreate.php:108 +#: actions/apifavoritedestroy.php:109 actions/apistatusesdestroy.php:113 +msgid "No status found with that ID." msgstr "" -#: actions/groupblock.php:193 -msgid "Database error blocking user from group." +#: ../actions/twitapistatuses.php:555 actions/twitapistatuses.php:478 +#: actions/twitapistatuses.php:418 actions/twitapistatuses.php:442 +#: actions/twitapistatuses.php:399 actions/apistatusesshow.php:144 +msgid "No status with that ID found." msgstr "" -#: actions/groupbyid.php:74 -msgid "No ID" +#: ../actions/openidsettings.php:135 actions/openidsettings.php:144 +#: actions/openidsettings.php:222 +msgid "No such OpenID." msgstr "" -#: actions/groupdesignsettings.php:68 -msgid "You must be logged in to edit a group." +#: ../actions/doc.php:29 actions/doc.php:29 actions/doc.php:64 +#: actions/doc.php:69 +msgid "No such document." msgstr "" -#: actions/groupdesignsettings.php:141 -msgid "Group design" +#: ../actions/shownotice.php:32 ../actions/shownotice.php:83 +#: ../lib/deleteaction.php:30 actions/shownotice.php:32 +#: actions/shownotice.php:83 lib/deleteaction.php:30 actions/shownotice.php:87 +#: lib/deleteaction.php:51 actions/deletenotice.php:52 +#: actions/shownotice.php:92 +msgid "No such notice." msgstr "" -#: actions/groupdesignsettings.php:152 -msgid "" -"Customize the way your group looks with a background image and a colour " -"palette of your choice." +#: ../actions/recoverpassword.php:56 actions/recoverpassword.php:56 +#: actions/recoverpassword.php:62 +msgid "No such recovery code." msgstr "" -#: actions/groupdesignsettings.php:262 actions/userdesignsettings.php:186 -#: lib/designsettings.php:434 lib/designsettings.php:464 -msgid "Couldn't update your design." +#: ../actions/postnotice.php:56 actions/postnotice.php:57 +#: actions/postnotice.php:60 +msgid "No such subscription" +msgstr "" + +#: ../actions/all.php:34 ../actions/allrss.php:35 +#: ../actions/avatarbynickname.php:43 ../actions/foaf.php:40 +#: ../actions/remotesubscribe.php:84 ../actions/remotesubscribe.php:91 +#: ../actions/replies.php:57 ../actions/repliesrss.php:35 +#: ../actions/showstream.php:110 ../actions/userbyid.php:36 +#: ../actions/userrss.php:35 ../actions/xrds.php:35 ../lib/gallery.php:57 +#: ../lib/subs.php:33 ../lib/subs.php:82 actions/all.php:34 +#: actions/allrss.php:35 actions/avatarbynickname.php:43 +#: actions/favoritesrss.php:35 actions/foaf.php:40 actions/ical.php:31 +#: actions/remotesubscribe.php:93 actions/remotesubscribe.php:100 +#: actions/replies.php:57 actions/repliesrss.php:35 +#: actions/showfavorites.php:34 actions/showstream.php:110 +#: actions/userbyid.php:36 actions/userrss.php:35 actions/xrds.php:35 +#: classes/Command.php:120 classes/Command.php:162 classes/Command.php:203 +#: classes/Command.php:237 lib/gallery.php:62 lib/mailbox.php:36 +#: lib/subs.php:33 lib/subs.php:95 actions/all.php:53 actions/allrss.php:66 +#: actions/avatarbynickname.php:75 actions/favoritesrss.php:64 +#: actions/foaf.php:41 actions/remotesubscribe.php:123 +#: actions/remotesubscribe.php:130 actions/replies.php:73 +#: actions/repliesrss.php:38 actions/showfavorites.php:105 +#: actions/showstream.php:100 actions/userbyid.php:74 +#: actions/usergroups.php:92 actions/userrss.php:38 actions/xrds.php:73 +#: classes/Command.php:140 classes/Command.php:185 classes/Command.php:234 +#: classes/Command.php:271 lib/galleryaction.php:60 lib/mailbox.php:82 +#: lib/subs.php:34 lib/subs.php:109 actions/all.php:56 actions/allrss.php:68 +#: actions/favoritesrss.php:74 lib/command.php:140 lib/command.php:185 +#: lib/command.php:234 lib/command.php:271 lib/mailbox.php:84 +#: actions/all.php:38 actions/foaf.php:58 actions/replies.php:72 +#: actions/usergroups.php:91 actions/userrss.php:39 lib/command.php:133 +#: lib/command.php:178 lib/command.php:227 lib/command.php:264 +#: lib/galleryaction.php:59 lib/profileaction.php:77 lib/subs.php:112 +#: actions/all.php:74 actions/remotesubscribe.php:145 actions/xrds.php:71 +#: lib/command.php:163 lib/command.php:311 lib/command.php:364 +#: lib/command.php:411 lib/command.php:466 +msgid "No such user." msgstr "" -#: actions/groupdesignsettings.php:286 actions/groupdesignsettings.php:296 -#: actions/userdesignsettings.php:210 actions/userdesignsettings.php:220 -#: actions/userdesignsettings.php:263 actions/userdesignsettings.php:273 -msgid "Unable to save your design settings!" +#: ../actions/recoverpassword.php:211 actions/recoverpassword.php:217 +#: actions/recoverpassword.php:251 actions/recoverpassword.php:269 +#: actions/recoverpassword.php:272 +msgid "No user with that email address or username." msgstr "" -#: actions/groupdesignsettings.php:307 actions/userdesignsettings.php:231 -msgid "Design preferences saved." +#: ../lib/gallery.php:80 lib/gallery.php:85 +msgid "Nobody to show!" msgstr "" -#: actions/grouplogo.php:139 actions/grouplogo.php:192 -msgid "Group logo" +#: ../actions/recoverpassword.php:60 actions/recoverpassword.php:60 +#: actions/recoverpassword.php:66 +msgid "Not a recovery code." msgstr "" -#: actions/grouplogo.php:150 -#, php-format -msgid "" -"You can upload a logo image for your group. The maximum file size is %s." +#: ../scripts/maildaemon.php:50 scripts/maildaemon.php:50 +#: scripts/maildaemon.php:53 scripts/maildaemon.php:52 +msgid "Not a registered user." msgstr "" -#: actions/grouplogo.php:362 -msgid "Pick a square area of the image to be the logo." +#: ../lib/twitterapi.php:226 ../lib/twitterapi.php:247 +#: ../lib/twitterapi.php:332 lib/twitterapi.php:391 lib/twitterapi.php:418 +#: lib/twitterapi.php:502 lib/twitterapi.php:448 lib/twitterapi.php:476 +#: lib/twitterapi.php:566 lib/twitterapi.php:483 lib/twitterapi.php:511 +#: lib/twitterapi.php:601 lib/twitterapi.php:620 lib/twitterapi.php:648 +#: lib/twitterapi.php:741 actions/oembed.php:181 actions/oembed.php:200 +#: lib/api.php:954 lib/api.php:982 lib/api.php:1092 lib/api.php:963 +#: lib/api.php:991 lib/api.php:1101 +msgid "Not a supported data format." msgstr "" -#: actions/grouplogo.php:396 -msgid "Logo updated." +#: ../actions/imsettings.php:167 actions/imsettings.php:175 +#: actions/imsettings.php:290 actions/imsettings.php:296 +msgid "Not a valid Jabber ID" msgstr "" -#: actions/grouplogo.php:398 -msgid "Failed updating logo." +#: ../lib/openid.php:131 lib/openid.php:131 lib/openid.php:140 +#: lib/openid.php:143 +msgid "Not a valid OpenID." msgstr "" -#: actions/groupmembers.php:93 lib/groupnav.php:91 -#, php-format -msgid "%s group members" +#: ../actions/emailsettings.php:185 actions/emailsettings.php:203 +#: actions/emailsettings.php:315 actions/emailsettings.php:322 +#: actions/emailsettings.php:330 +msgid "Not a valid email address" msgstr "" -#: actions/groupmembers.php:96 -#, php-format -msgid "%s group members, page %d" +#: ../actions/register.php:63 actions/register.php:70 actions/register.php:152 +#: actions/register.php:189 actions/register.php:195 actions/register.php:201 +msgid "Not a valid email address." msgstr "" -#: actions/groupmembers.php:111 -msgid "A list of the users in this group." +#: ../actions/profilesettings.php:91 ../actions/register.php:71 +#: actions/profilesettings.php:206 actions/register.php:78 +#: actions/editgroup.php:186 actions/newgroup.php:137 +#: actions/profilesettings.php:195 actions/register.php:161 +#: actions/editgroup.php:188 actions/newgroup.php:138 +#: actions/profilesettings.php:196 actions/register.php:198 +#: actions/apigroupcreate.php:228 actions/editgroup.php:189 +#: actions/newgroup.php:133 actions/profilesettings.php:211 +#: actions/register.php:204 actions/register.php:210 +msgid "Not a valid nickname." msgstr "" -#: actions/groupmembers.php:175 lib/groupnav.php:106 -msgid "Admin" +#: ../actions/remotesubscribe.php:120 actions/remotesubscribe.php:129 +#: actions/remotesubscribe.php:159 +msgid "Not a valid profile URL (incorrect services)." msgstr "" -#: actions/groupmembers.php:346 lib/blockform.php:153 -msgid "Block" +#: ../actions/remotesubscribe.php:113 actions/remotesubscribe.php:122 +#: actions/remotesubscribe.php:152 +msgid "Not a valid profile URL (no XRDS defined)." msgstr "" -#: actions/groupmembers.php:346 lib/blockform.php:123 lib/blockform.php:153 -msgid "Block this user" +#: ../actions/remotesubscribe.php:104 actions/remotesubscribe.php:113 +#: actions/remotesubscribe.php:143 +msgid "Not a valid profile URL (no YADIS document)." msgstr "" -#: actions/groupmembers.php:441 -msgid "Make user an admin of the group" +#: ../actions/avatar.php:95 actions/profilesettings.php:332 +#: lib/imagefile.php:87 lib/imagefile.php:90 lib/imagefile.php:91 +#: lib/imagefile.php:96 +msgid "Not an image or corrupt file." msgstr "" -#: actions/groupmembers.php:473 -msgid "Make Admin" +#: ../actions/finishremotesubscribe.php:51 +#: actions/finishremotesubscribe.php:53 actions/finishremotesubscribe.php:54 +msgid "Not authorized." msgstr "" -#: actions/groupmembers.php:473 -msgid "Make this user an admin" +#: ../actions/finishremotesubscribe.php:38 +#: actions/finishremotesubscribe.php:38 actions/finishremotesubscribe.php:40 +#: actions/finishremotesubscribe.php:69 +msgid "Not expecting this response!" msgstr "" -#: actions/grouprss.php:133 -#, php-format -msgid "Updates from members of %1$s on %2$s!" +#: ../actions/twitapistatuses.php:422 actions/twitapistatuses.php:361 +#: actions/twitapistatuses.php:309 actions/twitapistatuses.php:327 +#: actions/twitapistatuses.php:284 actions/apistatusesupdate.php:186 +#: actions/apistatusesupdate.php:193 +msgid "Not found" msgstr "" -#: actions/groupsearch.php:52 -#, php-format -msgid "" -"Search for groups on %%site.name%% by their name, location, or description. " -"Separate the terms by spaces; they must be 3 characters or more." +#: ../actions/finishaddopenid.php:29 ../actions/logout.php:33 +#: ../actions/newnotice.php:29 ../actions/subscribe.php:28 +#: ../actions/unsubscribe.php:25 ../lib/deleteaction.php:38 +#: ../lib/settingsaction.php:27 actions/disfavor.php:29 actions/favor.php:30 +#: actions/finishaddopenid.php:29 actions/logout.php:33 +#: actions/newmessage.php:28 actions/newnotice.php:29 actions/subscribe.php:28 +#: actions/unsubscribe.php:25 lib/deleteaction.php:38 +#: lib/settingsaction.php:27 actions/block.php:59 actions/disfavor.php:61 +#: actions/favor.php:64 actions/finishaddopenid.php:67 actions/logout.php:71 +#: actions/newmessage.php:83 actions/newnotice.php:90 actions/nudge.php:63 +#: actions/subedit.php:31 actions/subscribe.php:30 actions/unblock.php:60 +#: actions/unsubscribe.php:27 lib/deleteaction.php:66 +#: lib/settingsaction.php:72 actions/newmessage.php:87 actions/favor.php:62 +#: actions/groupblock.php:61 actions/groupunblock.php:61 +#: actions/makeadmin.php:61 actions/newnotice.php:88 +#: actions/deletenotice.php:67 actions/logout.php:69 actions/newnotice.php:89 +#: actions/unsubscribe.php:52 +msgid "Not logged in." msgstr "" -#: actions/groupsearch.php:58 -msgid "Group search" +#: ../lib/subs.php:91 lib/subs.php:104 lib/subs.php:122 lib/subs.php:124 +msgid "Not subscribed!." msgstr "" -#: actions/groupsearch.php:79 actions/noticesearch.php:117 -#: actions/peoplesearch.php:83 -msgid "No results." +#: ../actions/opensearch.php:35 actions/opensearch.php:35 +#: actions/opensearch.php:67 +msgid "Notice Search" msgstr "" -#: actions/groupsearch.php:82 +#: ../actions/showstream.php:82 actions/showstream.php:82 +#: actions/showstream.php:180 actions/showstream.php:187 +#: actions/showstream.php:192 #, php-format -msgid "" -"If you can't find the group you're looking for, you can [create it](%%action." -"newgroup%%) yourself." +msgid "Notice feed for %s" msgstr "" -#: actions/groupsearch.php:85 -#, php-format -msgid "" -"Why not [register an account](%%action.register%%) and [create the group](%%" -"action.newgroup%%) yourself!" +#: ../actions/shownotice.php:39 actions/shownotice.php:39 +#: actions/shownotice.php:94 actions/oembed.php:79 actions/shownotice.php:100 +msgid "Notice has no profile" msgstr "" -#: actions/groups.php:62 lib/profileaction.php:220 lib/publicgroupnav.php:81 -#: lib/subgroupnav.php:98 -msgid "Groups" +#: ../actions/showstream.php:316 actions/showstream.php:331 +#: actions/showstream.php:504 lib/facebookaction.php:477 lib/mailbox.php:116 +#: lib/noticelist.php:87 lib/facebookaction.php:581 lib/mailbox.php:118 +#: actions/conversation.php:149 lib/facebookaction.php:572 +#: lib/profileaction.php:206 actions/conversation.php:154 +msgid "Notices" msgstr "" -#: actions/groups.php:64 +#: ../actions/tag.php:35 ../actions/tag.php:81 actions/tag.php:35 +#: actions/tag.php:81 actions/tag.php:41 actions/tag.php:49 actions/tag.php:57 +#: actions/twitapitags.php:69 actions/apitimelinetag.php:101 +#: actions/tag.php:66 #, php-format -msgid "Groups, page %d" +msgid "Notices tagged with %s" msgstr "" -#: actions/groups.php:90 -#, php-format -msgid "" -"%%%%site.name%%%% groups let you find and talk with users of similar " -"interests. After you join a group you can send messages to all other members " -"using the syntax \"!groupname\". Are you not seeing any groups you like? Try " -"[searching for one](%%%%action.groupsearch%%%%) or [start your own](%%%%" -"action.newgroup%%%%)!" +#: ../actions/password.php:39 actions/profilesettings.php:178 +#: actions/passwordsettings.php:97 actions/passwordsettings.php:103 +msgid "Old password" msgstr "" -#: actions/groups.php:108 actions/usergroups.php:124 lib/groupeditform.php:122 -msgid "Create a new group" +#: ../lib/settingsaction.php:96 ../lib/util.php:314 lib/settingsaction.php:90 +#: lib/util.php:330 lib/accountsettingsaction.php:116 lib/action.php:341 +#: lib/logingroupnav.php:81 lib/action.php:418 +msgid "OpenID" msgstr "" -#: actions/groupunblock.php:91 -msgid "Only an admin can unblock group members." +#: ../actions/finishopenidlogin.php:61 actions/finishopenidlogin.php:66 +#: actions/finishopenidlogin.php:73 actions/finishopenidlogin.php:72 +msgid "OpenID Account Setup" msgstr "" -#: actions/groupunblock.php:95 -msgid "User is not blocked from group." +#: ../lib/openid.php:180 lib/openid.php:180 lib/openid.php:266 +#: lib/openid.php:269 +msgid "OpenID Auto-Submit" msgstr "" -#: actions/groupunblock.php:128 actions/unblock.php:108 -msgid "Error removing the block." +#: ../actions/finishaddopenid.php:99 ../actions/finishopenidlogin.php:140 +#: ../actions/openidlogin.php:60 actions/finishaddopenid.php:99 +#: actions/finishopenidlogin.php:146 actions/openidlogin.php:68 +#: actions/finishaddopenid.php:170 actions/openidlogin.php:80 +#: actions/openidlogin.php:89 +msgid "OpenID Login" msgstr "" -#: actions/imsettings.php:59 -msgid "IM Settings" +#: ../actions/openidlogin.php:65 ../actions/openidsettings.php:49 +#: actions/openidlogin.php:74 actions/openidsettings.php:50 +#: actions/openidlogin.php:102 actions/openidsettings.php:101 +#: actions/openidlogin.php:111 +msgid "OpenID URL" msgstr "" -#: actions/imsettings.php:70 +#: ../actions/finishaddopenid.php:42 ../actions/finishopenidlogin.php:103 +#: actions/finishaddopenid.php:42 actions/finishopenidlogin.php:109 +#: actions/finishaddopenid.php:88 actions/finishopenidlogin.php:130 +#: actions/finishopenidlogin.php:129 +msgid "OpenID authentication cancelled." +msgstr "" + +#: ../actions/finishaddopenid.php:46 ../actions/finishopenidlogin.php:107 +#: actions/finishaddopenid.php:46 actions/finishopenidlogin.php:113 +#: actions/finishaddopenid.php:92 actions/finishopenidlogin.php:134 +#: actions/finishopenidlogin.php:133 #, php-format -msgid "" -"You can send and receive notices through Jabber/GTalk [instant messages](%%" -"doc.im%%). Configure your instant messages address and settings below." +msgid "OpenID authentication failed: %s" msgstr "" -#: actions/imsettings.php:89 -msgid "IM is not available." +#: ../lib/openid.php:133 lib/openid.php:133 lib/openid.php:142 +#: lib/openid.php:145 +#, php-format +msgid "OpenID failure: %s" msgstr "" -#: actions/imsettings.php:100 -msgid "IM address" +#: ../actions/openidsettings.php:144 actions/openidsettings.php:153 +#: actions/openidsettings.php:231 +msgid "OpenID removed." msgstr "" -#: actions/imsettings.php:106 -msgid "Current confirmed Jabber/GTalk address." +#: ../actions/openidsettings.php:37 actions/openidsettings.php:37 +#: actions/openidsettings.php:59 +msgid "OpenID settings" msgstr "" -#: actions/imsettings.php:114 -#, php-format -msgid "" -"Awaiting confirmation on this IM address. Check your Jabber/GTalk account " -"for a message with further instructions. (Did you add %s to your buddy list?)" +#: ../actions/invite.php:135 actions/invite.php:143 actions/invite.php:180 +#: actions/invite.php:186 actions/invite.php:188 actions/invite.php:194 +msgid "Optionally add a personal message to the invitation." msgstr "" -#: actions/imsettings.php:124 -msgid "IM Address" +#: ../actions/avatar.php:84 actions/profilesettings.php:321 +#: lib/imagefile.php:75 lib/imagefile.php:79 lib/imagefile.php:80 +msgid "Partial upload." msgstr "" -#: actions/imsettings.php:126 -#, php-format -msgid "" -"Jabber or GTalk address, like \"UserName@example.org\". First, make sure to " -"add %s to your buddy list in your IM client or on GTalk." +#: ../actions/finishopenidlogin.php:90 ../actions/login.php:102 +#: ../actions/register.php:153 ../lib/settingsaction.php:93 +#: actions/finishopenidlogin.php:96 actions/login.php:102 +#: actions/register.php:167 actions/finishopenidlogin.php:118 +#: actions/login.php:231 actions/register.php:372 +#: lib/accountsettingsaction.php:110 lib/facebookaction.php:311 +#: actions/login.php:214 lib/facebookaction.php:315 +#: actions/finishopenidlogin.php:117 actions/register.php:418 +#: lib/facebookaction.php:317 actions/login.php:222 actions/register.php:422 +#: lib/accountsettingsaction.php:114 actions/login.php:249 +#: actions/register.php:428 +msgid "Password" msgstr "" -#: actions/imsettings.php:143 -msgid "Send me notices through Jabber/GTalk." +#: ../actions/recoverpassword.php:288 actions/recoverpassword.php:301 +#: actions/recoverpassword.php:335 actions/recoverpassword.php:353 +#: actions/recoverpassword.php:356 +msgid "Password and confirmation do not match." msgstr "" -#: actions/imsettings.php:148 -msgid "Post a notice when my Jabber/GTalk status changes." +#: ../actions/recoverpassword.php:284 actions/recoverpassword.php:297 +#: actions/recoverpassword.php:331 actions/recoverpassword.php:349 +#: actions/recoverpassword.php:352 +msgid "Password must be 6 chars or more." msgstr "" -#: actions/imsettings.php:153 -msgid "Send me replies through Jabber/GTalk from users I am not subscribed to." +#: ../actions/recoverpassword.php:261 ../actions/recoverpassword.php:263 +#: actions/recoverpassword.php:267 actions/recoverpassword.php:269 +#: actions/recoverpassword.php:199 actions/recoverpassword.php:301 +#: actions/recoverpassword.php:207 actions/recoverpassword.php:319 +#: actions/recoverpassword.php:210 actions/recoverpassword.php:322 +msgid "Password recovery requested" msgstr "" -#: actions/imsettings.php:159 -msgid "Publish a MicroID for my Jabber/GTalk address." +#: ../actions/password.php:89 ../actions/recoverpassword.php:313 +#: actions/profilesettings.php:408 actions/recoverpassword.php:326 +#: actions/passwordsettings.php:173 actions/recoverpassword.php:200 +#: actions/passwordsettings.php:178 actions/recoverpassword.php:208 +#: actions/passwordsettings.php:184 actions/recoverpassword.php:211 +#: actions/passwordsettings.php:191 +msgid "Password saved." msgstr "" -#: actions/imsettings.php:285 -msgid "No Jabber ID." +#: ../actions/password.php:61 ../actions/register.php:88 +#: actions/profilesettings.php:380 actions/register.php:98 +#: actions/passwordsettings.php:145 actions/register.php:183 +#: actions/passwordsettings.php:150 actions/register.php:220 +#: actions/passwordsettings.php:156 actions/register.php:227 +#: actions/register.php:233 +msgid "Passwords don't match." msgstr "" -#: actions/imsettings.php:292 -msgid "Cannot normalize that Jabber ID" +#: ../lib/searchaction.php:100 lib/searchaction.php:100 +#: lib/searchgroupnav.php:80 +msgid "People" msgstr "" -#: actions/imsettings.php:296 -msgid "Not a valid Jabber ID" +#: ../actions/opensearch.php:33 actions/opensearch.php:33 +#: actions/opensearch.php:64 +msgid "People Search" msgstr "" -#: actions/imsettings.php:299 -msgid "That is already your Jabber ID." +#: ../actions/peoplesearch.php:33 actions/peoplesearch.php:33 +#: actions/peoplesearch.php:58 +msgid "People search" msgstr "" -#: actions/imsettings.php:302 -msgid "Jabber ID already belongs to another user." +#: ../lib/stream.php:50 lib/personal.php:50 lib/personalgroupnav.php:98 +#: lib/personalgroupnav.php:99 +msgid "Personal" msgstr "" -#: actions/imsettings.php:327 -#, php-format -msgid "" -"A confirmation code was sent to the IM address you added. You must approve %" -"s for sending messages to you." +#: ../actions/invite.php:133 actions/invite.php:141 actions/invite.php:178 +#: actions/invite.php:184 actions/invite.php:186 actions/invite.php:192 +msgid "Personal message" msgstr "" -#: actions/imsettings.php:387 -msgid "That is not your Jabber ID." +#: ../actions/smssettings.php:69 actions/smssettings.php:69 +#: actions/smssettings.php:128 actions/smssettings.php:140 +msgid "Phone number, no punctuation or spaces, with area code" msgstr "" -#: actions/inbox.php:59 -#, php-format -msgid "Inbox for %s - page %d" +#: ../actions/userauthorization.php:78 +msgid "" +"Please check these details to make sure that you want to subscribe to this " +"user's notices. If you didn't just ask to subscribe to someone's notices, " +"click \"Cancel\"." msgstr "" -#: actions/inbox.php:62 -#, php-format -msgid "Inbox for %s" +#: ../actions/imsettings.php:73 actions/imsettings.php:74 +#: actions/imsettings.php:142 actions/imsettings.php:148 +msgid "Post a notice when my Jabber/GTalk status changes." msgstr "" -#: actions/inbox.php:115 -msgid "This is your inbox, which lists your incoming private messages." +#: ../actions/emailsettings.php:85 ../actions/imsettings.php:67 +#: ../actions/smssettings.php:94 actions/emailsettings.php:86 +#: actions/imsettings.php:68 actions/smssettings.php:94 +#: actions/twittersettings.php:70 actions/emailsettings.php:147 +#: actions/imsettings.php:133 actions/smssettings.php:157 +#: actions/twittersettings.php:134 actions/twittersettings.php:137 +#: actions/emailsettings.php:153 actions/imsettings.php:139 +#: actions/smssettings.php:169 +msgid "Preferences" msgstr "" -#: actions/invite.php:39 -msgid "Invites have been disabled." +#: ../actions/emailsettings.php:162 ../actions/imsettings.php:144 +#: ../actions/smssettings.php:163 actions/emailsettings.php:180 +#: actions/imsettings.php:152 actions/smssettings.php:171 +#: actions/emailsettings.php:286 actions/imsettings.php:258 +#: actions/othersettings.php:168 actions/smssettings.php:272 +#: actions/emailsettings.php:293 actions/othersettings.php:173 +#: actions/emailsettings.php:301 actions/imsettings.php:264 +#: actions/othersettings.php:180 actions/smssettings.php:284 +msgid "Preferences saved." msgstr "" -#: actions/invite.php:41 -#, php-format -msgid "You must be logged in to invite other users to use %s" +#: ../actions/profilesettings.php:57 actions/profilesettings.php:90 +#: actions/profilesettings.php:129 actions/profilesettings.php:130 +#: actions/profilesettings.php:145 +msgid "Preferred language" msgstr "" -#: actions/invite.php:72 -#, php-format -msgid "Invalid email address: %s" +#: ../lib/util.php:328 lib/util.php:344 lib/action.php:572 lib/action.php:665 +#: lib/action.php:715 lib/action.php:730 +msgid "Privacy" msgstr "" -#: actions/invite.php:110 -msgid "Invitation(s) sent" +#: ../classes/Notice.php:95 ../classes/Notice.php:106 classes/Notice.php:109 +#: classes/Notice.php:119 classes/Notice.php:145 classes/Notice.php:155 +#: classes/Notice.php:178 classes/Notice.php:188 classes/Notice.php:206 +#: classes/Notice.php:216 classes/Notice.php:232 classes/Notice.php:268 +#: classes/Notice.php:293 +msgid "Problem saving notice." msgstr "" -#: actions/invite.php:112 -msgid "Invite new users" +#: ../lib/settingsaction.php:84 ../lib/stream.php:60 lib/personal.php:60 +#: lib/settingsaction.php:84 lib/accountsettingsaction.php:104 +#: lib/personalgroupnav.php:108 lib/personalgroupnav.php:109 +#: lib/accountsettingsaction.php:108 +msgid "Profile" msgstr "" -#: actions/invite.php:128 -msgid "You are already subscribed to these users:" +#: ../actions/remotesubscribe.php:73 actions/remotesubscribe.php:82 +#: actions/remotesubscribe.php:109 actions/remotesubscribe.php:133 +msgid "Profile URL" msgstr "" -#: actions/invite.php:131 actions/invite.php:139 -#, php-format -msgid "%s (%s)" +#: ../actions/profilesettings.php:34 actions/profilesettings.php:32 +#: actions/profilesettings.php:58 actions/profilesettings.php:60 +msgid "Profile settings" msgstr "" -#: actions/invite.php:136 -msgid "These are already users and you were automatically subscribed to them:" +#: ../actions/postnotice.php:51 ../actions/updateprofile.php:52 +#: actions/postnotice.php:52 actions/updateprofile.php:53 +#: actions/postnotice.php:55 actions/updateprofile.php:56 +#: actions/updateprofile.php:58 +msgid "Profile unknown" msgstr "" -#: actions/invite.php:144 -msgid "Invitation(s) sent to the following e-mail addresses:" +#: ../actions/public.php:54 actions/public.php:54 actions/public.php:124 +msgid "Public Stream Feed" msgstr "" -#: actions/invite.php:150 -msgid "" -"You will be notified when your invitees accept the invitation and register " -"on the site. Thanks for growing the community!" +#: ../actions/public.php:33 actions/public.php:33 actions/public.php:109 +#: lib/publicgroupnav.php:77 actions/public.php:112 lib/publicgroupnav.php:79 +#: actions/public.php:120 actions/public.php:131 +msgid "Public timeline" msgstr "" -#: actions/invite.php:162 -msgid "" -"Use this form to invite your friends and colleagues to use this service." +#: ../actions/imsettings.php:79 actions/imsettings.php:80 +#: actions/imsettings.php:153 actions/imsettings.php:159 +msgid "Publish a MicroID for my Jabber/GTalk address." msgstr "" -#: actions/invite.php:187 -msgid "Email addresses" +#: ../actions/emailsettings.php:94 actions/emailsettings.php:101 +#: actions/emailsettings.php:178 actions/emailsettings.php:183 +#: actions/emailsettings.php:191 +msgid "Publish a MicroID for my email address." msgstr "" -#: actions/invite.php:189 -msgid "Addresses of friends to invite (one per line)" +#: ../actions/tag.php:75 ../actions/tag.php:76 actions/tag.php:75 +#: actions/tag.php:76 +msgid "Recent Tags" msgstr "" -#: actions/invite.php:192 -msgid "Personal message" +#: ../actions/recoverpassword.php:166 actions/recoverpassword.php:171 +#: actions/recoverpassword.php:190 actions/recoverpassword.php:197 +#: actions/recoverpassword.php:199 actions/recoverpassword.php:200 +msgid "Recover" msgstr "" -#: actions/invite.php:194 -msgid "Optionally add a personal message to the invitation." +#: ../actions/recoverpassword.php:156 actions/recoverpassword.php:161 +#: actions/recoverpassword.php:198 actions/recoverpassword.php:206 +#: actions/recoverpassword.php:209 +msgid "Recover password" msgstr "" -#: actions/invite.php:197 lib/messageform.php:181 lib/noticeform.php:208 -msgid "Send" +#: ../actions/recoverpassword.php:67 actions/recoverpassword.php:67 +#: actions/recoverpassword.php:73 +msgid "Recovery code for unknown user." msgstr "" -#: actions/invite.php:226 -#, php-format -msgid "%1$s has invited you to join them on %2$s" +#: ../actions/register.php:142 ../actions/register.php:193 ../lib/util.php:312 +#: actions/register.php:152 actions/register.php:207 lib/util.php:328 +#: actions/register.php:69 actions/register.php:436 lib/action.php:338 +#: lib/facebookaction.php:277 lib/logingroupnav.php:78 +#: actions/register.php:438 lib/action.php:415 lib/facebookaction.php:279 +#: actions/register.php:108 actions/register.php:486 lib/action.php:440 +#: lib/facebookaction.php:281 actions/register.php:496 lib/action.php:450 +#: lib/logingroupnav.php:85 actions/register.php:114 actions/register.php:502 +msgid "Register" msgstr "" -#: actions/invite.php:228 -#, php-format -msgid "" -"%1$s has invited you to join them on %2$s (%3$s).\n" -"\n" -"%2$s is a micro-blogging service that lets you keep up-to-date with those " -"you know and those who interest you.\n" -"\n" -"You can also share news about yourself, your thoughts, or your life online " -"with users who know about you. It is also great for meeting others who share " -"your interests.\n" -"\n" -"%1$s said:\n" -"\n" -"%4$s\n" -"\n" -"You can see %1$s's profile page on %2$s here:\n" -"\n" -"%5$s\n" -"\n" -"If you'd like to try the service, click on the link below to accept the " -"invitation.\n" -"\n" -"%6$s\n" -"\n" -"If not, you can ignore this message. Thanks for your patience and your " -"time.\n" -"\n" -"Sincerely, %2$s\n" +#: ../actions/register.php:28 actions/register.php:28 +#: actions/finishopenidlogin.php:196 actions/register.php:90 +#: actions/finishopenidlogin.php:195 actions/finishopenidlogin.php:204 +#: actions/register.php:129 actions/register.php:135 +msgid "Registration not allowed." msgstr "" -#: actions/joingroup.php:60 -msgid "You must be logged in to join a group." +#: ../actions/register.php:200 actions/register.php:214 +#: actions/register.php:67 actions/register.php:106 actions/register.php:112 +msgid "Registration successful" msgstr "" -#: actions/joingroup.php:90 lib/command.php:217 -msgid "You are already a member of that group" +#: ../actions/userauthorization.php:120 actions/userauthorization.php:127 +#: actions/userauthorization.php:144 actions/userauthorization.php:179 +#: actions/userauthorization.php:211 +msgid "Reject" msgstr "" -#: actions/joingroup.php:128 lib/command.php:234 -#, php-format -msgid "Could not join user %s to group %s" +#: ../actions/login.php:103 ../actions/register.php:176 actions/login.php:103 +#: actions/register.php:190 actions/login.php:234 actions/openidlogin.php:107 +#: actions/register.php:414 actions/login.php:217 actions/openidlogin.php:116 +#: actions/register.php:461 actions/login.php:225 actions/register.php:471 +#: actions/login.php:252 actions/register.php:477 +msgid "Remember me" msgstr "" -#: actions/joingroup.php:135 lib/command.php:239 -#, php-format -msgid "%s joined group %s" +#: ../actions/updateprofile.php:70 actions/updateprofile.php:71 +#: actions/updateprofile.php:74 actions/updateprofile.php:76 +msgid "Remote profile with no matching profile" msgstr "" -#: actions/leavegroup.php:60 -msgid "You must be logged in to leave a group." +#: ../actions/remotesubscribe.php:65 actions/remotesubscribe.php:73 +#: actions/remotesubscribe.php:88 actions/remotesubscribe.php:112 +msgid "Remote subscribe" msgstr "" -#: actions/leavegroup.php:90 lib/command.php:268 -msgid "You are not a member of that group." +#: ../actions/emailsettings.php:47 ../actions/emailsettings.php:75 +#: ../actions/imsettings.php:48 ../actions/openidsettings.php:106 +#: ../actions/smssettings.php:50 ../actions/smssettings.php:84 +#: actions/emailsettings.php:48 actions/emailsettings.php:76 +#: actions/imsettings.php:49 actions/openidsettings.php:108 +#: actions/smssettings.php:50 actions/smssettings.php:84 +#: actions/twittersettings.php:59 actions/emailsettings.php:101 +#: actions/emailsettings.php:134 actions/imsettings.php:102 +#: actions/openidsettings.php:166 actions/smssettings.php:103 +#: actions/smssettings.php:146 actions/twittersettings.php:115 +#: actions/twittersettings.php:118 actions/emailsettings.php:107 +#: actions/emailsettings.php:140 actions/imsettings.php:108 +#: actions/smssettings.php:115 actions/smssettings.php:158 +msgid "Remove" msgstr "" -#: actions/leavegroup.php:119 lib/command.php:278 -msgid "Could not find membership record." +#: ../actions/openidsettings.php:68 actions/openidsettings.php:69 +#: actions/openidsettings.php:123 +msgid "Remove OpenID" msgstr "" -#: actions/leavegroup.php:127 lib/command.php:284 -#, php-format -msgid "Could not remove user %s to group %s" +#: ../actions/openidsettings.php:73 actions/openidsettings.php:128 +msgid "" +"Removing your only OpenID would make it impossible to log in! If you need to " +"remove it, add another OpenID first." msgstr "" -#: actions/leavegroup.php:134 lib/command.php:289 +#: ../lib/stream.php:55 lib/personal.php:55 lib/personalgroupnav.php:103 +#: lib/personalgroupnav.php:104 +msgid "Replies" +msgstr "" + +#: ../actions/replies.php:47 ../actions/repliesrss.php:76 ../lib/stream.php:56 +#: actions/replies.php:47 actions/repliesrss.php:62 lib/personal.php:56 +#: actions/replies.php:116 actions/repliesrss.php:67 +#: lib/personalgroupnav.php:104 actions/replies.php:118 +#: actions/replies.php:117 lib/personalgroupnav.php:105 +#: actions/replies.php:125 actions/repliesrss.php:68 #, php-format -msgid "%s left group %s" +msgid "Replies to %s" msgstr "" -#: actions/login.php:79 actions/register.php:137 -msgid "Already logged in." +#: ../actions/recoverpassword.php:183 actions/recoverpassword.php:189 +#: actions/recoverpassword.php:223 actions/recoverpassword.php:240 +#: actions/recoverpassword.php:243 +msgid "Reset" msgstr "" -#: actions/login.php:110 actions/login.php:120 -msgid "Invalid or expired token." +#: ../actions/recoverpassword.php:173 actions/recoverpassword.php:178 +#: actions/recoverpassword.php:197 actions/recoverpassword.php:205 +#: actions/recoverpassword.php:208 +msgid "Reset password" msgstr "" -#: actions/login.php:143 -msgid "Incorrect username or password." +#: ../lib/settingsaction.php:99 lib/settingsaction.php:93 +#: actions/subscriptions.php:123 lib/connectsettingsaction.php:107 +#: actions/subscriptions.php:125 actions/subscriptions.php:184 +#: actions/subscriptions.php:199 lib/connectsettingsaction.php:115 +msgid "SMS" msgstr "" -#: actions/login.php:149 actions/recoverpassword.php:375 -#: actions/register.php:248 -msgid "Error setting user." +#: ../actions/smssettings.php:67 actions/smssettings.php:67 +#: actions/smssettings.php:126 actions/smssettings.php:138 +msgid "SMS Phone number" msgstr "" -#: actions/login.php:204 actions/login.php:257 lib/action.php:453 -#: lib/logingroupnav.php:79 -msgid "Login" +#: ../actions/smssettings.php:33 actions/smssettings.php:33 +#: actions/smssettings.php:58 +msgid "SMS Settings" msgstr "" -#: actions/login.php:243 -msgid "Login to site" +#: ../lib/mail.php:219 lib/mail.php:225 lib/mail.php:437 lib/mail.php:438 +msgid "SMS confirmation" msgstr "" -#: actions/login.php:246 actions/profilesettings.php:106 -#: actions/register.php:423 actions/showgroup.php:236 actions/tagother.php:94 -#: lib/groupeditform.php:152 lib/userprofile.php:131 -msgid "Nickname" +#: ../actions/recoverpassword.php:182 actions/recoverpassword.php:188 +#: actions/recoverpassword.php:222 actions/recoverpassword.php:237 +#: actions/recoverpassword.php:240 +msgid "Same as password above" msgstr "" -#: actions/login.php:249 actions/register.php:428 -#: lib/accountsettingsaction.php:114 -msgid "Password" +#: ../actions/register.php:156 actions/register.php:170 +#: actions/register.php:377 actions/register.php:423 actions/register.php:427 +#: actions/register.php:433 +msgid "Same as password above. Required." msgstr "" -#: actions/login.php:252 actions/register.php:477 -msgid "Remember me" +#: ../actions/emailsettings.php:97 ../actions/imsettings.php:81 +#: ../actions/profilesettings.php:67 ../actions/smssettings.php:100 +#: actions/emailsettings.php:104 actions/imsettings.php:82 +#: actions/profilesettings.php:101 actions/smssettings.php:100 +#: actions/twittersettings.php:83 actions/emailsettings.php:182 +#: actions/facebooksettings.php:114 actions/imsettings.php:157 +#: actions/othersettings.php:117 actions/profilesettings.php:150 +#: actions/smssettings.php:169 actions/subscriptions.php:124 +#: actions/tagother.php:152 actions/twittersettings.php:161 +#: lib/groupeditform.php:171 actions/emailsettings.php:187 +#: actions/subscriptions.php:126 actions/tagother.php:154 +#: actions/twittersettings.php:164 actions/othersettings.php:119 +#: actions/profilesettings.php:152 actions/subscriptions.php:185 +#: actions/twittersettings.php:180 lib/designsettings.php:256 +#: lib/groupeditform.php:196 actions/emailsettings.php:195 +#: actions/imsettings.php:163 actions/othersettings.php:126 +#: actions/profilesettings.php:167 actions/smssettings.php:181 +#: actions/subscriptions.php:203 lib/groupeditform.php:202 +msgid "Save" msgstr "" -#: actions/login.php:253 actions/register.php:479 -msgid "Automatically login in the future; not for shared computers!" +#: ../lib/searchaction.php:84 ../lib/util.php:300 lib/searchaction.php:84 +#: lib/util.php:316 lib/action.php:325 lib/action.php:396 lib/action.php:448 +#: lib/action.php:459 +msgid "Search" msgstr "" -#: actions/login.php:263 -msgid "Lost or forgotten password?" +#: ../actions/noticesearch.php:80 actions/noticesearch.php:85 +#: actions/noticesearch.php:127 +msgid "Search Stream Feed" msgstr "" -#: actions/login.php:282 +#: ../actions/noticesearch.php:30 actions/noticesearch.php:30 +#: actions/noticesearch.php:57 actions/noticesearch.php:68 +#, php-format msgid "" -"For security reasons, please re-enter your user name and password before " -"changing your settings." +"Search for notices on %%site.name%% by their contents. Separate search terms " +"by spaces; they must be 3 characters or more." msgstr "" -#: actions/login.php:286 +#: ../actions/peoplesearch.php:28 actions/peoplesearch.php:52 #, php-format msgid "" -"Login with your username and password. Don't have a username yet? [Register]" -"(%%action.register%%) a new account." +"Search for people on %%site.name%% by their name, location, or interests. " +"Separate the terms by spaces; they must be 3 characters or more." msgstr "" -#: actions/makeadmin.php:91 -msgid "Only an admin can make another user an admin." +#: ../actions/smssettings.php:296 actions/smssettings.php:304 +#: actions/smssettings.php:457 actions/smssettings.php:469 +msgid "Select a carrier" msgstr "" -#: actions/makeadmin.php:95 -#, php-format -msgid "%s is already an admin for group \"%s\"." +#: ../actions/invite.php:137 ../lib/util.php:1172 actions/invite.php:145 +#: lib/util.php:1306 lib/util.php:1731 actions/invite.php:182 +#: lib/messageform.php:167 lib/noticeform.php:177 actions/invite.php:189 +#: lib/messageform.php:165 actions/invite.php:191 lib/messageform.php:157 +#: lib/noticeform.php:179 actions/invite.php:197 lib/messageform.php:181 +#: lib/noticeform.php:208 +msgid "Send" msgstr "" -#: actions/makeadmin.php:132 -#, php-format -msgid "Can't get membership record for %s in group %s" +#: ../actions/emailsettings.php:73 ../actions/smssettings.php:82 +#: actions/emailsettings.php:74 actions/smssettings.php:82 +#: actions/emailsettings.php:132 actions/smssettings.php:145 +#: actions/emailsettings.php:138 actions/smssettings.php:157 +msgid "Send email to this address to post new notices." msgstr "" -#: actions/makeadmin.php:145 -#, php-format -msgid "Can't make %s an admin for group %s" +#: ../actions/emailsettings.php:88 actions/emailsettings.php:89 +#: actions/emailsettings.php:152 actions/emailsettings.php:158 +msgid "Send me notices of new subscriptions through email." msgstr "" -#: actions/microsummary.php:62 actions/newmessage.php:116 -#: actions/remotesubscribe.php:154 -msgid "No such user" +#: ../actions/imsettings.php:70 actions/imsettings.php:71 +#: actions/imsettings.php:137 actions/imsettings.php:143 +msgid "Send me notices through Jabber/GTalk." msgstr "" -#: actions/microsummary.php:69 -msgid "No current status" +#: ../actions/smssettings.php:97 actions/smssettings.php:97 +#: actions/smssettings.php:162 actions/smssettings.php:174 +msgid "" +"Send me notices through SMS; I understand I may incur exorbitant charges " +"from my carrier." msgstr "" -#: actions/newgroup.php:53 -msgid "New group" +#: ../actions/imsettings.php:76 actions/imsettings.php:77 +#: actions/imsettings.php:147 actions/imsettings.php:153 +msgid "Send me replies through Jabber/GTalk from people I'm not subscribed to." msgstr "" -#: actions/newgroup.php:110 -msgid "Use this form to create a new group." +#: ../lib/util.php:304 lib/util.php:320 lib/facebookaction.php:215 +#: lib/facebookaction.php:228 lib/facebookaction.php:230 +msgid "Settings" msgstr "" -#: actions/newmessage.php:71 actions/newmessage.php:231 -msgid "New message" +#: ../actions/profilesettings.php:192 actions/profilesettings.php:307 +#: actions/profilesettings.php:319 actions/profilesettings.php:318 +#: actions/profilesettings.php:344 +msgid "Settings saved." msgstr "" -#: actions/newmessage.php:121 actions/newmessage.php:161 lib/command.php:367 -msgid "You can't send a message to this user." +#: ../actions/tag.php:60 actions/tag.php:60 +msgid "Showing most popular tags from the last week" msgstr "" -#: actions/newmessage.php:144 actions/newnotice.php:136 lib/command.php:351 -#: lib/command.php:424 -msgid "No content!" +#: ../actions/finishaddopenid.php:66 actions/finishaddopenid.php:66 +#: actions/finishaddopenid.php:114 +msgid "Someone else already has this OpenID." msgstr "" -#: actions/newmessage.php:158 -msgid "No recipient specified." +#: ../actions/finishopenidlogin.php:42 ../actions/openidsettings.php:126 +#: actions/finishopenidlogin.php:47 actions/openidsettings.php:135 +#: actions/finishopenidlogin.php:52 actions/openidsettings.php:202 +msgid "Something weird happened." msgstr "" -#: actions/newmessage.php:164 lib/command.php:370 -msgid "" -"Don't send a message to yourself; just say it to yourself quietly instead." +#: ../scripts/maildaemon.php:58 scripts/maildaemon.php:58 +#: scripts/maildaemon.php:61 scripts/maildaemon.php:60 +msgid "Sorry, no incoming email allowed." msgstr "" -#: actions/newmessage.php:181 -msgid "Message sent" +#: ../scripts/maildaemon.php:54 scripts/maildaemon.php:54 +#: scripts/maildaemon.php:57 scripts/maildaemon.php:56 +msgid "Sorry, that is not your incoming email address." msgstr "" -#: actions/newmessage.php:185 lib/command.php:375 -#, php-format -msgid "Direct message to %s sent" +#: ../lib/util.php:330 lib/util.php:346 lib/action.php:574 lib/action.php:667 +#: lib/action.php:717 lib/action.php:732 +msgid "Source" msgstr "" -#: actions/newmessage.php:210 actions/newnotice.php:233 lib/channel.php:170 -msgid "Ajax Error" +#: ../actions/showstream.php:296 actions/showstream.php:311 +#: actions/showstream.php:476 actions/showgroup.php:375 +#: actions/showgroup.php:421 lib/profileaction.php:173 +#: actions/showgroup.php:429 +msgid "Statistics" msgstr "" -#: actions/newnotice.php:69 -msgid "New notice" +#: ../actions/finishopenidlogin.php:182 ../actions/finishopenidlogin.php:246 +#: actions/finishopenidlogin.php:188 actions/finishopenidlogin.php:252 +#: actions/finishopenidlogin.php:222 actions/finishopenidlogin.php:290 +#: actions/finishopenidlogin.php:295 actions/finishopenidlogin.php:238 +#: actions/finishopenidlogin.php:318 +msgid "Stored OpenID not found." msgstr "" -#: actions/newnotice.php:199 -msgid "Notice posted" +#: ../actions/remotesubscribe.php:75 ../actions/showstream.php:188 +#: ../actions/showstream.php:197 actions/remotesubscribe.php:84 +#: actions/showstream.php:197 actions/showstream.php:206 +#: actions/remotesubscribe.php:113 actions/showstream.php:376 +#: lib/subscribeform.php:139 actions/showstream.php:345 +#: actions/remotesubscribe.php:137 actions/showstream.php:439 +#: lib/userprofile.php:321 +msgid "Subscribe" msgstr "" -#: actions/noticesearch.php:68 -#, php-format -msgid "" -"Search for notices on %%site.name%% by their contents. Separate search terms " -"by spaces; they must be 3 characters or more." +#: ../actions/showstream.php:313 ../actions/subscribers.php:27 +#: actions/showstream.php:328 actions/subscribers.php:27 +#: actions/showstream.php:436 actions/showstream.php:498 +#: lib/subgroupnav.php:88 lib/profileaction.php:140 lib/profileaction.php:200 +#: lib/subgroupnav.php:90 +msgid "Subscribers" msgstr "" -#: actions/noticesearch.php:78 -msgid "Text search" +#: ../actions/userauthorization.php:310 actions/userauthorization.php:322 +#: actions/userauthorization.php:338 actions/userauthorization.php:344 +#: actions/userauthorization.php:378 actions/userauthorization.php:247 +msgid "Subscription authorized" msgstr "" -#: actions/noticesearch.php:91 -#, php-format -msgid "Search results for \"%s\" on %s" +#: ../actions/userauthorization.php:320 actions/userauthorization.php:332 +#: actions/userauthorization.php:349 actions/userauthorization.php:355 +#: actions/userauthorization.php:389 actions/userauthorization.php:259 +msgid "Subscription rejected" msgstr "" -#: actions/noticesearch.php:121 -#, php-format -msgid "" -"Be the first to [post on this topic](%%%%action.newnotice%%%%?" -"status_textarea=%s)!" +#: ../actions/showstream.php:230 ../actions/showstream.php:307 +#: ../actions/subscriptions.php:27 actions/showstream.php:240 +#: actions/showstream.php:322 actions/subscriptions.php:27 +#: actions/showstream.php:407 actions/showstream.php:489 +#: lib/subgroupnav.php:80 lib/profileaction.php:109 lib/profileaction.php:191 +#: lib/subgroupnav.php:82 +msgid "Subscriptions" msgstr "" -#: actions/noticesearch.php:124 -#, php-format -msgid "" -"Why not [register an account](%%%%action.register%%%%) and be the first to " -"[post on this topic](%%%%action.newnotice%%%%?status_textarea=%s)!" +#: ../actions/avatar.php:87 actions/profilesettings.php:324 +#: lib/imagefile.php:78 lib/imagefile.php:82 lib/imagefile.php:83 +#: lib/imagefile.php:88 lib/mediafile.php:170 +msgid "System error uploading file." msgstr "" -#: actions/noticesearchrss.php:89 -#, php-format -msgid "Updates with \"%s\"" +#: ../actions/tag.php:41 ../lib/util.php:301 actions/tag.php:41 +#: lib/util.php:317 actions/profilesettings.php:122 actions/showstream.php:297 +#: actions/tagother.php:147 actions/tagother.php:207 lib/profilelist.php:162 +#: lib/profilelist.php:164 actions/showstream.php:290 actions/tagother.php:149 +#: actions/tagother.php:209 lib/profilelist.php:160 +#: actions/profilesettings.php:123 actions/showstream.php:255 +#: lib/subscriptionlist.php:106 lib/subscriptionlist.php:108 +#: actions/profilesettings.php:138 actions/showstream.php:327 +#: lib/userprofile.php:209 +msgid "Tags" msgstr "" -#: actions/noticesearchrss.php:91 -#, php-format -msgid "Updates matching search term \"%1$s\" on %2$s!" +#: ../lib/searchaction.php:104 lib/searchaction.php:104 +#: lib/designsettings.php:217 +msgid "Text" msgstr "" -#: actions/nudge.php:85 -msgid "" -"This user doesn't allow nudges or hasn't confirmed or set his email yet." +#: ../actions/noticesearch.php:34 actions/noticesearch.php:34 +#: actions/noticesearch.php:67 actions/noticesearch.php:78 +msgid "Text search" msgstr "" -#: actions/nudge.php:94 -msgid "Nudge sent" +#: ../actions/openidsettings.php:140 actions/openidsettings.php:149 +#: actions/openidsettings.php:227 +msgid "That OpenID does not belong to you." msgstr "" -#: actions/nudge.php:97 -msgid "Nudge sent!" +#: ../actions/confirmaddress.php:52 actions/confirmaddress.php:52 +#: actions/confirmaddress.php:94 +msgid "That address has already been confirmed." msgstr "" -#: actions/oembed.php:79 actions/shownotice.php:100 -msgid "Notice has no profile" +#: ../actions/confirmaddress.php:43 actions/confirmaddress.php:43 +#: actions/confirmaddress.php:85 +msgid "That confirmation code is not for you!" msgstr "" -#: actions/oembed.php:86 actions/shownotice.php:180 -#, php-format -msgid "%1$s's status on %2$s" +#: ../actions/emailsettings.php:191 actions/emailsettings.php:209 +#: actions/emailsettings.php:328 actions/emailsettings.php:336 +msgid "That email address already belongs to another user." msgstr "" -#: actions/oembed.php:157 -msgid "content type " +#: ../actions/avatar.php:80 actions/profilesettings.php:317 +#: lib/imagefile.php:71 +msgid "That file is too big." msgstr "" -#: actions/oembed.php:160 -msgid "Only " +#: ../actions/imsettings.php:170 actions/imsettings.php:178 +#: actions/imsettings.php:293 actions/imsettings.php:299 +msgid "That is already your Jabber ID." msgstr "" -#: actions/oembed.php:181 actions/oembed.php:200 lib/api.php:963 -#: lib/api.php:991 lib/api.php:1101 -msgid "Not a supported data format." +#: ../actions/emailsettings.php:188 actions/emailsettings.php:206 +#: actions/emailsettings.php:318 actions/emailsettings.php:325 +#: actions/emailsettings.php:333 +msgid "That is already your email address." msgstr "" -#: actions/opensearch.php:64 -msgid "User Search" +#: ../actions/smssettings.php:188 actions/smssettings.php:196 +#: actions/smssettings.php:306 actions/smssettings.php:318 +msgid "That is already your phone number." msgstr "" -#: actions/opensearch.php:67 -msgid "Notice Search" +#: ../actions/imsettings.php:233 actions/imsettings.php:241 +#: actions/imsettings.php:381 actions/imsettings.php:387 +msgid "That is not your Jabber ID." msgstr "" -#: actions/othersettings.php:60 -msgid "Other Settings" +#: ../actions/emailsettings.php:249 actions/emailsettings.php:267 +#: actions/emailsettings.php:397 actions/emailsettings.php:404 +#: actions/emailsettings.php:412 +msgid "That is not your email address." msgstr "" -#: actions/othersettings.php:71 -msgid "Manage various other options." +#: ../actions/smssettings.php:257 actions/smssettings.php:265 +#: actions/smssettings.php:393 actions/smssettings.php:405 +msgid "That is not your phone number." msgstr "" -#: actions/othersettings.php:117 -msgid "Shorten URLs with" +#: ../actions/emailsettings.php:226 ../actions/imsettings.php:210 +#: actions/emailsettings.php:244 actions/imsettings.php:218 +#: actions/emailsettings.php:367 actions/imsettings.php:349 +#: actions/emailsettings.php:374 actions/emailsettings.php:382 +#: actions/imsettings.php:355 +msgid "That is the wrong IM address." msgstr "" -#: actions/othersettings.php:118 -msgid "Automatic shortening service to use." +#: ../actions/smssettings.php:233 actions/smssettings.php:241 +#: actions/smssettings.php:362 actions/smssettings.php:374 +msgid "That is the wrong confirmation number." msgstr "" -#: actions/othersettings.php:122 -msgid "View profile designs" +#: ../actions/smssettings.php:191 actions/smssettings.php:199 +#: actions/smssettings.php:309 actions/smssettings.php:321 +msgid "That phone number already belongs to another user." msgstr "" -#: actions/othersettings.php:123 -msgid "Show or hide profile designs." +#: ../actions/newnotice.php:49 ../actions/twitapistatuses.php:408 +#: actions/newnotice.php:49 actions/twitapistatuses.php:330 +#: actions/facebookhome.php:243 actions/twitapistatuses.php:276 +#: actions/newnotice.php:136 actions/twitapistatuses.php:294 +#: lib/facebookaction.php:485 actions/newnotice.php:166 +#: actions/twitapistatuses.php:251 lib/facebookaction.php:477 +#: scripts/maildaemon.php:70 +msgid "That's too long. Max notice size is 140 chars." msgstr "" -#: actions/othersettings.php:153 -msgid "URL shortening service is too long (max 50 chars)." +#: ../actions/twitapiaccount.php:74 actions/twitapiaccount.php:72 +#: actions/twitapiaccount.php:62 actions/twitapiaccount.php:63 +#: actions/twitapiaccount.php:66 +msgid "That's too long. Max notice size is 255 chars." msgstr "" -#: actions/outbox.php:58 +#: ../actions/confirmaddress.php:92 actions/confirmaddress.php:92 +#: actions/confirmaddress.php:159 #, php-format -msgid "Outbox for %s - page %d" +msgid "The address \"%s\" has been confirmed for your account." msgstr "" -#: actions/outbox.php:61 -#, php-format -msgid "Outbox for %s" +#: ../actions/emailsettings.php:264 ../actions/imsettings.php:250 +#: ../actions/smssettings.php:274 actions/emailsettings.php:282 +#: actions/imsettings.php:258 actions/smssettings.php:282 +#: actions/emailsettings.php:416 actions/imsettings.php:402 +#: actions/smssettings.php:413 actions/emailsettings.php:423 +#: actions/emailsettings.php:431 actions/imsettings.php:408 +#: actions/smssettings.php:425 +msgid "The address was removed." msgstr "" -#: actions/outbox.php:116 -msgid "This is your outbox, which lists private messages you have sent." +#: ../actions/userauthorization.php:312 actions/userauthorization.php:346 +#: actions/userauthorization.php:380 +msgid "" +"The subscription has been authorized, but no callback URL was passed. Check " +"with the site's instructions for details on how to authorize the " +"subscription. Your subscription token is:" msgstr "" -#: actions/passwordsettings.php:58 -msgid "Change password" +#: ../actions/userauthorization.php:322 actions/userauthorization.php:357 +#: actions/userauthorization.php:391 +msgid "" +"The subscription has been rejected, but no callback URL was passed. Check " +"with the site's instructions for details on how to fully reject the " +"subscription." msgstr "" -#: actions/passwordsettings.php:69 -msgid "Change your password." +#: ../actions/subscribers.php:35 actions/subscribers.php:35 +#: actions/subscribers.php:67 +#, php-format +msgid "These are the people who listen to %s's notices." msgstr "" -#: actions/passwordsettings.php:95 actions/recoverpassword.php:231 -msgid "Password change" +#: ../actions/subscribers.php:33 actions/subscribers.php:33 +#: actions/subscribers.php:63 +msgid "These are the people who listen to your notices." msgstr "" -#: actions/passwordsettings.php:103 -msgid "Old password" +#: ../actions/subscriptions.php:35 actions/subscriptions.php:35 +#: actions/subscriptions.php:69 +#, php-format +msgid "These are the people whose notices %s listens to." msgstr "" -#: actions/passwordsettings.php:107 actions/recoverpassword.php:235 -msgid "New password" +#: ../actions/subscriptions.php:33 actions/subscriptions.php:33 +#: actions/subscriptions.php:65 +msgid "These are the people whose notices you listen to." msgstr "" -#: actions/passwordsettings.php:108 -msgid "6 or more characters" +#: ../actions/invite.php:89 actions/invite.php:96 actions/invite.php:128 +#: actions/invite.php:130 actions/invite.php:136 +msgid "" +"These people are already users and you were automatically subscribed to them:" msgstr "" -#: actions/passwordsettings.php:111 actions/recoverpassword.php:239 -#: actions/register.php:432 actions/smssettings.php:134 -msgid "Confirm" +#: ../actions/recoverpassword.php:88 actions/recoverpassword.php:97 +msgid "This confirmation code is too old. Please start again." msgstr "" -#: actions/passwordsettings.php:112 -msgid "same as password above" +#: ../lib/openid.php:195 lib/openid.php:206 +msgid "" +"This form should automatically submit itself. If not, click the submit " +"button to go to your OpenID provider." msgstr "" -#: actions/passwordsettings.php:116 -msgid "Change" +#: ../actions/finishopenidlogin.php:56 actions/finishopenidlogin.php:61 +#: actions/finishopenidlogin.php:67 actions/finishopenidlogin.php:66 +#, php-format +msgid "" +"This is the first time you've logged into %s so we must connect your OpenID " +"to a local account. You can either create a new account, or connect with " +"your existing account, if you have one." +msgstr "" + +#: ../actions/twitapifriendships.php:108 ../actions/twitapistatuses.php:586 +#: actions/twitapifavorites.php:127 actions/twitapifriendships.php:108 +#: actions/twitapistatuses.php:511 actions/twitapifavorites.php:97 +#: actions/twitapifriendships.php:85 actions/twitapistatuses.php:436 +#: actions/twitapifavorites.php:103 actions/twitapistatuses.php:460 +#: actions/twitapifavorites.php:154 actions/twitapifriendships.php:90 +#: actions/twitapistatuses.php:416 actions/apistatusesdestroy.php:107 +msgid "This method requires a POST or DELETE." msgstr "" -#: actions/passwordsettings.php:153 actions/register.php:230 -msgid "Password must be 6 or more characters." +#: ../actions/twitapiaccount.php:65 ../actions/twitapifriendships.php:44 +#: ../actions/twitapistatuses.php:381 actions/twitapiaccount.php:63 +#: actions/twitapidirect_messages.php:114 actions/twitapifriendships.php:44 +#: actions/twitapistatuses.php:303 actions/twitapiaccount.php:53 +#: actions/twitapidirect_messages.php:122 actions/twitapifriendships.php:32 +#: actions/twitapistatuses.php:244 actions/twitapiaccount.php:54 +#: actions/twitapidirect_messages.php:131 actions/twitapistatuses.php:262 +#: actions/twitapiaccount.php:56 actions/twitapidirect_messages.php:124 +#: actions/twitapifriendships.php:34 actions/twitapistatuses.php:216 +#: actions/apiblockcreate.php:89 actions/apiblockdestroy.php:88 +#: actions/apidirectmessagenew.php:117 actions/apifavoritecreate.php:90 +#: actions/apifavoritedestroy.php:91 actions/apifriendshipscreate.php:91 +#: actions/apifriendshipsdestroy.php:91 actions/apigroupcreate.php:104 +#: actions/apigroupjoin.php:91 actions/apigroupleave.php:91 +#: actions/apistatusesupdate.php:109 +#: actions/apiaccountupdateprofileimage.php:84 +msgid "This method requires a POST." msgstr "" -#: actions/passwordsettings.php:156 actions/register.php:233 -msgid "Passwords don't match." +#: ../lib/util.php:164 lib/util.php:246 lib/htmloutputter.php:104 +msgid "This page is not available in a media type you accept" msgstr "" -#: actions/passwordsettings.php:164 -msgid "Incorrect old password" +#: ../actions/profilesettings.php:63 actions/profilesettings.php:96 +#: actions/profilesettings.php:138 actions/profilesettings.php:139 +#: actions/profilesettings.php:154 +msgid "Timezone" msgstr "" -#: actions/passwordsettings.php:180 -msgid "Error saving user; invalid." +#: ../actions/profilesettings.php:107 actions/profilesettings.php:222 +#: actions/profilesettings.php:211 actions/profilesettings.php:212 +#: actions/profilesettings.php:228 +msgid "Timezone not selected." msgstr "" -#: actions/passwordsettings.php:185 actions/recoverpassword.php:368 -msgid "Can't save new password." +#: ../actions/remotesubscribe.php:43 actions/remotesubscribe.php:74 +#: actions/remotesubscribe.php:98 +#, php-format +msgid "" +"To subscribe, you can [login](%%action.login%%), or [register](%%action." +"register%%) a new account. If you already have an account on a [compatible " +"microblogging site](%%doc.openmublog%%), enter your profile URL below." msgstr "" -#: actions/passwordsettings.php:191 actions/recoverpassword.php:211 -msgid "Password saved." +#: ../actions/twitapifriendships.php:163 actions/twitapifriendships.php:167 +#: actions/twitapifriendships.php:132 actions/twitapifriendships.php:139 +#: actions/apifriendshipsexists.php:103 actions/apifriendshipsexists.php:94 +msgid "Two user ids or screen_names must be supplied." msgstr "" -#: actions/peoplesearch.php:52 -#, php-format -msgid "" -"Search for users on %%site.name%% by their name, location, or interests. " -"Separate the terms by spaces; they must be 3 characters or more." +#: ../actions/profilesettings.php:48 ../actions/register.php:169 +#: actions/profilesettings.php:81 actions/register.php:183 +#: actions/profilesettings.php:109 actions/register.php:398 +#: actions/register.php:444 actions/profilesettings.php:117 +#: actions/register.php:448 actions/register.php:454 +msgid "URL of your homepage, blog, or profile on another site" msgstr "" -#: actions/peoplesearch.php:58 -msgid "People search" +#: ../actions/remotesubscribe.php:74 actions/remotesubscribe.php:83 +#: actions/remotesubscribe.php:110 actions/remotesubscribe.php:134 +msgid "URL of your profile on another compatible microblogging service" msgstr "" -#: actions/peopletag.php:70 -#, php-format -msgid "Not a valid user tag: %s" +#: ../actions/emailsettings.php:130 ../actions/imsettings.php:110 +#: ../actions/recoverpassword.php:39 ../actions/smssettings.php:135 +#: actions/emailsettings.php:144 actions/imsettings.php:118 +#: actions/recoverpassword.php:39 actions/smssettings.php:143 +#: actions/twittersettings.php:108 actions/avatarsettings.php:258 +#: actions/emailsettings.php:242 actions/grouplogo.php:317 +#: actions/imsettings.php:214 actions/recoverpassword.php:44 +#: actions/smssettings.php:236 actions/twittersettings.php:302 +#: actions/avatarsettings.php:263 actions/emailsettings.php:247 +#: actions/grouplogo.php:324 actions/twittersettings.php:306 +#: actions/twittersettings.php:322 lib/designsettings.php:301 +#: actions/emailsettings.php:255 actions/grouplogo.php:319 +#: actions/imsettings.php:220 actions/smssettings.php:248 +#: actions/avatarsettings.php:277 lib/designsettings.php:304 +msgid "Unexpected form submission." msgstr "" -#: actions/peopletag.php:144 -#, php-format -msgid "Users self-tagged with %s - page %d" +#: ../actions/recoverpassword.php:276 actions/recoverpassword.php:289 +#: actions/recoverpassword.php:323 actions/recoverpassword.php:341 +#: actions/recoverpassword.php:344 +msgid "Unexpected password reset." msgstr "" -#: actions/postnotice.php:84 -msgid "Invalid notice content" +#: ../index.php:57 index.php:57 actions/recoverpassword.php:202 +#: actions/recoverpassword.php:210 actions/recoverpassword.php:213 +msgid "Unknown action" msgstr "" -#: actions/postnotice.php:90 -#, php-format -msgid "Notice license ‘%s’ is not compatible with site license ‘%s’." +#: ../actions/finishremotesubscribe.php:58 +#: actions/finishremotesubscribe.php:60 actions/finishremotesubscribe.php:61 +msgid "Unknown version of OMB protocol." msgstr "" -#: actions/profilesettings.php:60 -msgid "Profile settings" +#: ../lib/util.php:269 lib/util.php:285 +msgid "" +"Unless otherwise specified, contents of this site are copyright by the " +"contributors and available under the " msgstr "" -#: actions/profilesettings.php:71 -msgid "" -"You can update your personal profile info here so readers know more about " -"you." +#: ../actions/confirmaddress.php:48 actions/confirmaddress.php:48 +#: actions/confirmaddress.php:90 +#, php-format +msgid "Unrecognized address type %s" msgstr "" -#: actions/profilesettings.php:99 -msgid "Profile information" +#: ../actions/showstream.php:209 actions/showstream.php:219 +#: lib/unsubscribeform.php:137 +msgid "Unsubscribe" msgstr "" -#: actions/profilesettings.php:108 lib/groupeditform.php:154 -msgid "1-64 lowercase letters or numbers, no punctuation or spaces" +#: ../actions/postnotice.php:44 ../actions/updateprofile.php:45 +#: actions/postnotice.php:45 actions/updateprofile.php:46 +#: actions/postnotice.php:48 actions/updateprofile.php:49 +#: actions/updateprofile.php:51 +msgid "Unsupported OMB version" msgstr "" -#: actions/profilesettings.php:111 actions/register.php:447 -#: actions/showgroup.php:247 actions/tagother.php:104 -#: lib/groupeditform.php:157 lib/userprofile.php:149 -msgid "Full name" +#: ../actions/avatar.php:105 actions/profilesettings.php:342 +#: lib/imagefile.php:102 lib/imagefile.php:99 lib/imagefile.php:100 +#: lib/imagefile.php:105 +msgid "Unsupported image file format." msgstr "" -#: actions/profilesettings.php:115 actions/register.php:452 -#: lib/groupeditform.php:161 -msgid "Homepage" +#: ../lib/settingsaction.php:100 lib/settingsaction.php:94 +#: lib/connectsettingsaction.php:108 lib/connectsettingsaction.php:116 +msgid "Updates by SMS" msgstr "" -#: actions/profilesettings.php:117 actions/register.php:454 -msgid "URL of your homepage, blog, or profile on another site" +#: ../lib/settingsaction.php:103 lib/settingsaction.php:97 +#: lib/connectsettingsaction.php:105 lib/connectsettingsaction.php:111 +msgid "Updates by instant messenger (IM)" msgstr "" -#: actions/profilesettings.php:122 actions/register.php:460 +#: ../actions/twitapistatuses.php:241 actions/twitapistatuses.php:158 +#: actions/twitapistatuses.php:129 actions/twitapistatuses.php:134 +#: actions/twitapistatuses.php:94 actions/allrss.php:119 +#: actions/apitimelinefriends.php:121 #, php-format -msgid "Describe yourself and your interests in %d chars" +msgid "Updates from %1$s and friends on %2$s!" msgstr "" -#: actions/profilesettings.php:125 actions/register.php:463 -msgid "Describe yourself and your interests" +#: ../actions/twitapistatuses.php:341 actions/twitapistatuses.php:268 +#: actions/twitapistatuses.php:202 actions/twitapistatuses.php:213 +#: actions/twitapigroups.php:74 actions/twitapistatuses.php:159 +#: actions/apitimelinegroup.php:110 actions/apitimelineuser.php:125 +#: actions/userrss.php:92 +#, php-format +msgid "Updates from %1$s on %2$s!" msgstr "" -#: actions/profilesettings.php:127 actions/register.php:465 -msgid "Bio" +#: ../actions/avatar.php:68 actions/profilesettings.php:161 +#: actions/avatarsettings.php:162 actions/grouplogo.php:232 +#: actions/avatarsettings.php:165 actions/grouplogo.php:238 +#: actions/grouplogo.php:233 +msgid "Upload" msgstr "" -#: actions/profilesettings.php:132 actions/register.php:470 -#: actions/showgroup.php:256 actions/tagother.php:112 -#: actions/userauthorization.php:158 lib/groupeditform.php:177 -#: lib/userprofile.php:164 -msgid "Location" +#: ../actions/avatar.php:27 +msgid "" +"Upload a new \"avatar\" (user image) here. You can't edit the picture after " +"you upload it, so make sure it's more or less square. It must be under the " +"site license, also. Use a picture that belongs to you and that you want to " +"share." msgstr "" -#: actions/profilesettings.php:134 actions/register.php:472 -msgid "Where you are, like \"City, State (or Region), Country\"" +#: ../lib/settingsaction.php:91 +msgid "Upload a new profile image" msgstr "" -#: actions/profilesettings.php:138 actions/tagother.php:149 -#: actions/tagother.php:209 lib/subscriptionlist.php:106 -#: lib/subscriptionlist.php:108 lib/userprofile.php:209 -msgid "Tags" +#: ../actions/invite.php:114 actions/invite.php:121 actions/invite.php:154 +#: actions/invite.php:156 actions/invite.php:162 +msgid "" +"Use this form to invite your friends and colleagues to use this service." msgstr "" -#: actions/profilesettings.php:140 -msgid "" -"Tags for yourself (letters, numbers, -, ., and _), comma- or space- separated" +#: ../actions/register.php:159 ../actions/register.php:162 +#: actions/register.php:173 actions/register.php:176 actions/register.php:382 +#: actions/register.php:386 actions/register.php:428 actions/register.php:432 +#: actions/register.php:436 actions/register.php:438 actions/register.php:442 +msgid "Used only for updates, announcements, and password recovery" msgstr "" -#: actions/profilesettings.php:144 -msgid "Language" +#: ../actions/finishremotesubscribe.php:86 +#: actions/finishremotesubscribe.php:88 actions/finishremotesubscribe.php:94 +msgid "User being listened to doesn't exist." +msgstr "" + +#: ../actions/all.php:41 ../actions/avatarbynickname.php:48 +#: ../actions/foaf.php:47 ../actions/replies.php:41 +#: ../actions/showstream.php:44 ../actions/twitapiaccount.php:82 +#: ../actions/twitapistatuses.php:319 ../actions/twitapistatuses.php:685 +#: ../actions/twitapiusers.php:82 actions/all.php:41 +#: actions/avatarbynickname.php:48 actions/foaf.php:47 actions/replies.php:41 +#: actions/showfavorites.php:41 actions/showstream.php:44 +#: actions/twitapiaccount.php:80 actions/twitapifavorites.php:68 +#: actions/twitapistatuses.php:235 actions/twitapistatuses.php:609 +#: actions/twitapiusers.php:87 lib/mailbox.php:50 +#: actions/avatarbynickname.php:80 actions/foaf.php:48 actions/replies.php:80 +#: actions/showstream.php:107 actions/twitapiaccount.php:70 +#: actions/twitapifavorites.php:42 actions/twitapistatuses.php:167 +#: actions/twitapistatuses.php:503 actions/twitapiusers.php:55 +#: actions/usergroups.php:99 lib/galleryaction.php:67 lib/twitterapi.php:626 +#: actions/twitapiaccount.php:71 actions/twitapistatuses.php:179 +#: actions/twitapistatuses.php:535 actions/twitapiusers.php:59 +#: actions/foaf.php:65 actions/replies.php:79 actions/twitapiusers.php:57 +#: actions/usergroups.php:98 lib/galleryaction.php:66 lib/profileaction.php:84 +#: actions/apiusershow.php:108 actions/apiaccountupdateprofileimage.php:124 +#: actions/apiaccountupdateprofileimage.php:130 +msgid "User has no profile." msgstr "" -#: actions/profilesettings.php:145 -msgid "Preferred language" +#: ../actions/remotesubscribe.php:71 actions/remotesubscribe.php:80 +#: actions/remotesubscribe.php:105 actions/remotesubscribe.php:129 +msgid "User nickname" msgstr "" -#: actions/profilesettings.php:154 -msgid "Timezone" +#: ../actions/twitapiusers.php:75 actions/twitapiusers.php:80 +msgid "User not found." msgstr "" +#: ../actions/profilesettings.php:63 actions/profilesettings.php:96 +#: actions/profilesettings.php:139 actions/profilesettings.php:140 #: actions/profilesettings.php:155 msgid "What timezone are you normally in?" msgstr "" -#: actions/profilesettings.php:160 -msgid "" -"Automatically subscribe to whoever subscribes to me (best for non-humans)" +#: ../lib/util.php:1159 lib/util.php:1293 lib/noticeform.php:141 +#: lib/noticeform.php:158 +#, php-format +msgid "What's up, %s?" +msgstr "" + +#: ../actions/profilesettings.php:54 ../actions/register.php:175 +#: actions/profilesettings.php:87 actions/register.php:189 +#: actions/profilesettings.php:119 actions/register.php:410 +#: actions/register.php:456 actions/profilesettings.php:134 +#: actions/register.php:466 actions/register.php:472 +msgid "Where you are, like \"City, State (or Region), Country\"" msgstr "" -#: actions/profilesettings.php:221 actions/register.php:223 +#: ../actions/updateprofile.php:128 actions/updateprofile.php:129 +#: actions/updateprofile.php:132 actions/updateprofile.php:134 #, php-format -msgid "Bio is too long (max %d chars)." +msgid "Wrong image type for '%s'" msgstr "" -#: actions/profilesettings.php:228 -msgid "Timezone not selected." +#: ../actions/updateprofile.php:123 actions/updateprofile.php:124 +#: actions/updateprofile.php:127 actions/updateprofile.php:129 +#, php-format +msgid "Wrong size image at '%s'" msgstr "" -#: actions/profilesettings.php:234 -msgid "Language is too long (max 50 chars)." +#: ../actions/deletenotice.php:63 ../actions/deletenotice.php:72 +#: actions/deletenotice.php:64 actions/deletenotice.php:79 +#: actions/block.php:148 actions/deletenotice.php:122 +#: actions/deletenotice.php:141 actions/deletenotice.php:115 +#: actions/block.php:150 actions/deletenotice.php:116 +#: actions/groupblock.php:177 actions/deletenotice.php:146 +msgid "Yes" msgstr "" -#: actions/profilesettings.php:246 actions/tagother.php:178 -#, php-format -msgid "Invalid tag: \"%s\"" +#: ../actions/finishaddopenid.php:64 actions/finishaddopenid.php:64 +#: actions/finishaddopenid.php:112 +msgid "You already have this OpenID!" msgstr "" -#: actions/profilesettings.php:295 -msgid "Couldn't update user for autosubscribe." +#: ../actions/deletenotice.php:37 actions/deletenotice.php:37 +msgid "" +"You are about to permanently delete a notice. Once this is done, it cannot " +"be undone." msgstr "" -#: actions/profilesettings.php:328 -msgid "Couldn't save profile." +#: ../actions/recoverpassword.php:31 actions/recoverpassword.php:31 +#: actions/recoverpassword.php:36 +msgid "You are already logged in!" msgstr "" -#: actions/profilesettings.php:336 -msgid "Couldn't save tags." +#: ../actions/invite.php:81 actions/invite.php:88 actions/invite.php:120 +#: actions/invite.php:122 actions/invite.php:128 +msgid "You are already subscribed to these users:" msgstr "" -#: actions/profilesettings.php:344 -msgid "Settings saved." +#: ../actions/twitapifriendships.php:128 actions/twitapifriendships.php:128 +#: actions/twitapifriendships.php:105 actions/twitapifriendships.php:111 +msgid "You are not friends with the specified user." +msgstr "" + +#: ../actions/password.php:27 +msgid "You can change your password here. Choose a good one!" msgstr "" -#: actions/public.php:83 +#: ../actions/register.php:135 actions/register.php:145 +msgid "You can create a new account to start posting notices." +msgstr "" + +#: ../actions/smssettings.php:28 actions/smssettings.php:28 +#: actions/smssettings.php:69 #, php-format -msgid "Beyond the page limit (%s)" +msgid "You can receive SMS messages through email from %%site.name%%." msgstr "" -#: actions/public.php:92 -msgid "Could not retrieve public stream." +#: ../actions/openidsettings.php:86 actions/openidsettings.php:143 +msgid "" +"You can remove an OpenID from your account by clicking the button marked " +"\"Remove\"." msgstr "" -#: actions/public.php:129 +#: ../actions/imsettings.php:28 actions/imsettings.php:28 +#: actions/imsettings.php:70 #, php-format -msgid "Public timeline, page %d" +msgid "" +"You can send and receive notices through Jabber/GTalk [instant messages](%%" +"doc.im%%). Configure your address and settings below." msgstr "" -#: actions/public.php:131 lib/publicgroupnav.php:79 -msgid "Public timeline" +#: ../actions/profilesettings.php:27 actions/profilesettings.php:69 +#: actions/profilesettings.php:71 +msgid "" +"You can update your personal profile info here so people know more about you." msgstr "" -#: actions/public.php:151 -msgid "Public Stream Feed (RSS 1.0)" +#: ../actions/finishremotesubscribe.php:31 ../actions/remotesubscribe.php:31 +#: actions/finishremotesubscribe.php:31 actions/remotesubscribe.php:31 +#: actions/finishremotesubscribe.php:33 actions/finishremotesubscribe.php:85 +#: actions/finishremotesubscribe.php:101 actions/remotesubscribe.php:35 +#: actions/finishremotesubscribe.php:87 actions/remotesubscribe.php:59 +msgid "You can use the local subscription!" msgstr "" -#: actions/public.php:155 -msgid "Public Stream Feed (RSS 2.0)" +#: ../actions/finishopenidlogin.php:33 ../actions/register.php:61 +#: actions/finishopenidlogin.php:38 actions/register.php:68 +#: actions/finishopenidlogin.php:43 actions/register.php:149 +#: actions/register.php:186 actions/register.php:192 actions/register.php:198 +msgid "You can't register if you don't agree to the license." msgstr "" -#: actions/public.php:159 -msgid "Public Stream Feed (Atom)" +#: ../actions/updateprofile.php:63 actions/updateprofile.php:64 +#: actions/updateprofile.php:67 actions/updateprofile.php:69 +msgid "You did not send us that profile" msgstr "" -#: actions/public.php:179 +#: ../lib/mail.php:147 lib/mail.php:289 lib/mail.php:288 #, php-format msgid "" -"This is the public timeline for %%site.name%% but no one has posted anything " -"yet." +"You have a new posting address on %1$s.\n" +"\n" +"Send email to %2$s to post new messages.\n" +"\n" +"More email instructions at %3$s.\n" +"\n" +"Faithfully yours,\n" +"%4$s" msgstr "" -#: actions/public.php:182 -msgid "Be the first to post!" +#: ../actions/twitapistatuses.php:612 actions/twitapistatuses.php:537 +#: actions/twitapistatuses.php:463 actions/twitapistatuses.php:486 +#: actions/twitapistatuses.php:443 actions/apistatusesdestroy.php:130 +msgid "You may not delete another user's status." msgstr "" -#: actions/public.php:186 +#: ../actions/invite.php:31 actions/invite.php:31 actions/invite.php:39 +#: actions/invite.php:41 #, php-format -msgid "" -"Why not [register an account](%%action.register%%) and be the first to post!" +msgid "You must be logged in to invite other users to use %s" msgstr "" -#: actions/public.php:233 -#, php-format +#: ../actions/invite.php:103 actions/invite.php:110 actions/invite.php:142 +#: actions/invite.php:144 actions/invite.php:150 msgid "" -"This is %%site.name%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-" -"blogging) service based on the Free Software [StatusNet](http://status.net/) " -"tool. [Join now](%%action.register%%) to share notices about yourself with " -"friends, family, and colleagues! ([Read more](%%doc.help%%))" +"You will be notified when your invitees accept the invitation and register " +"on the site. Thanks for growing the community!" +msgstr "" + +#: ../actions/recoverpassword.php:149 actions/recoverpassword.php:158 +msgid "You've been identified. Enter a new password below. " +msgstr "" + +#: ../actions/openidlogin.php:67 actions/openidlogin.php:76 +#: actions/openidlogin.php:104 actions/openidlogin.php:113 +msgid "Your OpenID URL" msgstr "" -#: actions/public.php:238 +#: ../actions/recoverpassword.php:164 actions/recoverpassword.php:188 +#: actions/recoverpassword.php:193 +msgid "Your nickname on this server, or your registered email address." +msgstr "" + +#: ../actions/openidsettings.php:28 actions/openidsettings.php:70 #, php-format msgid "" -"This is %%site.name%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-" -"blogging) service based on the Free Software [StatusNet](http://status.net/) " -"tool." +"[OpenID](%%doc.openid%%) lets you log into many sites with the same user " +"account. Manage your associated OpenIDs from here." msgstr "" -#: actions/publictagcloud.php:57 -msgid "Public tag cloud" +#: ../lib/util.php:943 lib/util.php:992 lib/util.php:945 lib/util.php:756 +#: lib/util.php:770 lib/util.php:816 lib/util.php:844 +msgid "a few seconds ago" msgstr "" -#: actions/publictagcloud.php:63 +#: ../lib/util.php:955 lib/util.php:1004 lib/util.php:957 lib/util.php:768 +#: lib/util.php:782 lib/util.php:828 lib/util.php:856 #, php-format -msgid "These are most popular recent tags on %s " +msgid "about %d days ago" msgstr "" -#: actions/publictagcloud.php:69 +#: ../lib/util.php:951 lib/util.php:1000 lib/util.php:953 lib/util.php:764 +#: lib/util.php:778 lib/util.php:824 lib/util.php:852 #, php-format -msgid "No one has posted a notice with a [hashtag](%%doc.tags%%) yet." +msgid "about %d hours ago" msgstr "" -#: actions/publictagcloud.php:72 -msgid "Be the first to post one!" +#: ../lib/util.php:947 lib/util.php:996 lib/util.php:949 lib/util.php:760 +#: lib/util.php:774 lib/util.php:820 lib/util.php:848 +#, php-format +msgid "about %d minutes ago" msgstr "" -#: actions/publictagcloud.php:75 +#: ../lib/util.php:959 lib/util.php:1008 lib/util.php:961 lib/util.php:772 +#: lib/util.php:786 lib/util.php:832 lib/util.php:860 #, php-format -msgid "" -"Why not [register an account](%%action.register%%) and be the first to post " -"one!" +msgid "about %d months ago" msgstr "" -#: actions/publictagcloud.php:135 -msgid "Tag cloud" +#: ../lib/util.php:953 lib/util.php:1002 lib/util.php:955 lib/util.php:766 +#: lib/util.php:780 lib/util.php:826 lib/util.php:854 +msgid "about a day ago" msgstr "" -#: actions/recoverpassword.php:36 -msgid "You are already logged in!" +#: ../lib/util.php:945 lib/util.php:994 lib/util.php:947 lib/util.php:758 +#: lib/util.php:772 lib/util.php:818 lib/util.php:846 +msgid "about a minute ago" msgstr "" -#: actions/recoverpassword.php:62 -msgid "No such recovery code." +#: ../lib/util.php:957 lib/util.php:1006 lib/util.php:959 lib/util.php:770 +#: lib/util.php:784 lib/util.php:830 lib/util.php:858 +msgid "about a month ago" msgstr "" -#: actions/recoverpassword.php:66 -msgid "Not a recovery code." +#: ../lib/util.php:961 lib/util.php:1010 lib/util.php:963 lib/util.php:774 +#: lib/util.php:788 lib/util.php:834 lib/util.php:862 +msgid "about a year ago" msgstr "" -#: actions/recoverpassword.php:73 -msgid "Recovery code for unknown user." +#: ../lib/util.php:949 lib/util.php:998 lib/util.php:951 lib/util.php:762 +#: lib/util.php:776 lib/util.php:822 lib/util.php:850 +msgid "about an hour ago" msgstr "" -#: actions/recoverpassword.php:86 -msgid "Error with confirmation code." +#: ../actions/showstream.php:423 ../lib/stream.php:132 +#: actions/showstream.php:441 lib/stream.php:99 +msgid "delete" msgstr "" -#: actions/recoverpassword.php:97 -msgid "This confirmation code is too old. Please start again." +#: ../actions/noticesearch.php:130 ../actions/showstream.php:408 +#: ../lib/stream.php:117 actions/noticesearch.php:136 +#: actions/showstream.php:426 lib/stream.php:84 actions/noticesearch.php:187 +msgid "in reply to..." msgstr "" -#: actions/recoverpassword.php:111 -msgid "Could not update user with confirmed email address." +#: ../actions/noticesearch.php:137 ../actions/showstream.php:415 +#: ../lib/stream.php:124 actions/noticesearch.php:143 +#: actions/showstream.php:433 lib/stream.php:91 actions/noticesearch.php:194 +msgid "reply" msgstr "" -#: actions/recoverpassword.php:152 -msgid "" -"If you have forgotten or lost your password, you can get a new one sent to " -"the email address you have stored in your account." +#: ../actions/password.php:44 actions/profilesettings.php:183 +#: actions/passwordsettings.php:106 actions/passwordsettings.php:112 +msgid "same as password above" msgstr "" -#: actions/recoverpassword.php:158 -msgid "You have been identified. Enter a new password below. " +#: ../actions/twitapistatuses.php:755 actions/twitapistatuses.php:678 +#: actions/twitapistatuses.php:555 actions/twitapistatuses.php:596 +#: actions/twitapistatuses.php:618 actions/twitapistatuses.php:553 +#: actions/twitapistatuses.php:575 +msgid "unsupported file type" +msgstr "" + +#: ../lib/util.php:1309 lib/util.php:1443 +msgid "« After" +msgstr "" + +#: actions/deletenotice.php:74 actions/disfavor.php:43 +#: actions/emailsettings.php:127 actions/favor.php:45 +#: actions/finishopenidlogin.php:33 actions/imsettings.php:105 +#: actions/invite.php:46 actions/newmessage.php:45 actions/openidlogin.php:36 +#: actions/openidsettings.php:123 actions/profilesettings.php:47 +#: actions/recoverpassword.php:282 actions/register.php:42 +#: actions/remotesubscribe.php:40 actions/smssettings.php:124 +#: actions/subscribe.php:44 actions/twittersettings.php:97 +#: actions/unsubscribe.php:41 actions/userauthorization.php:35 +#: actions/block.php:64 actions/disfavor.php:74 actions/favor.php:77 +#: actions/finishopenidlogin.php:38 actions/invite.php:54 actions/nudge.php:80 +#: actions/openidlogin.php:37 actions/recoverpassword.php:316 +#: actions/subscribe.php:46 actions/unblock.php:65 actions/unsubscribe.php:43 +#: actions/avatarsettings.php:251 actions/emailsettings.php:229 +#: actions/grouplogo.php:314 actions/imsettings.php:200 actions/login.php:103 +#: actions/newmessage.php:133 actions/newnotice.php:96 +#: actions/openidsettings.php:188 actions/othersettings.php:136 +#: actions/passwordsettings.php:131 actions/profilesettings.php:172 +#: actions/register.php:113 actions/remotesubscribe.php:53 +#: actions/smssettings.php:216 actions/subedit.php:38 actions/tagother.php:166 +#: actions/twittersettings.php:294 actions/userauthorization.php:39 +#: actions/favor.php:75 actions/groupblock.php:66 actions/groupunblock.php:66 +#: actions/invite.php:56 actions/makeadmin.php:66 actions/newnotice.php:102 +#: actions/othersettings.php:138 actions/recoverpassword.php:334 +#: actions/register.php:153 actions/twittersettings.php:310 +#: lib/designsettings.php:291 actions/emailsettings.php:237 +#: actions/grouplogo.php:309 actions/imsettings.php:206 actions/login.php:105 +#: actions/newmessage.php:135 actions/newnotice.php:103 +#: actions/othersettings.php:145 actions/passwordsettings.php:137 +#: actions/profilesettings.php:187 actions/recoverpassword.php:337 +#: actions/register.php:159 actions/remotesubscribe.php:77 +#: actions/smssettings.php:228 actions/unsubscribe.php:69 +#: actions/userauthorization.php:52 actions/login.php:131 +#: actions/register.php:165 actions/avatarsettings.php:265 +#: lib/designsettings.php:294 +msgid "There was a problem with your session token. Try again, please." msgstr "" -#: actions/recoverpassword.php:188 -msgid "Password recovery" +#: actions/disfavor.php:55 actions/disfavor.php:81 +msgid "This notice is not a favorite!" msgstr "" -#: actions/recoverpassword.php:191 -msgid "Nickname or email address" +#: actions/disfavor.php:63 actions/disfavor.php:87 +#: actions/twitapifavorites.php:188 actions/apifavoritedestroy.php:134 +msgid "Could not delete favorite." msgstr "" -#: actions/recoverpassword.php:193 -msgid "Your nickname on this server, or your registered email address." +#: actions/disfavor.php:72 lib/favorform.php:140 +msgid "Favor" msgstr "" -#: actions/recoverpassword.php:199 actions/recoverpassword.php:200 -msgid "Recover" +#: actions/emailsettings.php:92 actions/emailsettings.php:157 +#: actions/emailsettings.php:163 +msgid "Send me email when someone adds my notice as a favorite." msgstr "" -#: actions/recoverpassword.php:208 -msgid "Reset password" +#: actions/emailsettings.php:95 actions/emailsettings.php:163 +#: actions/emailsettings.php:169 +msgid "Send me email when someone sends me a private message." msgstr "" -#: actions/recoverpassword.php:209 -msgid "Recover password" +#: actions/favor.php:53 actions/twitapifavorites.php:142 actions/favor.php:81 +#: actions/twitapifavorites.php:118 actions/twitapifavorites.php:124 +#: actions/favor.php:79 +msgid "This notice is already a favorite!" msgstr "" -#: actions/recoverpassword.php:210 actions/recoverpassword.php:322 -msgid "Password recovery requested" +#: actions/favor.php:60 actions/twitapifavorites.php:151 +#: classes/Command.php:132 actions/favor.php:86 +#: actions/twitapifavorites.php:125 classes/Command.php:152 +#: actions/twitapifavorites.php:131 lib/command.php:152 actions/favor.php:84 +#: actions/twitapifavorites.php:133 lib/command.php:145 +#: actions/apifavoritecreate.php:130 lib/command.php:176 +msgid "Could not create favorite." msgstr "" -#: actions/recoverpassword.php:213 -msgid "Unknown action" +#: actions/favor.php:70 +msgid "Disfavor" msgstr "" -#: actions/recoverpassword.php:236 -msgid "6 or more characters, and don't forget it!" +#: actions/favoritesrss.php:60 actions/showfavorites.php:47 +#: actions/favoritesrss.php:100 actions/showfavorites.php:77 +#: actions/favoritesrss.php:110 +#, php-format +msgid "%s favorite notices" msgstr "" -#: actions/recoverpassword.php:240 -msgid "Same as password above" +#: actions/favoritesrss.php:64 actions/favoritesrss.php:104 +#: actions/favoritesrss.php:114 +#, php-format +msgid "Feed of favorite notices of %s" msgstr "" -#: actions/recoverpassword.php:243 -msgid "Reset" +#: actions/inbox.php:28 actions/inbox.php:59 +#, php-format +msgid "Inbox for %s - page %d" msgstr "" -#: actions/recoverpassword.php:252 -msgid "Enter a nickname or email address." +#: actions/inbox.php:30 actions/inbox.php:62 +#, php-format +msgid "Inbox for %s" msgstr "" -#: actions/recoverpassword.php:272 -msgid "No user with that email address or username." +#: actions/inbox.php:53 actions/inbox.php:115 +msgid "This is your inbox, which lists your incoming private messages." msgstr "" -#: actions/recoverpassword.php:287 -msgid "No registered email address for that user." +#: actions/invite.php:178 actions/invite.php:213 +#, php-format +msgid "" +"%1$s has invited you to join them on %2$s (%3$s).\n" +"\n" msgstr "" -#: actions/recoverpassword.php:301 -msgid "Error saving address confirmation." +#: actions/login.php:104 actions/login.php:235 actions/openidlogin.php:108 +#: actions/register.php:416 +msgid "Automatically login in the future; " msgstr "" -#: actions/recoverpassword.php:325 -msgid "" -"Instructions for recovering your password have been sent to the email " -"address registered to your account." +#: actions/login.php:122 actions/login.php:264 +msgid "For security reasons, please re-enter your " msgstr "" -#: actions/recoverpassword.php:344 -msgid "Unexpected password reset." +#: actions/login.php:126 actions/login.php:268 +msgid "Login with your username and password. " msgstr "" -#: actions/recoverpassword.php:352 -msgid "Password must be 6 chars or more." +#: actions/newmessage.php:58 actions/twitapidirect_messages.php:130 +#: actions/twitapidirect_messages.php:141 actions/newmessage.php:148 +#: actions/twitapidirect_messages.php:150 +#: actions/twitapidirect_messages.php:145 +msgid "That's too long. Max message size is 140 chars." msgstr "" -#: actions/recoverpassword.php:356 -msgid "Password and confirmation do not match." +#: actions/newmessage.php:65 actions/newmessage.php:128 +#: actions/newmessage.php:155 actions/newmessage.php:158 +msgid "No recipient specified." msgstr "" -#: actions/recoverpassword.php:382 -msgid "New password successfully saved. You are now logged in." +#: actions/newmessage.php:68 actions/newmessage.php:113 +#: classes/Command.php:206 actions/newmessage.php:131 +#: actions/newmessage.php:168 classes/Command.php:237 +#: actions/newmessage.php:119 actions/newmessage.php:158 lib/command.php:237 +#: lib/command.php:230 actions/newmessage.php:121 actions/newmessage.php:161 +#: lib/command.php:367 +msgid "You can't send a message to this user." +msgstr "" + +#: actions/newmessage.php:71 actions/twitapidirect_messages.php:146 +#: classes/Command.php:209 actions/twitapidirect_messages.php:158 +#: classes/Command.php:240 actions/newmessage.php:161 +#: actions/twitapidirect_messages.php:167 lib/command.php:240 +#: actions/twitapidirect_messages.php:163 lib/command.php:233 +#: actions/newmessage.php:164 lib/command.php:370 +msgid "" +"Don't send a message to yourself; just say it to yourself quietly instead." msgstr "" -#: actions/register.php:85 actions/register.php:189 actions/register.php:404 -msgid "Sorry. Only those invited can register." +#: actions/newmessage.php:108 actions/microsummary.php:62 +#: actions/newmessage.php:163 actions/newmessage.php:114 +#: actions/newmessage.php:116 actions/remotesubscribe.php:154 +msgid "No such user" msgstr "" -#: actions/register.php:92 -msgid "Sorry. This is an invalid invitation code." +#: actions/newmessage.php:117 actions/newmessage.php:67 +#: actions/newmessage.php:71 actions/newmessage.php:231 +msgid "New message" msgstr "" -#: actions/register.php:112 -msgid "Registration successful" +#: actions/noticesearch.php:95 actions/noticesearch.php:146 +msgid "Notice without matching profile" msgstr "" -#: actions/register.php:114 actions/register.php:502 lib/action.php:450 -#: lib/logingroupnav.php:85 -msgid "Register" +#: actions/openidsettings.php:28 actions/openidsettings.php:70 +#, php-format +msgid "[OpenID](%%doc.openid%%) lets you log into many sites " msgstr "" -#: actions/register.php:135 -msgid "Registration not allowed." +#: actions/openidsettings.php:46 actions/openidsettings.php:96 +msgid "If you want to add an OpenID to your account, " msgstr "" -#: actions/register.php:198 -msgid "You can't register if you don't agree to the license." +#: actions/openidsettings.php:74 +msgid "Removing your only OpenID would make it impossible to log in! " msgstr "" -#: actions/register.php:201 -msgid "Not a valid email address." +#: actions/openidsettings.php:87 actions/openidsettings.php:143 +msgid "You can remove an OpenID from your account " msgstr "" -#: actions/register.php:212 -msgid "Email address already exists." +#: actions/outbox.php:28 actions/outbox.php:58 +#, php-format +msgid "Outbox for %s - page %d" msgstr "" -#: actions/register.php:243 actions/register.php:264 -msgid "Invalid username or password." +#: actions/outbox.php:30 actions/outbox.php:61 +#, php-format +msgid "Outbox for %s" +msgstr "" + +#: actions/outbox.php:53 actions/outbox.php:116 +msgid "This is your outbox, which lists private messages you have sent." msgstr "" -#: actions/register.php:342 +#: actions/peoplesearch.php:28 actions/peoplesearch.php:52 +#, php-format msgid "" -"With this form you can create a new account. You can then post notices and " -"link up to friends and colleagues. " +"Search for people on %%site.name%% by their name, location, or interests. " msgstr "" -#: actions/register.php:424 -msgid "1-64 lowercase letters or numbers, no punctuation or spaces. Required." +#: actions/profilesettings.php:27 actions/profilesettings.php:69 +msgid "You can update your personal profile info here " msgstr "" -#: actions/register.php:429 -msgid "6 or more characters. Required." +#: actions/profilesettings.php:115 actions/remotesubscribe.php:320 +#: actions/userauthorization.php:159 actions/userrss.php:76 +#: actions/avatarsettings.php:104 actions/avatarsettings.php:179 +#: actions/grouplogo.php:177 actions/remotesubscribe.php:367 +#: actions/userauthorization.php:176 actions/userrss.php:82 +#: actions/avatarsettings.php:106 actions/avatarsettings.php:182 +#: actions/grouplogo.php:183 actions/remotesubscribe.php:366 +#: actions/remotesubscribe.php:364 actions/userauthorization.php:215 +#: actions/userrss.php:103 actions/grouplogo.php:178 +#: actions/remotesubscribe.php:191 actions/userauthorization.php:72 +msgid "User without matching profile" msgstr "" -#: actions/register.php:433 -msgid "Same as password above. Required." +#: actions/recoverpassword.php:91 actions/recoverpassword.php:97 +msgid "This confirmation code is too old. " msgstr "" -#: actions/register.php:437 actions/register.php:441 -#: lib/accountsettingsaction.php:117 -msgid "Email" +#: actions/recoverpassword.php:141 actions/recoverpassword.php:152 +msgid "If you've forgotten or lost your" msgstr "" -#: actions/register.php:438 actions/register.php:442 -msgid "Used only for updates, announcements, and password recovery" +#: actions/recoverpassword.php:154 actions/recoverpassword.php:158 +msgid "You've been identified. Enter a " msgstr "" -#: actions/register.php:449 -msgid "Longer name, preferably your \"real\" name" +#: actions/recoverpassword.php:169 actions/recoverpassword.php:188 +msgid "Your nickname on this server, " msgstr "" -#: actions/register.php:493 -msgid "My text and files are available under " +#: actions/recoverpassword.php:271 actions/recoverpassword.php:304 +msgid "Instructions for recovering your password " msgstr "" -#: actions/register.php:495 -msgid "Creative Commons Attribution 3.0" +#: actions/recoverpassword.php:327 actions/recoverpassword.php:361 +msgid "New password successfully saved. " msgstr "" -#: actions/register.php:496 -msgid "" -" except this private data: password, email address, IM address, and phone " -"number." +#: actions/register.php:95 actions/register.php:180 +#: actions/passwordsettings.php:147 actions/register.php:217 +#: actions/passwordsettings.php:153 actions/register.php:224 +#: actions/register.php:230 +msgid "Password must be 6 or more characters." msgstr "" -#: actions/register.php:537 +#: actions/register.php:216 #, php-format msgid "" "Congratulations, %s! And welcome to %%%%site.name%%%%. From here, you may " -"want to...\n" -"\n" -"* Go to [your profile](%s) and post your first message.\n" -"* Add a [Jabber/GTalk address](%%%%action.imsettings%%%%) so you can send " -"notices through instant messages.\n" -"* [Search for users](%%%%action.peoplesearch%%%%) that you may know or that " -"share your interests. \n" -"* Update your [profile settings](%%%%action.profilesettings%%%%) to tell " -"others more about you. \n" -"* Read over the [online docs](%%%%doc.help%%%%) for features you may have " -"missed. \n" -"\n" -"Thanks for signing up and we hope you enjoy using this service." +"want to..." msgstr "" -#: actions/register.php:561 -msgid "" -"(You should receive a message by email momentarily, with instructions on how " -"to confirm your email address.)" +#: actions/register.php:227 +msgid "(You should receive a message by email momentarily, with " msgstr "" -#: actions/remotesubscribe.php:98 +#: actions/remotesubscribe.php:51 actions/remotesubscribe.php:74 #, php-format -msgid "" -"To subscribe, you can [login](%%action.login%%), or [register](%%action." -"register%%) a new account. If you already have an account on a [compatible " -"microblogging site](%%doc.openmublog%%), enter your profile URL below." +msgid "To subscribe, you can [login](%%action.login%%)," msgstr "" -#: actions/remotesubscribe.php:112 -msgid "Remote subscribe" +#: actions/showfavorites.php:61 actions/showfavorites.php:145 +#: actions/showfavorites.php:147 +#, php-format +msgid "Feed for favorites of %s" msgstr "" -#: actions/remotesubscribe.php:124 -msgid "Subscribe to a remote user" +#: actions/showfavorites.php:84 actions/twitapifavorites.php:85 +#: actions/showfavorites.php:202 actions/twitapifavorites.php:59 +#: actions/showfavorites.php:179 actions/showfavorites.php:209 +#: actions/showfavorites.php:132 +msgid "Could not retrieve favorite notices." msgstr "" -#: actions/remotesubscribe.php:129 -msgid "User nickname" +#: actions/showmessage.php:33 actions/showmessage.php:81 +msgid "No such message." msgstr "" -#: actions/remotesubscribe.php:130 -msgid "Nickname of the user you want to follow" +#: actions/showmessage.php:42 actions/showmessage.php:98 +msgid "Only the sender and recipient may read this message." msgstr "" -#: actions/remotesubscribe.php:133 -msgid "Profile URL" +#: actions/showmessage.php:61 actions/showmessage.php:108 +#, php-format +msgid "Message to %1$s on %2$s" msgstr "" -#: actions/remotesubscribe.php:134 -msgid "URL of your profile on another compatible microblogging service" +#: actions/showmessage.php:66 actions/showmessage.php:113 +#, php-format +msgid "Message from %1$s on %2$s" msgstr "" -#: actions/remotesubscribe.php:137 lib/subscribeform.php:139 -#: lib/userprofile.php:321 -msgid "Subscribe" +#: actions/showstream.php:154 +msgid "Send a message" msgstr "" -#: actions/remotesubscribe.php:159 -msgid "Invalid profile URL (bad format)" +#: actions/smssettings.php:312 actions/smssettings.php:464 +#, php-format +msgid "Mobile carrier for your phone. " msgstr "" -#: actions/remotesubscribe.php:168 -msgid "" -"Not a valid profile URL (no YADIS document or no or invalid XRDS defined)." +#: actions/twitapidirect_messages.php:76 actions/twitapidirect_messages.php:68 +#: actions/twitapidirect_messages.php:67 actions/twitapidirect_messages.php:53 +#: actions/apidirectmessage.php:101 +#, php-format +msgid "Direct messages to %s" msgstr "" -#: actions/remotesubscribe.php:176 -msgid "That’s a local profile! Login to subscribe." +#: actions/twitapidirect_messages.php:77 actions/twitapidirect_messages.php:69 +#: actions/twitapidirect_messages.php:68 actions/twitapidirect_messages.php:54 +#: actions/apidirectmessage.php:105 +#, php-format +msgid "All the direct messages sent to %s" msgstr "" -#: actions/remotesubscribe.php:183 -msgid "Couldn’t get a request token." +#: actions/twitapidirect_messages.php:81 actions/twitapidirect_messages.php:73 +#: actions/twitapidirect_messages.php:72 actions/twitapidirect_messages.php:59 +msgid "Direct Messages You've Sent" msgstr "" -#: actions/replies.php:125 actions/repliesrss.php:68 -#: lib/personalgroupnav.php:105 +#: actions/twitapidirect_messages.php:82 actions/twitapidirect_messages.php:74 +#: actions/twitapidirect_messages.php:73 actions/twitapidirect_messages.php:60 +#: actions/apidirectmessage.php:93 #, php-format -msgid "Replies to %s" +msgid "All the direct messages sent from %s" msgstr "" -#: actions/replies.php:127 -#, php-format -msgid "Replies to %s, page %d" +#: actions/twitapidirect_messages.php:128 +#: actions/twitapidirect_messages.php:137 +#: actions/twitapidirect_messages.php:146 +#: actions/twitapidirect_messages.php:140 actions/apidirectmessagenew.php:126 +msgid "No message text!" msgstr "" -#: actions/replies.php:144 -#, php-format -msgid "Replies feed for %s (RSS 1.0)" +#: actions/twitapidirect_messages.php:138 +#: actions/twitapidirect_messages.php:150 +#: actions/twitapidirect_messages.php:159 +#: actions/twitapidirect_messages.php:154 actions/apidirectmessagenew.php:146 +msgid "Recipient user not found." msgstr "" -#: actions/replies.php:151 +#: actions/twitapidirect_messages.php:141 +#: actions/twitapidirect_messages.php:153 +#: actions/twitapidirect_messages.php:162 +#: actions/twitapidirect_messages.php:158 actions/apidirectmessagenew.php:150 +msgid "Can't send direct messages to users who aren't your friend." +msgstr "" + +#: actions/twitapifavorites.php:92 actions/twitapifavorites.php:66 +#: actions/twitapifavorites.php:64 actions/twitapifavorites.php:49 +#: actions/apitimelinefavorites.php:107 #, php-format -msgid "Replies feed for %s (RSS 2.0)" +msgid "%s / Favorites from %s" msgstr "" -#: actions/replies.php:158 +#: actions/twitapifavorites.php:95 actions/twitapifavorites.php:69 +#: actions/twitapifavorites.php:68 actions/twitapifavorites.php:55 +#: actions/apitimelinefavorites.php:119 #, php-format -msgid "Replies feed for %s (Atom)" +msgid "%s updates favorited by %s / %s." msgstr "" -#: actions/replies.php:198 +#: actions/twitapifavorites.php:187 lib/mail.php:275 +#: actions/twitapifavorites.php:164 lib/mail.php:553 +#: actions/twitapifavorites.php:170 lib/mail.php:554 +#: actions/twitapifavorites.php:221 #, php-format -msgid "" -"This is the timeline showing replies to %s but %s has not received a notice " -"to his attention yet." +msgid "%s added your notice as a favorite" msgstr "" -#: actions/replies.php:203 +#: actions/twitapifavorites.php:188 lib/mail.php:276 +#: actions/twitapifavorites.php:165 #, php-format msgid "" -"You can engage other users in a conversation, subscribe to more users or " -"[join groups](%%action.groups%%)." +"%1$s just added your notice from %2$s as one of their favorites.\n" +"\n" msgstr "" -#: actions/replies.php:205 -#, php-format +#: actions/twittersettings.php:27 msgid "" -"You can try to [nudge %s](../%s) or [post something to his or her attention]" -"(%%%%action.newnotice%%%%?status_textarea=%s)." +"Add your Twitter account to automatically send your notices to Twitter, " msgstr "" -#: actions/repliesrss.php:72 -#, php-format -msgid "Replies to %1$s on %2$s!" +#: actions/twittersettings.php:41 actions/twittersettings.php:60 +#: actions/twittersettings.php:61 +msgid "Twitter settings" msgstr "" -#: actions/showfavorites.php:79 -#, php-format -msgid "%s's favorite notices, page %d" +#: actions/twittersettings.php:48 actions/twittersettings.php:105 +#: actions/twittersettings.php:106 +msgid "Twitter Account" msgstr "" -#: actions/showfavorites.php:132 -msgid "Could not retrieve favorite notices." +#: actions/twittersettings.php:56 actions/twittersettings.php:113 +#: actions/twittersettings.php:114 +msgid "Current verified Twitter account." msgstr "" -#: actions/showfavorites.php:170 -#, php-format -msgid "Feed for favorites of %s (RSS 1.0)" +#: actions/twittersettings.php:63 +msgid "Twitter Username" msgstr "" -#: actions/showfavorites.php:177 -#, php-format -msgid "Feed for favorites of %s (RSS 2.0)" +#: actions/twittersettings.php:65 actions/twittersettings.php:123 +#: actions/twittersettings.php:126 +msgid "No spaces, please." msgstr "" -#: actions/showfavorites.php:184 -#, php-format -msgid "Feed for favorites of %s (Atom)" +#: actions/twittersettings.php:67 +msgid "Twitter Password" msgstr "" -#: actions/showfavorites.php:205 -msgid "" -"You haven't chosen any favorite notices yet. Click the fave button on " -"notices you like to bookmark them for later or shed a spotlight on them." +#: actions/twittersettings.php:72 actions/twittersettings.php:139 +#: actions/twittersettings.php:142 +msgid "Automatically send my notices to Twitter." msgstr "" -#: actions/showfavorites.php:207 -#, php-format -msgid "" -"%s hasn't added any notices to his favorites yet. Post something interesting " -"they would add to their favorites :)" +#: actions/twittersettings.php:75 actions/twittersettings.php:146 +#: actions/twittersettings.php:149 +msgid "Send local \"@\" replies to Twitter." msgstr "" -#: actions/showfavorites.php:211 -#, php-format -msgid "" -"%s hasn't added any notices to his favorites yet. Why not [register an " -"account](%%%%action.register%%%%) and then post something interesting they " -"would add to their favorites :)" +#: actions/twittersettings.php:78 actions/twittersettings.php:153 +#: actions/twittersettings.php:156 +msgid "Subscribe to my Twitter friends here." msgstr "" -#: actions/showfavorites.php:242 -msgid "This is a way to share what you like." +#: actions/twittersettings.php:122 actions/twittersettings.php:331 +#: actions/twittersettings.php:348 +msgid "" +"Username must have only numbers, upper- and lowercase letters, and " +"underscore (_). 15 chars max." msgstr "" -#: actions/showgroup.php:82 lib/groupnav.php:85 -#, php-format -msgid "%s group" +#: actions/twittersettings.php:128 actions/twittersettings.php:334 +#: actions/twittersettings.php:338 actions/twittersettings.php:355 +msgid "Could not verify your Twitter credentials!" msgstr "" -#: actions/showgroup.php:84 +#: actions/twittersettings.php:137 #, php-format -msgid "%s group, page %d" +msgid "Unable to retrieve account information for \"%s\" from Twitter." msgstr "" -#: actions/showgroup.php:218 -msgid "Group profile" +#: actions/twittersettings.php:151 actions/twittersettings.php:170 +#: actions/twittersettings.php:348 actions/twittersettings.php:368 +#: actions/twittersettings.php:352 actions/twittersettings.php:372 +#: actions/twittersettings.php:369 actions/twittersettings.php:389 +msgid "Unable to save your Twitter settings!" msgstr "" -#: actions/showgroup.php:263 actions/tagother.php:118 -#: actions/userauthorization.php:167 lib/userprofile.php:177 -msgid "URL" +#: actions/twittersettings.php:174 actions/twittersettings.php:376 +#: actions/twittersettings.php:380 actions/twittersettings.php:399 +msgid "Twitter settings saved." msgstr "" -#: actions/showgroup.php:274 actions/tagother.php:128 -#: actions/userauthorization.php:179 lib/userprofile.php:194 -msgid "Note" +#: actions/twittersettings.php:192 actions/twittersettings.php:395 +#: actions/twittersettings.php:399 actions/twittersettings.php:418 +msgid "That is not your Twitter account." msgstr "" -#: actions/showgroup.php:284 lib/groupeditform.php:184 -msgid "Aliases" +#: actions/twittersettings.php:200 actions/twittersettings.php:208 +#: actions/twittersettings.php:403 actions/twittersettings.php:407 +#: actions/twittersettings.php:426 +msgid "Couldn't remove Twitter user." msgstr "" -#: actions/showgroup.php:293 -msgid "Group actions" +#: actions/twittersettings.php:212 actions/twittersettings.php:407 +#: actions/twittersettings.php:411 actions/twittersettings.php:430 +msgid "Twitter account removed." msgstr "" -#: actions/showgroup.php:328 -#, php-format -msgid "Notice feed for %s group (RSS 1.0)" +#: actions/twittersettings.php:225 actions/twittersettings.php:239 +#: actions/twittersettings.php:428 actions/twittersettings.php:439 +#: actions/twittersettings.php:453 actions/twittersettings.php:432 +#: actions/twittersettings.php:443 actions/twittersettings.php:457 +#: actions/twittersettings.php:452 actions/twittersettings.php:463 +#: actions/twittersettings.php:477 +msgid "Couldn't save Twitter preferences." msgstr "" -#: actions/showgroup.php:334 -#, php-format -msgid "Notice feed for %s group (RSS 2.0)" +#: actions/twittersettings.php:245 actions/twittersettings.php:461 +#: actions/twittersettings.php:465 actions/twittersettings.php:485 +msgid "Twitter preferences saved." msgstr "" -#: actions/showgroup.php:340 -#, php-format -msgid "Notice feed for %s group (Atom)" +#: actions/userauthorization.php:84 actions/userauthorization.php:86 +msgid "Please check these details to make sure " msgstr "" -#: actions/showgroup.php:345 -#, php-format -msgid "FOAF for %s group" +#: actions/userauthorization.php:324 actions/userauthorization.php:340 +msgid "The subscription has been authorized, but no " msgstr "" -#: actions/showgroup.php:381 actions/showgroup.php:438 lib/groupnav.php:90 -msgid "Members" +#: actions/userauthorization.php:334 actions/userauthorization.php:351 +msgid "The subscription has been rejected, but no " msgstr "" -#: actions/showgroup.php:386 lib/profileaction.php:117 -#: lib/profileaction.php:148 lib/profileaction.php:226 lib/section.php:95 -#: lib/tagcloudsection.php:71 -msgid "(None)" +#: classes/Channel.php:113 classes/Channel.php:132 classes/Channel.php:151 +#: lib/channel.php:138 lib/channel.php:158 +msgid "Command results" msgstr "" -#: actions/showgroup.php:392 -msgid "All members" +#: classes/Channel.php:148 classes/Channel.php:204 lib/channel.php:210 +msgid "Command complete" msgstr "" -#: actions/showgroup.php:429 lib/profileaction.php:173 -msgid "Statistics" +#: classes/Channel.php:158 classes/Channel.php:215 lib/channel.php:221 +msgid "Command failed" msgstr "" -#: actions/showgroup.php:432 -msgid "Created" +#: classes/Command.php:39 classes/Command.php:44 lib/command.php:44 +msgid "Sorry, this command is not yet implemented." msgstr "" -#: actions/showgroup.php:448 +#: classes/Command.php:96 classes/Command.php:113 #, php-format -msgid "" -"**%s** is a user group on %%%%site.name%%%%, a [micro-blogging](http://en." -"wikipedia.org/wiki/Micro-blogging) service based on the Free Software " -"[StatusNet](http://status.net/) tool. Its members share short messages about " -"their life and interests. [Join now](%%%%action.register%%%%) to become part " -"of this group and many more! ([Read more](%%%%doc.help%%%%))" +msgid "Subscriptions: %1$s\n" msgstr "" -#: actions/showgroup.php:454 -#, php-format -msgid "" -"**%s** is a user group on %%%%site.name%%%%, a [micro-blogging](http://en." -"wikipedia.org/wiki/Micro-blogging) service based on the Free Software " -"[StatusNet](http://status.net/) tool. Its members share short messages about " -"their life and interests. " +#: classes/Command.php:125 classes/Command.php:242 classes/Command.php:145 +#: classes/Command.php:276 lib/command.php:145 lib/command.php:276 +#: lib/command.php:138 lib/command.php:269 lib/command.php:168 +#: lib/command.php:416 lib/command.php:471 +msgid "User has no last notice" msgstr "" -#: actions/showgroup.php:482 -msgid "Admins" +#: classes/Command.php:146 classes/Command.php:166 lib/command.php:166 +#: lib/command.php:159 lib/command.php:190 +msgid "Notice marked as fave." msgstr "" -#: actions/showmessage.php:81 -msgid "No such message." +#: classes/Command.php:166 classes/Command.php:189 lib/command.php:189 +#: lib/command.php:182 lib/command.php:315 +#, php-format +msgid "%1$s (%2$s)" msgstr "" -#: actions/showmessage.php:98 -msgid "Only the sender and recipient may read this message." +#: classes/Command.php:169 classes/Command.php:192 lib/command.php:192 +#: lib/command.php:185 lib/command.php:318 +#, php-format +msgid "Fullname: %s" msgstr "" -#: actions/showmessage.php:108 +#: classes/Command.php:172 classes/Command.php:195 lib/command.php:195 +#: lib/command.php:188 lib/command.php:321 #, php-format -msgid "Message to %1$s on %2$s" +msgid "Location: %s" msgstr "" -#: actions/showmessage.php:113 +#: classes/Command.php:175 classes/Command.php:198 lib/command.php:198 +#: lib/command.php:191 lib/command.php:324 #, php-format -msgid "Message from %1$s on %2$s" +msgid "Homepage: %s" msgstr "" -#: actions/shownotice.php:90 -msgid "Notice deleted." +#: classes/Command.php:178 classes/Command.php:201 lib/command.php:201 +#: lib/command.php:194 lib/command.php:327 +#, php-format +msgid "About: %s" msgstr "" -#: actions/showstream.php:73 +#: classes/Command.php:200 classes/Command.php:228 lib/command.php:228 +#: lib/command.php:221 #, php-format -msgid " tagged %s" +msgid "Message too long - maximum is 140 characters, you sent %d" msgstr "" -#: actions/showstream.php:79 +#: classes/Command.php:214 classes/Command.php:245 lib/command.php:245 +#: actions/newmessage.php:182 lib/command.php:238 actions/newmessage.php:185 +#: lib/command.php:375 #, php-format -msgid "%s, page %d" +msgid "Direct message to %s sent" msgstr "" -#: actions/showstream.php:122 -#, php-format -msgid "Notice feed for %s tagged %s (RSS 1.0)" +#: classes/Command.php:216 classes/Command.php:247 lib/command.php:247 +#: lib/command.php:240 lib/command.php:377 +msgid "Error sending direct message." msgstr "" -#: actions/showstream.php:129 -#, php-format -msgid "Notice feed for %s (RSS 1.0)" +#: classes/Command.php:263 classes/Command.php:300 lib/command.php:300 +#: lib/command.php:293 lib/command.php:495 +msgid "Specify the name of the user to subscribe to" msgstr "" -#: actions/showstream.php:136 +#: classes/Command.php:270 classes/Command.php:307 lib/command.php:307 +#: lib/command.php:300 lib/command.php:502 #, php-format -msgid "Notice feed for %s (RSS 2.0)" +msgid "Subscribed to %s" msgstr "" -#: actions/showstream.php:143 -#, php-format -msgid "Notice feed for %s (Atom)" +#: classes/Command.php:288 classes/Command.php:328 lib/command.php:328 +#: lib/command.php:321 lib/command.php:523 +msgid "Specify the name of the user to unsubscribe from" msgstr "" -#: actions/showstream.php:148 +#: classes/Command.php:295 classes/Command.php:335 lib/command.php:335 +#: lib/command.php:328 lib/command.php:530 #, php-format -msgid "FOAF for %s" +msgid "Unsubscribed from %s" msgstr "" -#: actions/showstream.php:191 -#, php-format -msgid "This is the timeline for %s but %s hasn't posted anything yet." +#: classes/Command.php:310 classes/Command.php:330 classes/Command.php:353 +#: classes/Command.php:376 lib/command.php:353 lib/command.php:376 +#: lib/command.php:346 lib/command.php:369 lib/command.php:548 +#: lib/command.php:571 +msgid "Command not yet implemented." msgstr "" -#: actions/showstream.php:196 -msgid "" -"Seen anything interesting recently? You haven't posted any notices yet, now " -"would be a good time to start :)" +#: classes/Command.php:313 classes/Command.php:356 lib/command.php:356 +#: lib/command.php:349 lib/command.php:551 +msgid "Notification off." msgstr "" -#: actions/showstream.php:198 +#: classes/Command.php:315 classes/Command.php:358 lib/command.php:358 +#: lib/command.php:351 lib/command.php:553 +msgid "Can't turn off notification." +msgstr "" + +#: classes/Command.php:333 classes/Command.php:379 lib/command.php:379 +#: lib/command.php:372 lib/command.php:574 +msgid "Notification on." +msgstr "" + +#: classes/Command.php:335 classes/Command.php:381 lib/command.php:381 +#: lib/command.php:374 lib/command.php:576 +msgid "Can't turn on notification." +msgstr "" + +#: classes/Command.php:344 classes/Command.php:392 +msgid "Commands:\n" +msgstr "" + +#: classes/Message.php:53 classes/Message.php:56 classes/Message.php:55 +msgid "Could not insert message." +msgstr "" + +#: classes/Message.php:63 classes/Message.php:66 classes/Message.php:65 +msgid "Could not update message with new URI." +msgstr "" + +#: lib/gallery.php:46 +msgid "User without matching profile in system." +msgstr "" + +#: lib/mail.php:147 lib/mail.php:289 #, php-format msgid "" -"You can try to nudge %s or [post something to his or her attention](%%%%" -"action.newnotice%%%%?status_textarea=%s)." +"You have a new posting address on %1$s.\n" +"\n" msgstr "" -#: actions/showstream.php:234 +#: lib/mail.php:249 lib/mail.php:508 lib/mail.php:509 #, php-format -msgid "" -"**%s** has an account on %%%%site.name%%%%, a [micro-blogging](http://en." -"wikipedia.org/wiki/Micro-blogging) service based on the Free Software " -"[StatusNet](http://status.net/) tool. [Join now](%%%%action.register%%%%) to " -"follow **%s**'s notices and many more! ([Read more](%%%%doc.help%%%%))" +msgid "New private message from %s" msgstr "" -#: actions/showstream.php:239 +#: lib/mail.php:253 lib/mail.php:512 #, php-format msgid "" -"**%s** has an account on %%%%site.name%%%%, a [micro-blogging](http://en." -"wikipedia.org/wiki/Micro-blogging) service based on the Free Software " -"[StatusNet](http://status.net/) tool. " +"%1$s (%2$s) sent you a private message:\n" +"\n" msgstr "" -#: actions/smssettings.php:58 -msgid "SMS Settings" +#: lib/mailbox.php:43 lib/mailbox.php:89 lib/mailbox.php:91 +msgid "Only the user can read their own mailboxes." msgstr "" -#: actions/smssettings.php:69 -#, php-format -msgid "You can receive SMS messages through email from %%site.name%%." +#: lib/openid.php:195 lib/openid.php:203 +msgid "This form should automatically submit itself. " msgstr "" -#: actions/smssettings.php:91 -msgid "SMS is not available." +#: lib/personal.php:65 lib/personalgroupnav.php:113 +#: lib/personalgroupnav.php:114 +msgid "Favorites" msgstr "" -#: actions/smssettings.php:104 -msgid "SMS address" +#: lib/personal.php:66 lib/personalgroupnav.php:114 +#: actions/favoritesrss.php:110 actions/showfavorites.php:77 +#: lib/personalgroupnav.php:115 actions/favoritesrss.php:111 +#, php-format +msgid "%s's favorite notices" msgstr "" -#: actions/smssettings.php:112 -msgid "Current confirmed SMS-enabled phone number." +#: lib/personal.php:66 lib/personalgroupnav.php:114 +#: lib/personalgroupnav.php:115 +msgid "User" msgstr "" -#: actions/smssettings.php:123 -msgid "Awaiting confirmation on this phone number." +#: lib/personal.php:75 lib/personalgroupnav.php:123 +#: lib/personalgroupnav.php:124 +msgid "Inbox" msgstr "" -#: actions/smssettings.php:130 -msgid "Confirmation code" +#: lib/personal.php:76 lib/personalgroupnav.php:124 +#: lib/personalgroupnav.php:125 +msgid "Your incoming messages" msgstr "" -#: actions/smssettings.php:131 -msgid "Enter the code you received on your phone." +#: lib/personal.php:80 lib/personalgroupnav.php:128 +#: lib/personalgroupnav.php:129 +msgid "Outbox" msgstr "" -#: actions/smssettings.php:138 -msgid "SMS Phone number" +#: lib/personal.php:81 lib/personalgroupnav.php:129 +#: lib/personalgroupnav.php:130 +msgid "Your sent messages" msgstr "" -#: actions/smssettings.php:140 -msgid "Phone number, no punctuation or spaces, with area code" +#: lib/settingsaction.php:99 lib/connectsettingsaction.php:110 +msgid "Twitter" msgstr "" -#: actions/smssettings.php:174 -msgid "" -"Send me notices through SMS; I understand I may incur exorbitant charges " -"from my carrier." +#: lib/settingsaction.php:100 lib/connectsettingsaction.php:111 +msgid "Twitter integration options" msgstr "" -#: actions/smssettings.php:306 -msgid "No phone number." +#: lib/util.php:1718 lib/messageform.php:139 lib/noticelist.php:422 +#: lib/messageform.php:137 lib/noticelist.php:425 lib/messageform.php:135 +#: lib/noticelist.php:433 lib/messageform.php:146 +msgid "To" msgstr "" -#: actions/smssettings.php:311 -msgid "No carrier selected." +#: scripts/maildaemon.php:45 scripts/maildaemon.php:48 +#: scripts/maildaemon.php:47 +msgid "Could not parse message." msgstr "" -#: actions/smssettings.php:318 -msgid "That is already your phone number." +#: actions/all.php:63 actions/facebookhome.php:162 actions/all.php:66 +#: actions/facebookhome.php:161 actions/all.php:48 +#: actions/facebookhome.php:156 actions/all.php:84 +#, php-format +msgid "%s and friends, page %d" msgstr "" -#: actions/smssettings.php:321 -msgid "That phone number already belongs to another user." +#: actions/avatarsettings.php:76 +msgid "You can upload your personal avatar." msgstr "" -#: actions/smssettings.php:347 -msgid "" -"A confirmation code was sent to the phone number you added. Check your phone " -"for the code and instructions on how to use it." +#: actions/avatarsettings.php:117 actions/avatarsettings.php:191 +#: actions/grouplogo.php:250 actions/avatarsettings.php:119 +#: actions/avatarsettings.php:194 actions/grouplogo.php:256 +#: actions/grouplogo.php:251 +msgid "Avatar settings" msgstr "" -#: actions/smssettings.php:374 -msgid "That is the wrong confirmation number." +#: actions/avatarsettings.php:124 actions/avatarsettings.php:199 +#: actions/grouplogo.php:198 actions/grouplogo.php:258 +#: actions/avatarsettings.php:126 actions/avatarsettings.php:202 +#: actions/grouplogo.php:204 actions/grouplogo.php:264 +#: actions/grouplogo.php:199 actions/grouplogo.php:259 +msgid "Original" msgstr "" -#: actions/smssettings.php:405 -msgid "That is not your phone number." +#: actions/avatarsettings.php:139 actions/avatarsettings.php:211 +#: actions/grouplogo.php:209 actions/grouplogo.php:270 +#: actions/avatarsettings.php:141 actions/avatarsettings.php:214 +#: actions/grouplogo.php:215 actions/grouplogo.php:276 +#: actions/grouplogo.php:210 actions/grouplogo.php:271 +msgid "Preview" msgstr "" -#: actions/smssettings.php:465 -msgid "Mobile carrier" +#: actions/avatarsettings.php:225 actions/grouplogo.php:284 +#: actions/avatarsettings.php:228 actions/grouplogo.php:291 +#: actions/grouplogo.php:286 +msgid "Crop" msgstr "" -#: actions/smssettings.php:469 -msgid "Select a carrier" +#: actions/avatarsettings.php:248 actions/deletenotice.php:133 +#: actions/emailsettings.php:224 actions/grouplogo.php:307 +#: actions/imsettings.php:200 actions/login.php:102 actions/newmessage.php:100 +#: actions/newnotice.php:96 actions/openidsettings.php:188 +#: actions/othersettings.php:136 actions/passwordsettings.php:131 +#: actions/profilesettings.php:172 actions/register.php:113 +#: actions/remotesubscribe.php:53 actions/smssettings.php:216 +#: actions/subedit.php:38 actions/twittersettings.php:290 +#: actions/userauthorization.php:39 +msgid "There was a problem with your session token. " msgstr "" -#: actions/smssettings.php:476 -#, php-format -msgid "" -"Mobile carrier for your phone. If you know a carrier that accepts SMS over " -"email but isn't listed here, send email to let us know at %s." +#: actions/avatarsettings.php:303 actions/grouplogo.php:360 +#: actions/avatarsettings.php:308 actions/avatarsettings.php:322 +msgid "Pick a square area of the image to be your avatar" msgstr "" -#: actions/smssettings.php:498 -msgid "No code entered" +#: actions/avatarsettings.php:327 actions/grouplogo.php:384 +#: actions/avatarsettings.php:323 actions/grouplogo.php:382 +#: actions/grouplogo.php:377 actions/avatarsettings.php:337 +msgid "Lost our file data." msgstr "" -#: actions/subedit.php:70 -msgid "You are not subscribed to that profile." +#: actions/avatarsettings.php:334 actions/grouplogo.php:391 +#: classes/User_group.php:112 lib/imagefile.php:112 lib/imagefile.php:113 +#: lib/imagefile.php:118 +msgid "Lost our file." msgstr "" -#: actions/subedit.php:83 -msgid "Could not save subscription." +#: actions/avatarsettings.php:349 actions/avatarsettings.php:383 +#: actions/grouplogo.php:406 actions/grouplogo.php:440 +#: classes/User_group.php:129 classes/User_group.php:161 lib/imagefile.php:144 +#: lib/imagefile.php:191 lib/imagefile.php:145 lib/imagefile.php:192 +#: lib/imagefile.php:150 lib/imagefile.php:197 +msgid "Unknown file type" msgstr "" -#: actions/subscribe.php:55 -msgid "Not a local user." +#: actions/block.php:69 actions/subedit.php:46 actions/unblock.php:70 +#: actions/groupblock.php:71 actions/groupunblock.php:71 +#: actions/makeadmin.php:71 +msgid "No profile specified." msgstr "" -#: actions/subscribe.php:69 -msgid "Subscribed" +#: actions/block.php:74 actions/subedit.php:53 actions/tagother.php:46 +#: actions/unblock.php:75 actions/groupblock.php:76 +#: actions/groupunblock.php:76 actions/makeadmin.php:76 +msgid "No profile with that ID." msgstr "" -#: actions/subscribers.php:50 -#, php-format -msgid "%s subscribers" +#: actions/block.php:111 actions/block.php:134 +msgid "Block user" msgstr "" -#: actions/subscribers.php:52 -#, php-format -msgid "%s subscribers, page %d" +#: actions/block.php:129 +msgid "Are you sure you want to block this user? " msgstr "" -#: actions/subscribers.php:63 -msgid "These are the users who have subscribed to your notices." +#: actions/block.php:162 actions/block.php:165 +msgid "You have already blocked this user." msgstr "" -#: actions/subscribers.php:67 +#: actions/block.php:167 actions/block.php:170 +msgid "Failed to save block information." +msgstr "" + +#: actions/confirmaddress.php:159 #, php-format -msgid "These are the users who have subscribed to %s's notices." +msgid "The address \"%s\" has been " msgstr "" -#: actions/subscribers.php:108 -msgid "" -"You have no subscribers. Try subscribing to users you know and they might " -"return the favor" +#: actions/deletenotice.php:73 +msgid "You are about to permanently delete a notice. " msgstr "" -#: actions/subscribers.php:110 -#, php-format -msgid "%s has no subscribers. Want to be the first?" +#: actions/disfavor.php:94 +msgid "Add to favorites" msgstr "" -#: actions/subscribers.php:114 +#: actions/editgroup.php:54 actions/editgroup.php:56 #, php-format -msgid "" -"%s has no subscribers. Why not [register an account](%%%%action.register%%%" -"%) and be the first?" +msgid "Edit %s group" msgstr "" -#: actions/subscriptions.php:52 -#, php-format -msgid "%s subscriptions" +#: actions/editgroup.php:66 actions/groupbyid.php:72 actions/grouplogo.php:66 +#: actions/joingroup.php:60 actions/newgroup.php:65 actions/showgroup.php:100 +#: actions/grouplogo.php:70 actions/grouprss.php:80 actions/editgroup.php:68 +#: actions/groupdesignsettings.php:68 actions/showgroup.php:105 +msgid "Inboxes must be enabled for groups to work" msgstr "" -#: actions/subscriptions.php:54 -#, php-format -msgid "%s subscriptions, page %d" +#: actions/editgroup.php:71 actions/grouplogo.php:71 actions/newgroup.php:70 +#: actions/grouplogo.php:75 actions/editgroup.php:73 actions/editgroup.php:68 +#: actions/grouplogo.php:70 actions/newgroup.php:65 +msgid "You must be logged in to create a group." msgstr "" -#: actions/subscriptions.php:65 -msgid "These are the users whose notices you have subscribed to." +#: actions/editgroup.php:87 actions/grouplogo.php:87 +#: actions/groupmembers.php:76 actions/joingroup.php:81 +#: actions/showgroup.php:121 actions/grouplogo.php:91 actions/grouprss.php:96 +#: actions/blockedfromgroup.php:73 actions/editgroup.php:89 +#: actions/groupdesignsettings.php:89 actions/showgroup.php:126 +#: actions/editgroup.php:84 actions/groupdesignsettings.php:84 +#: actions/grouplogo.php:86 actions/grouprss.php:91 actions/joingroup.php:76 +msgid "No nickname" msgstr "" -#: actions/subscriptions.php:69 -#, php-format -msgid "These are the users whose notices %s has subscribed to." +#: actions/editgroup.php:99 actions/groupbyid.php:88 actions/grouplogo.php:100 +#: actions/groupmembers.php:83 actions/joingroup.php:88 +#: actions/showgroup.php:128 actions/grouplogo.php:104 +#: actions/grouprss.php:103 actions/blockedfromgroup.php:80 +#: actions/editgroup.php:101 actions/groupdesignsettings.php:102 +#: actions/showgroup.php:133 actions/editgroup.php:96 actions/groupbyid.php:83 +#: actions/groupdesignsettings.php:97 actions/grouplogo.php:99 +#: actions/grouprss.php:98 actions/joingroup.php:83 actions/showgroup.php:137 +msgid "No such group" msgstr "" -#: actions/subscriptions.php:121 -#, php-format -msgid "" -"You have not subscribed to anyone's notices right now. Try subscribing to " -"users you know. Try [user search](%%action.peoplesearch%%), look for members " -"in groups you're interested in and in our [featured users](%%action.featured%" -"%). If you are a [Twitter user](%%action.twittersettings%%), you can " -"automatically subscribe to users you already follow there." +#: actions/editgroup.php:106 actions/editgroup.php:165 +#: actions/grouplogo.php:107 actions/grouplogo.php:111 +#: actions/editgroup.php:108 actions/editgroup.php:167 +#: actions/groupdesignsettings.php:109 actions/editgroup.php:103 +#: actions/editgroup.php:168 actions/groupdesignsettings.php:104 +#: actions/grouplogo.php:106 +msgid "You must be an admin to edit the group" msgstr "" -#: actions/subscriptions.php:123 actions/subscriptions.php:127 -#, php-format -msgid "%s is not listening to anyone." +#: actions/editgroup.php:157 actions/editgroup.php:159 +#: actions/editgroup.php:154 +msgid "Use this form to edit the group." msgstr "" -#: actions/subscriptions.php:194 -msgid "Jabber" +#: actions/editgroup.php:179 actions/newgroup.php:130 actions/register.php:156 +msgid "Nickname must have only lowercase letters " msgstr "" -#: actions/subscriptions.php:199 lib/connectsettingsaction.php:115 -msgid "SMS" +#: actions/editgroup.php:198 actions/newgroup.php:149 +#: actions/editgroup.php:200 actions/newgroup.php:150 +msgid "description is too long (max 140 chars)." msgstr "" -#: actions/tagother.php:33 -msgid "Not logged in" +#: actions/editgroup.php:218 actions/editgroup.php:253 +msgid "Could not update group." msgstr "" -#: actions/tagother.php:39 -msgid "No id argument." +#: actions/editgroup.php:226 actions/editgroup.php:269 +msgid "Options saved." msgstr "" -#: actions/tagother.php:65 +#: actions/emailsettings.php:107 actions/imsettings.php:108 #, php-format -msgid "Tag %s" +msgid "Awaiting confirmation on this address. " msgstr "" -#: actions/tagother.php:77 lib/userprofile.php:75 -msgid "User profile" +#: actions/emailsettings.php:139 actions/smssettings.php:150 +msgid "Make a new email address for posting to; " msgstr "" -#: actions/tagother.php:81 lib/userprofile.php:102 -msgid "Photo" +#: actions/emailsettings.php:157 +msgid "Send me email when someone " msgstr "" -#: actions/tagother.php:141 -msgid "Tag user" +#: actions/emailsettings.php:168 actions/emailsettings.php:173 +#: actions/emailsettings.php:179 +msgid "Allow friends to nudge me and send me an email." msgstr "" -#: actions/tagother.php:151 -msgid "" -"Tags for this user (letters, numbers, -, ., and _), comma- or space- " -"separated" +#: actions/emailsettings.php:321 +msgid "That email address already belongs " msgstr "" -#: actions/tagother.php:193 -msgid "" -"You can only tag users you are subscribed to or who are subscribed to you." +#: actions/emailsettings.php:343 +msgid "A confirmation code was sent to the email address you added. " msgstr "" -#: actions/tagother.php:200 -msgid "Could not save tags." +#: actions/facebookhome.php:110 actions/facebookhome.php:109 +msgid "Server error - couldn't get user!" msgstr "" -#: actions/tagother.php:236 -msgid "Use this form to add tags to your subscribers or subscriptions." +#: actions/facebookhome.php:196 +#, php-format +msgid "If you would like the %s app to automatically update " msgstr "" -#: actions/tag.php:68 +#: actions/facebookhome.php:213 actions/facebooksettings.php:137 #, php-format -msgid "Notices tagged with %s, page %d" +msgid "Allow %s to update my Facebook status" msgstr "" -#: actions/tag.php:86 -#, php-format -msgid "Notice feed for tag %s (RSS 1.0)" +#: actions/facebookhome.php:218 actions/facebookhome.php:223 +#: actions/facebookhome.php:217 +msgid "Skip" msgstr "" -#: actions/tag.php:92 -#, php-format -msgid "Notice feed for tag %s (RSS 2.0)" +#: actions/facebookhome.php:235 lib/facebookaction.php:479 +#: lib/facebookaction.php:471 +msgid "No notice content!" msgstr "" -#: actions/tag.php:98 -#, php-format -msgid "Notice feed for tag %s (Atom)" +#: actions/facebookhome.php:295 lib/action.php:870 lib/facebookaction.php:399 +#: actions/facebookhome.php:253 lib/action.php:973 lib/facebookaction.php:433 +#: actions/facebookhome.php:247 lib/action.php:1037 lib/facebookaction.php:435 +#: lib/action.php:1053 +msgid "Pagination" msgstr "" -#: actions/tagrss.php:35 -msgid "No such tag." +#: actions/facebookhome.php:304 lib/action.php:879 lib/facebookaction.php:408 +#: actions/facebookhome.php:262 lib/action.php:982 lib/facebookaction.php:442 +#: actions/facebookhome.php:256 lib/action.php:1046 lib/facebookaction.php:444 +#: lib/action.php:1062 +msgid "After" msgstr "" -#: actions/twitapitrends.php:87 -msgid "API method under construction." +#: actions/facebookhome.php:312 lib/action.php:887 lib/facebookaction.php:416 +#: actions/facebookhome.php:270 lib/action.php:990 lib/facebookaction.php:450 +#: actions/facebookhome.php:264 lib/action.php:1054 lib/facebookaction.php:452 +#: lib/action.php:1070 +msgid "Before" msgstr "" -#: actions/unsubscribe.php:77 -msgid "No profile id in request." +#: actions/facebookinvite.php:70 actions/facebookinvite.php:72 +#, php-format +msgid "Thanks for inviting your friends to use %s" msgstr "" -#: actions/unsubscribe.php:84 -msgid "No profile with that id." +#: actions/facebookinvite.php:72 actions/facebookinvite.php:74 +msgid "Invitations have been sent to the following users:" msgstr "" -#: actions/unsubscribe.php:98 -msgid "Unsubscribed" +#: actions/facebookinvite.php:96 actions/facebookinvite.php:102 +#: actions/facebookinvite.php:94 +#, php-format +msgid "You have been invited to %s" msgstr "" -#: actions/updateprofile.php:62 actions/userauthorization.php:330 +#: actions/facebookinvite.php:105 actions/facebookinvite.php:111 +#: actions/facebookinvite.php:103 #, php-format -msgid "Listenee stream license ‘%s’ is not compatible with site license ‘%s’." +msgid "Invite your friends to use %s" msgstr "" -#: actions/userauthorization.php:105 -msgid "Authorize subscription" +#: actions/facebookinvite.php:113 actions/facebookinvite.php:126 +#: actions/facebookinvite.php:124 +#, php-format +msgid "Friends already using %s:" msgstr "" -#: actions/userauthorization.php:110 -msgid "" -"Please check these details to make sure that you want to subscribe to this " -"user’s notices. If you didn’t just ask to subscribe to someone’s notices, " -"click “Reject”." +#: actions/facebookinvite.php:130 actions/facebookinvite.php:143 +#: actions/facebookinvite.php:142 +#, php-format +msgid "Send invitations" msgstr "" -#: actions/userauthorization.php:188 -msgid "License" +#: actions/facebookremove.php:56 +msgid "Couldn't remove Facebook user." msgstr "" -#: actions/userauthorization.php:209 -msgid "Accept" +#: actions/facebooksettings.php:65 +msgid "There was a problem saving your sync preferences!" msgstr "" -#: actions/userauthorization.php:210 lib/subscribeform.php:115 -#: lib/subscribeform.php:139 -msgid "Subscribe to this user" +#: actions/facebooksettings.php:67 +msgid "Sync preferences saved." msgstr "" -#: actions/userauthorization.php:211 -msgid "Reject" +#: actions/facebooksettings.php:90 +msgid "Automatically update my Facebook status with my notices." msgstr "" -#: actions/userauthorization.php:212 -msgid "Reject this subscription" +#: actions/facebooksettings.php:97 +msgid "Send \"@\" replies to Facebook." msgstr "" -#: actions/userauthorization.php:225 -msgid "No authorization request!" +#: actions/facebooksettings.php:106 +msgid "Prefix" msgstr "" -#: actions/userauthorization.php:247 -msgid "Subscription authorized" +#: actions/facebooksettings.php:108 +msgid "A string to prefix notices with." msgstr "" -#: actions/userauthorization.php:249 -msgid "" -"The subscription has been authorized, but no callback URL was passed. Check " -"with the site’s instructions for details on how to authorize the " -"subscription. Your subscription token is:" +#: actions/facebooksettings.php:124 +#, php-format +msgid "If you would like %s to automatically update " msgstr "" -#: actions/userauthorization.php:259 -msgid "Subscription rejected" +#: actions/facebooksettings.php:147 +msgid "Sync preferences" msgstr "" -#: actions/userauthorization.php:261 -msgid "" -"The subscription has been rejected, but no callback URL was passed. Check " -"with the site’s instructions for details on how to fully reject the " -"subscription." +#: actions/favor.php:94 lib/disfavorform.php:140 actions/favor.php:92 +msgid "Disfavor favorite" msgstr "" -#: actions/userauthorization.php:296 -#, php-format -msgid "Listener URI ‘%s’ not found here" +#: actions/favorited.php:65 lib/popularnoticesection.php:76 +#: lib/publicgroupnav.php:91 lib/popularnoticesection.php:82 +#: lib/publicgroupnav.php:93 lib/popularnoticesection.php:91 +#: lib/popularnoticesection.php:87 +msgid "Popular notices" msgstr "" -#: actions/userauthorization.php:301 +#: actions/favorited.php:67 #, php-format -msgid "Listenee URI ‘%s’ is too long." +msgid "Popular notices, page %d" msgstr "" -#: actions/userauthorization.php:307 -#, php-format -msgid "Listenee URI ‘%s’ is a local user." +#: actions/favorited.php:79 +msgid "The most popular notices on the site right now." msgstr "" -#: actions/userauthorization.php:322 -#, php-format -msgid "Profile URL ‘%s’ is for a local user." +#: actions/featured.php:69 lib/featureduserssection.php:82 +#: lib/publicgroupnav.php:87 lib/publicgroupnav.php:89 +#: lib/featureduserssection.php:87 +msgid "Featured users" msgstr "" -#: actions/userauthorization.php:338 +#: actions/featured.php:71 #, php-format -msgid "Avatar URL ‘%s’ is not valid." +msgid "Featured users, page %d" msgstr "" -#: actions/userauthorization.php:343 +#: actions/featured.php:99 #, php-format -msgid "Can’t read avatar URL ‘%s’." +msgid "A selection of some of the great users on %s" msgstr "" -#: actions/userauthorization.php:348 -#, php-format -msgid "Wrong image type for avatar URL ‘%s’." +#: actions/finishremotesubscribe.php:188 actions/finishremotesubscribe.php:96 +msgid "That user has blocked you from subscribing." msgstr "" -#: actions/userbyid.php:70 -msgid "No id." +#: actions/groupbyid.php:79 actions/groupbyid.php:74 +msgid "No ID" msgstr "" -#: actions/userdesignsettings.php:76 lib/designsettings.php:65 -msgid "Profile design" +#: actions/grouplogo.php:138 actions/grouplogo.php:191 +#: actions/grouplogo.php:144 actions/grouplogo.php:197 +#: actions/grouplogo.php:139 actions/grouplogo.php:192 +msgid "Group logo" msgstr "" -#: actions/userdesignsettings.php:87 lib/designsettings.php:76 -msgid "" -"Customize the way your profile looks with a background image and a colour " -"palette of your choice." +#: actions/grouplogo.php:149 +msgid "You can upload a logo image for your group." msgstr "" -#: actions/userdesignsettings.php:282 -msgid "Enjoy your hotdog!" +#: actions/grouplogo.php:448 actions/grouplogo.php:401 +#: actions/grouplogo.php:396 +msgid "Logo updated." msgstr "" -#: actions/usergroups.php:64 -#, php-format -msgid "%s groups, page %d" +#: actions/grouplogo.php:450 actions/grouplogo.php:403 +#: actions/grouplogo.php:398 +msgid "Failed updating logo." msgstr "" -#: actions/usergroups.php:130 -msgid "Search for more groups" +#: actions/groupmembers.php:93 lib/groupnav.php:91 +#, php-format +msgid "%s group members" msgstr "" -#: actions/usergroups.php:153 +#: actions/groupmembers.php:96 #, php-format -msgid "%s is not a member of any group." +msgid "%s group members, page %d" msgstr "" -#: actions/usergroups.php:158 -#, php-format -msgid "Try [searching for groups](%%action.groupsearch%%) and joining them." +#: actions/groupmembers.php:111 +msgid "A list of the users in this group." msgstr "" -#: classes/File.php:137 -#, php-format -msgid "" -"No file may be larger than %d bytes and the file you sent was %d bytes. Try " -"to upload a smaller version." +#: actions/groups.php:62 actions/showstream.php:518 lib/publicgroupnav.php:79 +#: lib/subgroupnav.php:96 lib/publicgroupnav.php:81 lib/profileaction.php:220 +#: lib/subgroupnav.php:98 +msgid "Groups" msgstr "" -#: classes/File.php:147 +#: actions/groups.php:64 #, php-format -msgid "A file this large would exceed your user quota of %d bytes." +msgid "Groups, page %d" msgstr "" -#: classes/File.php:154 +#: actions/groups.php:90 #, php-format -msgid "A file this large would exceed your monthly quota of %d bytes." +msgid "%%%%site.name%%%% groups let you find and talk with " msgstr "" -#: classes/Message.php:55 -msgid "Could not insert message." +#: actions/groups.php:106 actions/usergroups.php:124 lib/groupeditform.php:123 +#: actions/usergroups.php:125 actions/groups.php:107 lib/groupeditform.php:122 +msgid "Create a new group" msgstr "" -#: classes/Message.php:65 -msgid "Could not update message with new URI." +#: actions/groupsearch.php:57 +#, php-format +msgid "" +"Search for groups on %%site.name%% by their name, location, or description. " msgstr "" -#: classes/Notice.php:164 -#, php-format -msgid "DB error inserting hashtag: %s" +#: actions/groupsearch.php:63 actions/groupsearch.php:58 +msgid "Group search" msgstr "" -#: classes/Notice.php:179 -msgid "Problem saving notice. Too long." +#: actions/imsettings.php:70 +msgid "You can send and receive notices through " msgstr "" -#: classes/Notice.php:183 -msgid "Problem saving notice. Unknown user." +#: actions/imsettings.php:120 +#, php-format +msgid "Jabber or GTalk address, " msgstr "" -#: classes/Notice.php:188 -msgid "" -"Too many notices too fast; take a breather and post again in a few minutes." +#: actions/imsettings.php:147 +msgid "Send me replies through Jabber/GTalk " msgstr "" -#: classes/Notice.php:194 -msgid "" -"Too many duplicate messages too quickly; take a breather and post again in a " -"few minutes." +#: actions/imsettings.php:321 +#, php-format +msgid "A confirmation code was sent " msgstr "" -#: classes/Notice.php:202 -msgid "You are banned from posting notices on this site." +#: actions/joingroup.php:65 actions/joingroup.php:60 +msgid "You must be logged in to join a group." msgstr "" -#: classes/Notice.php:268 classes/Notice.php:293 -msgid "Problem saving notice." +#: actions/joingroup.php:95 actions/joingroup.php:90 lib/command.php:217 +msgid "You are already a member of that group" msgstr "" -#: classes/Notice.php:1120 +#: actions/joingroup.php:128 actions/joingroup.php:133 lib/command.php:234 #, php-format -msgid "DB error inserting reply: %s" +msgid "Could not join user %s to group %s" msgstr "" -#: classes/User.php:333 +#: actions/joingroup.php:135 actions/joingroup.php:140 lib/command.php:239 #, php-format -msgid "Welcome to %1$s, @%2$s!" +msgid "%s joined group %s" msgstr "" -#: lib/accountsettingsaction.php:108 lib/personalgroupnav.php:109 -msgid "Profile" +#: actions/leavegroup.php:60 +msgid "Inboxes must be enabled for groups to work." msgstr "" -#: lib/accountsettingsaction.php:109 -msgid "Change your profile settings" +#: actions/leavegroup.php:65 actions/leavegroup.php:60 +msgid "You must be logged in to leave a group." msgstr "" -#: lib/accountsettingsaction.php:112 -msgid "Upload an avatar" +#: actions/leavegroup.php:88 actions/groupblock.php:86 +#: actions/groupunblock.php:86 actions/makeadmin.php:86 +#: actions/foafgroup.php:44 actions/foafgroup.php:62 actions/leavegroup.php:83 +#: lib/command.php:212 lib/command.php:263 +msgid "No such group." msgstr "" -#: lib/accountsettingsaction.php:115 -msgid "Change your password" +#: actions/leavegroup.php:95 actions/leavegroup.php:90 lib/command.php:268 +msgid "You are not a member of that group." msgstr "" -#: lib/accountsettingsaction.php:118 -msgid "Change email handling" +#: actions/leavegroup.php:100 +msgid "You may not leave a group while you are its administrator." msgstr "" -#: lib/accountsettingsaction.php:120 lib/groupnav.php:118 -msgid "Design" +#: actions/leavegroup.php:130 actions/leavegroup.php:124 +#: actions/leavegroup.php:119 lib/command.php:278 +msgid "Could not find membership record." msgstr "" -#: lib/accountsettingsaction.php:121 -msgid "Design your profile" +#: actions/leavegroup.php:138 actions/leavegroup.php:132 +#: actions/leavegroup.php:127 lib/command.php:284 +#, php-format +msgid "Could not remove user %s to group %s" msgstr "" -#: lib/accountsettingsaction.php:123 -msgid "Other" +#: actions/leavegroup.php:145 actions/leavegroup.php:139 +#: actions/leavegroup.php:134 lib/command.php:289 +#, php-format +msgid "%s left group %s" msgstr "" -#: lib/accountsettingsaction.php:124 -msgid "Other options" +#: actions/login.php:225 lib/facebookaction.php:304 actions/login.php:208 +#: actions/login.php:216 actions/login.php:243 +msgid "Login to site" msgstr "" -#: lib/action.php:144 -#, php-format -msgid "%s - %s" +#: actions/microsummary.php:69 +msgid "No current status" msgstr "" -#: lib/action.php:159 -msgid "Untitled page" +#: actions/newgroup.php:53 +msgid "New group" msgstr "" -#: lib/action.php:424 -msgid "Primary site navigation" +#: actions/newgroup.php:115 actions/newgroup.php:110 +msgid "Use this form to create a new group." msgstr "" -#: lib/action.php:430 -msgid "Home" +#: actions/newgroup.php:177 actions/newgroup.php:209 +#: actions/apigroupcreate.php:136 actions/newgroup.php:204 +msgid "Could not create group." msgstr "" -#: lib/action.php:430 -msgid "Personal profile and friends timeline" +#: actions/newgroup.php:191 actions/newgroup.php:229 +#: actions/apigroupcreate.php:166 actions/newgroup.php:224 +msgid "Could not set group membership." msgstr "" -#: lib/action.php:432 -msgid "Account" +#: actions/newmessage.php:119 actions/newnotice.php:132 +msgid "That's too long. " msgstr "" -#: lib/action.php:432 -msgid "Change your email, avatar, password, profile" +#: actions/newmessage.php:134 +msgid "Don't send a message to yourself; " msgstr "" -#: lib/action.php:435 -msgid "Connect" +#: actions/newnotice.php:166 actions/newnotice.php:174 +#: actions/newnotice.php:272 actions/newnotice.php:199 +msgid "Notice posted" msgstr "" -#: lib/action.php:435 -msgid "Connect to services" +#: actions/newnotice.php:200 classes/Channel.php:163 actions/newnotice.php:208 +#: lib/channel.php:170 actions/newmessage.php:207 actions/newnotice.php:387 +#: actions/newmessage.php:210 actions/newnotice.php:233 +msgid "Ajax Error" msgstr "" -#: lib/action.php:439 lib/subgroupnav.php:105 -msgid "Invite" +#: actions/nudge.php:85 +msgid "" +"This user doesn't allow nudges or hasn't confirmed or set his email yet." msgstr "" -#: lib/action.php:440 lib/subgroupnav.php:106 -#, php-format -msgid "Invite friends and colleagues to join you on %s" +#: actions/nudge.php:94 +msgid "Nudge sent" msgstr "" -#: lib/action.php:445 -msgid "Logout" +#: actions/nudge.php:97 +msgid "Nudge sent!" msgstr "" -#: lib/action.php:445 -msgid "Logout from the site" +#: actions/openidlogin.php:97 actions/openidlogin.php:106 +msgid "OpenID login" msgstr "" -#: lib/action.php:450 -msgid "Create an account" +#: actions/openidsettings.php:128 +msgid "Removing your only OpenID " msgstr "" -#: lib/action.php:453 -msgid "Login to the site" +#: actions/othersettings.php:60 +msgid "Other Settings" msgstr "" -#: lib/action.php:456 lib/action.php:719 -msgid "Help" +#: actions/othersettings.php:71 +msgid "Manage various other options." msgstr "" -#: lib/action.php:456 -msgid "Help me!" +#: actions/othersettings.php:93 +msgid "URL Auto-shortening" msgstr "" -#: lib/action.php:459 -msgid "Search" +#: actions/othersettings.php:112 +msgid "Service" msgstr "" -#: lib/action.php:459 -msgid "Search for users or text" +#: actions/othersettings.php:113 actions/othersettings.php:111 +#: actions/othersettings.php:118 +msgid "Automatic shortening service to use." msgstr "" -#: lib/action.php:480 -msgid "Site notice" +#: actions/othersettings.php:144 actions/othersettings.php:146 +#: actions/othersettings.php:153 +msgid "URL shortening service is too long (max 50 chars)." msgstr "" -#: lib/action.php:546 -msgid "Local views" +#: actions/passwordsettings.php:69 +msgid "Change your password." msgstr "" -#: lib/action.php:612 -msgid "Page notice" +#: actions/passwordsettings.php:89 actions/recoverpassword.php:228 +#: actions/passwordsettings.php:95 actions/recoverpassword.php:231 +msgid "Password change" msgstr "" -#: lib/action.php:714 -msgid "Secondary site navigation" +#: actions/peopletag.php:35 actions/peopletag.php:70 +#, php-format +msgid "Not a valid people tag: %s" msgstr "" -#: lib/action.php:721 -msgid "About" +#: actions/peopletag.php:47 actions/peopletag.php:144 +#, php-format +msgid "Users self-tagged with %s - page %d" msgstr "" -#: lib/action.php:723 -msgid "FAQ" +#: actions/peopletag.php:91 +#, php-format +msgid "These are users who have tagged themselves \"%s\" " msgstr "" -#: lib/action.php:727 -msgid "TOS" +#: actions/profilesettings.php:91 actions/profilesettings.php:99 +msgid "Profile information" msgstr "" -#: lib/action.php:730 -msgid "Privacy" +#: actions/profilesettings.php:124 actions/profilesettings.php:125 +#: actions/profilesettings.php:140 +msgid "" +"Tags for yourself (letters, numbers, -, ., and _), comma- or space- separated" msgstr "" -#: lib/action.php:732 -msgid "Source" +#: actions/profilesettings.php:144 +msgid "Automatically subscribe to whoever " msgstr "" -#: lib/action.php:734 -msgid "Contact" +#: actions/profilesettings.php:229 actions/tagother.php:176 +#: actions/tagother.php:178 actions/profilesettings.php:230 +#: actions/profilesettings.php:246 +#, php-format +msgid "Invalid tag: \"%s\"" msgstr "" -#: lib/action.php:736 -msgid "Badge" +#: actions/profilesettings.php:311 actions/profilesettings.php:310 +#: actions/profilesettings.php:336 +msgid "Couldn't save tags." msgstr "" -#: lib/action.php:764 -msgid "StatusNet software license" +#: actions/public.php:107 actions/public.php:110 actions/public.php:118 +#: actions/public.php:129 +#, php-format +msgid "Public timeline, page %d" +msgstr "" + +#: actions/public.php:173 actions/public.php:184 actions/public.php:210 +#: actions/public.php:92 +msgid "Could not retrieve public stream." msgstr "" -#: lib/action.php:767 +#: actions/public.php:220 #, php-format msgid "" -"**%%site.name%%** is a microblogging service brought to you by [%%site." -"broughtby%%](%%site.broughtbyurl%%). " +"This is %%site.name%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-" +"blogging) service " msgstr "" -#: lib/action.php:769 -#, php-format -msgid "**%%site.name%%** is a microblogging service. " +#: actions/publictagcloud.php:57 +msgid "Public tag cloud" msgstr "" -#: lib/action.php:771 +#: actions/publictagcloud.php:63 #, php-format -msgid "" -"It runs the [StatusNet](http://status.net/) microblogging software, version %" -"s, available under the [GNU Affero General Public License](http://www.fsf." -"org/licensing/licenses/agpl-3.0.html)." +msgid "These are most popular recent tags on %s " msgstr "" -#: lib/action.php:785 -msgid "Site content license" +#: actions/publictagcloud.php:119 actions/publictagcloud.php:135 +msgid "Tag cloud" msgstr "" -#: lib/action.php:794 -msgid "All " +#: actions/register.php:139 actions/register.php:349 actions/register.php:79 +#: actions/register.php:177 actions/register.php:394 actions/register.php:183 +#: actions/register.php:398 actions/register.php:85 actions/register.php:189 +#: actions/register.php:404 +msgid "Sorry, only invited people can register." msgstr "" -#: lib/action.php:799 -msgid "license." +#: actions/register.php:149 +msgid "You can't register if you don't " msgstr "" -#: lib/action.php:1053 -msgid "Pagination" +#: actions/register.php:286 +msgid "With this form you can create " msgstr "" -#: lib/action.php:1062 -msgid "After" +#: actions/register.php:368 +msgid "1-64 lowercase letters or numbers, " msgstr "" -#: lib/action.php:1070 -msgid "Before" +#: actions/register.php:382 actions/register.php:386 +msgid "Used only for updates, announcements, " msgstr "" -#: lib/attachmentlist.php:87 -msgid "Attachments" +#: actions/register.php:398 +msgid "URL of your homepage, blog, " msgstr "" -#: lib/attachmentlist.php:265 -msgid "Author" -msgstr "" - -#: lib/attachmentlist.php:278 -msgid "Provider" -msgstr "" - -#: lib/attachmentnoticesection.php:67 -msgid "Notices where this attachment appears" +#: actions/register.php:404 +msgid "Describe yourself and your " msgstr "" -#: lib/attachmenttagcloudsection.php:48 -msgid "Tags for this attachment" +#: actions/register.php:410 +msgid "Where you are, like \"City, " msgstr "" -#: lib/channel.php:138 lib/channel.php:158 -msgid "Command results" +#: actions/register.php:432 +msgid " except this private data: password, " msgstr "" -#: lib/channel.php:210 -msgid "Command complete" +#: actions/register.php:471 +#, php-format +msgid "Congratulations, %s! And welcome to %%%%site.name%%%%. " msgstr "" -#: lib/channel.php:221 -msgid "Command failed" +#: actions/register.php:495 +msgid "(You should receive a message by email " msgstr "" -#: lib/command.php:44 -msgid "Sorry, this command is not yet implemented." +#: actions/remotesubscribe.php:166 actions/remotesubscribe.php:171 +msgid "That's a local profile! Login to subscribe." msgstr "" -#: lib/command.php:88 +#: actions/replies.php:118 actions/replies.php:120 actions/replies.php:119 +#: actions/replies.php:127 #, php-format -msgid "Could not find a user with nickname %s" +msgid "Replies to %s, page %d" msgstr "" -#: lib/command.php:92 -msgid "It does not make a lot of sense to nudge yourself!" +#: actions/showfavorites.php:79 +#, php-format +msgid "%s favorite notices, page %d" msgstr "" -#: lib/command.php:99 +#: actions/showgroup.php:77 lib/groupnav.php:85 actions/showgroup.php:82 #, php-format -msgid "Nudge sent to %s" +msgid "%s group" msgstr "" -#: lib/command.php:126 +#: actions/showgroup.php:79 actions/showgroup.php:84 #, php-format -msgid "" -"Subscriptions: %1$s\n" -"Subscribers: %2$s\n" -"Notices: %3$s" +msgid "%s group, page %d" msgstr "" -#: lib/command.php:152 lib/command.php:400 -msgid "Notice with that id does not exist" +#: actions/showgroup.php:206 actions/showgroup.php:208 +#: actions/showgroup.php:213 actions/showgroup.php:218 +msgid "Group profile" msgstr "" -#: lib/command.php:168 lib/command.php:416 lib/command.php:471 -msgid "User has no last notice" +#: actions/showgroup.php:251 actions/showstream.php:278 +#: actions/tagother.php:119 lib/grouplist.php:134 lib/profilelist.php:133 +#: actions/showgroup.php:253 actions/showstream.php:271 +#: actions/tagother.php:118 lib/profilelist.php:131 actions/showgroup.php:258 +#: actions/showstream.php:236 actions/userauthorization.php:137 +#: lib/profilelist.php:197 actions/showgroup.php:263 +#: actions/showstream.php:295 actions/userauthorization.php:167 +#: lib/profilelist.php:230 lib/userprofile.php:177 +msgid "URL" msgstr "" -#: lib/command.php:190 -msgid "Notice marked as fave." +#: actions/showgroup.php:262 actions/showstream.php:289 +#: actions/tagother.php:129 lib/grouplist.php:145 lib/profilelist.php:144 +#: actions/showgroup.php:264 actions/showstream.php:282 +#: actions/tagother.php:128 lib/profilelist.php:142 actions/showgroup.php:269 +#: actions/showstream.php:247 actions/userauthorization.php:149 +#: lib/profilelist.php:212 actions/showgroup.php:274 +#: actions/showstream.php:312 actions/userauthorization.php:179 +#: lib/profilelist.php:245 lib/userprofile.php:194 +msgid "Note" msgstr "" -#: lib/command.php:315 -#, php-format -msgid "%1$s (%2$s)" +#: actions/showgroup.php:270 actions/showgroup.php:272 +#: actions/showgroup.php:288 actions/showgroup.php:293 +msgid "Group actions" msgstr "" -#: lib/command.php:318 +#: actions/showgroup.php:323 actions/showgroup.php:304 #, php-format -msgid "Fullname: %s" +msgid "Notice feed for %s group" msgstr "" -#: lib/command.php:321 -#, php-format -msgid "Location: %s" +#: actions/showgroup.php:357 lib/groupnav.php:90 actions/showgroup.php:339 +#: actions/showgroup.php:384 actions/showgroup.php:373 +#: actions/showgroup.php:430 actions/showgroup.php:381 +#: actions/showgroup.php:438 +msgid "Members" msgstr "" -#: lib/command.php:324 -#, php-format -msgid "Homepage: %s" +#: actions/showgroup.php:363 actions/showstream.php:413 +#: actions/showstream.php:442 actions/showstream.php:524 lib/section.php:95 +#: lib/tagcloudsection.php:71 actions/showgroup.php:344 +#: actions/showgroup.php:378 lib/profileaction.php:117 +#: lib/profileaction.php:148 lib/profileaction.php:226 +#: actions/showgroup.php:386 +msgid "(None)" msgstr "" -#: lib/command.php:327 -#, php-format -msgid "About: %s" +#: actions/showgroup.php:370 actions/showgroup.php:350 +#: actions/showgroup.php:384 actions/showgroup.php:392 +msgid "All members" msgstr "" -#: lib/command.php:358 scripts/xmppdaemon.php:321 +#: actions/showgroup.php:378 #, php-format -msgid "Message too long - maximum is %d characters, you sent %d" +msgid "" +"**%s** is a user group on %%%%site.name%%%%, a [micro-blogging](http://en." +"wikipedia.org/wiki/Micro-blogging) service " msgstr "" -#: lib/command.php:377 -msgid "Error sending direct message." +#: actions/showmessage.php:98 +msgid "Only the sender and recipient " msgstr "" -#: lib/command.php:431 +#: actions/showstream.php:73 actions/showstream.php:78 +#: actions/showstream.php:79 #, php-format -msgid "Notice too long - maximum is %d characters, you sent %d" +msgid "%s, page %d" msgstr "" -#: lib/command.php:439 -#, php-format -msgid "Reply to %s sent" +#: actions/showstream.php:143 +msgid "'s profile" msgstr "" -#: lib/command.php:441 -msgid "Error saving notice." +#: actions/showstream.php:236 actions/tagother.php:77 +#: actions/showstream.php:220 actions/showstream.php:185 +#: actions/showstream.php:193 lib/userprofile.php:75 +msgid "User profile" msgstr "" -#: lib/command.php:495 -msgid "Specify the name of the user to subscribe to" +#: actions/showstream.php:240 actions/tagother.php:81 +#: actions/showstream.php:224 actions/showstream.php:189 +#: actions/showstream.php:220 lib/userprofile.php:102 +msgid "Photo" msgstr "" -#: lib/command.php:502 -#, php-format -msgid "Subscribed to %s" +#: actions/showstream.php:317 actions/showstream.php:309 +#: actions/showstream.php:274 actions/showstream.php:354 +#: lib/userprofile.php:236 +msgid "User actions" msgstr "" -#: lib/command.php:523 -msgid "Specify the name of the user to unsubscribe from" +#: actions/showstream.php:342 actions/showstream.php:307 +#: actions/showstream.php:390 lib/userprofile.php:272 +msgid "Send a direct message to this user" msgstr "" -#: lib/command.php:530 -#, php-format -msgid "Unsubscribed from %s" +#: actions/showstream.php:343 actions/showstream.php:308 +#: actions/showstream.php:391 lib/userprofile.php:273 +msgid "Message" msgstr "" -#: lib/command.php:548 lib/command.php:571 -msgid "Command not yet implemented." +#: actions/showstream.php:451 lib/profileaction.php:157 +msgid "All subscribers" msgstr "" -#: lib/command.php:551 -msgid "Notification off." +#: actions/showstream.php:533 lib/profileaction.php:235 +msgid "All groups" msgstr "" -#: lib/command.php:553 -msgid "Can't turn off notification." +#: actions/showstream.php:542 +#, php-format +msgid "" +"**%s** has an account on %%%%site.name%%%%, a [micro-blogging](http://en." +"wikipedia.org/wiki/Micro-blogging) service " msgstr "" -#: lib/command.php:574 -msgid "Notification on." +#: actions/smssettings.php:128 +msgid "Phone number, no punctuation or spaces, " msgstr "" -#: lib/command.php:576 -msgid "Can't turn on notification." +#: actions/smssettings.php:162 +msgid "Send me notices through SMS; " msgstr "" -#: lib/command.php:597 -#, php-format -msgid "Could not create login token for %s" +#: actions/smssettings.php:335 +msgid "A confirmation code was sent to the phone number you added. " msgstr "" -#: lib/command.php:602 -#, php-format -msgid "This link is useable only once, and is good for only 2 minutes: %s" +#: actions/smssettings.php:453 actions/smssettings.php:465 +msgid "Mobile carrier" msgstr "" -#: lib/command.php:613 -msgid "" -"Commands:\n" -"on - turn on notifications\n" -"off - turn off notifications\n" -"help - show this help\n" -"follow - subscribe to user\n" -"leave - unsubscribe from user\n" -"d - direct message to user\n" -"get - get last notice from user\n" -"whois - get profile info on user\n" -"fav - add user's last notice as a 'fave'\n" -"fav # - add notice with the given id as a 'fave'\n" -"reply # - reply to notice with a given id\n" -"reply - reply to the last notice from user\n" -"join - join group\n" -"login - Get a link to login to the web interface\n" -"drop - leave group\n" -"stats - get your stats\n" -"stop - same as 'off'\n" -"quit - same as 'off'\n" -"sub - same as 'follow'\n" -"unsub - same as 'leave'\n" -"last - same as 'get'\n" -"on - not yet implemented.\n" -"off - not yet implemented.\n" -"nudge - remind a user to update.\n" -"invite - not yet implemented.\n" -"track - not yet implemented.\n" -"untrack - not yet implemented.\n" -"track off - not yet implemented.\n" -"untrack all - not yet implemented.\n" -"tracks - not yet implemented.\n" -"tracking - not yet implemented.\n" +#: actions/subedit.php:70 +msgid "You are not subscribed to that profile." msgstr "" -#: lib/common.php:191 -msgid "No configuration file found. " +#: actions/subedit.php:83 +msgid "Could not save subscription." msgstr "" -#: lib/common.php:192 -msgid "I looked for configuration files in the following places: " +#: actions/subscribe.php:55 +msgid "Not a local user." msgstr "" -#: lib/common.php:193 -msgid "You may wish to run the installer to fix this." +#: actions/subscribe.php:69 +msgid "Subscribed" msgstr "" -#: lib/common.php:194 -msgid "Go to the installer." +#: actions/subscribers.php:50 +#, php-format +msgid "%s subscribers" msgstr "" -#: lib/connectsettingsaction.php:110 -msgid "IM" +#: actions/subscribers.php:52 +#, php-format +msgid "%s subscribers, page %d" msgstr "" -#: lib/connectsettingsaction.php:111 -msgid "Updates by instant messenger (IM)" +#: actions/subscribers.php:63 +msgid "These are the people who listen to " msgstr "" -#: lib/connectsettingsaction.php:116 -msgid "Updates by SMS" +#: actions/subscribers.php:67 +#, php-format +msgid "These are the people who " msgstr "" -#: lib/dberroraction.php:60 -msgid "Database error" +#: actions/subscriptions.php:52 +#, php-format +msgid "%s subscriptions" msgstr "" -#: lib/designsettings.php:101 -msgid "Change background image" +#: actions/subscriptions.php:54 +#, php-format +msgid "%s subscriptions, page %d" msgstr "" -#: lib/designsettings.php:105 -msgid "Upload file" +#: actions/subscriptions.php:65 +msgid "These are the people whose notices " msgstr "" -#: lib/designsettings.php:109 -msgid "" -"You can upload your personal background image. The maximum file size is 2Mb." +#: actions/subscriptions.php:69 +#, php-format +msgid "These are the people whose " msgstr "" -#: lib/designsettings.php:139 -msgid "On" +#: actions/subscriptions.php:122 actions/subscriptions.php:124 +#: actions/subscriptions.php:183 actions/subscriptions.php:194 +msgid "Jabber" msgstr "" -#: lib/designsettings.php:155 -msgid "Off" +#: actions/tag.php:43 actions/tag.php:51 actions/tag.php:59 actions/tag.php:68 +#, php-format +msgid "Notices tagged with %s, page %d" msgstr "" -#: lib/designsettings.php:156 -msgid "Turn background image on or off." +#: actions/tag.php:66 actions/tag.php:73 +#, php-format +msgid "Messages tagged \"%s\", most recent first" msgstr "" -#: lib/designsettings.php:161 -msgid "Tile background image" +#: actions/tagother.php:33 +msgid "Not logged in" msgstr "" -#: lib/designsettings.php:170 -msgid "Change colours" +#: actions/tagother.php:39 +msgid "No id argument." msgstr "" -#: lib/designsettings.php:178 -msgid "Background" +#: actions/tagother.php:65 +#, php-format +msgid "Tag %s" msgstr "" -#: lib/designsettings.php:191 -msgid "Content" +#: actions/tagother.php:141 +msgid "Tag user" msgstr "" -#: lib/designsettings.php:204 -msgid "Sidebar" +#: actions/tagother.php:149 actions/tagother.php:151 +msgid "" +"Tags for this user (letters, numbers, -, ., and _), comma- or space- " +"separated" msgstr "" -#: lib/designsettings.php:217 -msgid "Text" +#: actions/tagother.php:164 +msgid "There was a problem with your session token." msgstr "" -#: lib/designsettings.php:230 -msgid "Links" +#: actions/tagother.php:191 actions/tagother.php:193 +msgid "" +"You can only tag people you are subscribed to or who are subscribed to you." msgstr "" -#: lib/designsettings.php:247 -msgid "Use defaults" +#: actions/tagother.php:198 actions/tagother.php:200 +msgid "Could not save tags." msgstr "" -#: lib/designsettings.php:248 -msgid "Restore default designs" +#: actions/tagother.php:233 actions/tagother.php:235 actions/tagother.php:236 +msgid "Use this form to add tags to your subscribers or subscriptions." msgstr "" -#: lib/designsettings.php:254 -msgid "Reset back to default" +#: actions/tagrss.php:35 +msgid "No such tag." msgstr "" -#: lib/designsettings.php:257 -msgid "Save design" +#: actions/tagrss.php:66 actions/tagrss.php:64 +#, php-format +msgid "Microblog tagged with %s" msgstr "" -#: lib/designsettings.php:372 -msgid "Bad default color settings: " +#: actions/twitapiblocks.php:47 actions/twitapiblocks.php:49 +#: actions/apiblockcreate.php:108 +msgid "Block user failed." msgstr "" -#: lib/designsettings.php:468 -msgid "Design defaults restored." +#: actions/twitapiblocks.php:69 actions/twitapiblocks.php:71 +#: actions/apiblockdestroy.php:107 +msgid "Unblock user failed." msgstr "" -#: lib/disfavorform.php:114 lib/disfavorform.php:140 -msgid "Disfavor this notice" +#: actions/twitapiusers.php:48 actions/twitapiusers.php:52 +#: actions/twitapiusers.php:50 actions/apiusershow.php:96 +msgid "Not found." msgstr "" -#: lib/favorform.php:114 lib/favorform.php:140 -msgid "Favor this notice" +#: actions/twittersettings.php:71 +msgid "Add your Twitter account to automatically send " msgstr "" -#: lib/favorform.php:140 -msgid "Favor" +#: actions/twittersettings.php:119 actions/twittersettings.php:122 +msgid "Twitter user name" msgstr "" -#: lib/feedlist.php:64 -msgid "Export data" +#: actions/twittersettings.php:126 actions/twittersettings.php:129 +msgid "Twitter password" msgstr "" -#: lib/feed.php:85 -msgid "RSS 1.0" +#: actions/twittersettings.php:228 actions/twittersettings.php:232 +#: actions/twittersettings.php:248 +msgid "Twitter Friends" msgstr "" -#: lib/feed.php:87 -msgid "RSS 2.0" +#: actions/twittersettings.php:327 +msgid "Username must have only numbers, " msgstr "" -#: lib/feed.php:89 -msgid "Atom" +#: actions/twittersettings.php:341 +#, php-format +msgid "Unable to retrieve account information " msgstr "" -#: lib/feed.php:91 -msgid "FOAF" +#: actions/unblock.php:108 actions/groupunblock.php:128 +msgid "Error removing the block." msgstr "" -#: lib/galleryaction.php:121 -msgid "Filter tags" +#: actions/unsubscribe.php:50 actions/unsubscribe.php:77 +msgid "No profile id in request." msgstr "" -#: lib/galleryaction.php:131 -msgid "All" +#: actions/unsubscribe.php:57 actions/unsubscribe.php:84 +msgid "No profile with that id." msgstr "" -#: lib/galleryaction.php:139 -msgid "Select tag to filter" +#: actions/unsubscribe.php:71 actions/unsubscribe.php:98 +msgid "Unsubscribed" msgstr "" -#: lib/galleryaction.php:140 -msgid "Tag" +#: actions/usergroups.php:63 actions/usergroups.php:62 +#: actions/apigrouplistall.php:90 +#, php-format +msgid "%s groups" msgstr "" -#: lib/galleryaction.php:141 -msgid "Choose a tag to narrow list" +#: actions/usergroups.php:65 actions/usergroups.php:64 +#, php-format +msgid "%s groups, page %d" msgstr "" -#: lib/galleryaction.php:143 -msgid "Go" +#: classes/Notice.php:104 classes/Notice.php:128 classes/Notice.php:144 +#: classes/Notice.php:183 +msgid "Problem saving notice. Unknown user." msgstr "" -#: lib/groupeditform.php:163 -msgid "URL of the homepage or blog of the group or topic" +#: classes/Notice.php:109 classes/Notice.php:133 classes/Notice.php:149 +#: classes/Notice.php:188 +msgid "" +"Too many notices too fast; take a breather and post again in a few minutes." msgstr "" -#: lib/groupeditform.php:168 -msgid "Describe the group or topic" +#: classes/Notice.php:116 classes/Notice.php:145 classes/Notice.php:161 +#: classes/Notice.php:202 +msgid "You are banned from posting notices on this site." msgstr "" -#: lib/groupeditform.php:170 -#, php-format -msgid "Describe the group or topic in %d characters" +#: lib/accountsettingsaction.php:108 lib/accountsettingsaction.php:112 +msgid "Upload an avatar" msgstr "" -#: lib/groupeditform.php:172 -msgid "Description" +#: lib/accountsettingsaction.php:119 lib/accountsettingsaction.php:122 +#: lib/accountsettingsaction.php:123 +msgid "Other" msgstr "" -#: lib/groupeditform.php:179 -msgid "" -"Location for the group, if any, like \"City, State (or Region), Country\"" +#: lib/accountsettingsaction.php:120 lib/accountsettingsaction.php:123 +#: lib/accountsettingsaction.php:124 +msgid "Other options" msgstr "" -#: lib/groupeditform.php:187 +#: lib/action.php:130 lib/action.php:132 lib/action.php:142 lib/action.php:144 #, php-format -msgid "Extra nicknames for the group, comma- or space- separated, max %d" +msgid "%s - %s" msgstr "" -#: lib/groupnav.php:84 lib/searchgroupnav.php:84 -msgid "Group" +#: lib/action.php:145 lib/action.php:147 lib/action.php:157 lib/action.php:159 +msgid "Untitled page" msgstr "" -#: lib/groupnav.php:100 -msgid "Blocked" +#: lib/action.php:316 lib/action.php:387 lib/action.php:411 lib/action.php:424 +msgid "Primary site navigation" msgstr "" -#: lib/groupnav.php:101 -#, php-format -msgid "%s blocked users" +#: lib/action.php:322 lib/action.php:393 lib/action.php:417 lib/action.php:430 +msgid "Personal profile and friends timeline" msgstr "" -#: lib/groupnav.php:107 -#, php-format -msgid "Edit %s group properties" +#: lib/action.php:325 lib/action.php:396 lib/action.php:448 lib/action.php:459 +msgid "Search for people or text" msgstr "" -#: lib/groupnav.php:112 -msgid "Logo" +#: lib/action.php:328 lib/action.php:399 lib/action.php:419 lib/action.php:432 +msgid "Account" msgstr "" -#: lib/groupnav.php:113 -#, php-format -msgid "Add or edit %s logo" +#: lib/action.php:328 lib/action.php:399 lib/action.php:419 lib/action.php:432 +msgid "Change your email, avatar, password, profile" msgstr "" -#: lib/groupnav.php:119 -#, php-format -msgid "Add or edit %s design" +#: lib/action.php:330 lib/action.php:403 lib/action.php:422 +msgid "Connect to IM, SMS, Twitter" msgstr "" -#: lib/groupsbymemberssection.php:71 -msgid "Groups with most members" +#: lib/action.php:332 lib/action.php:409 lib/action.php:435 lib/action.php:445 +msgid "Logout from the site" msgstr "" -#: lib/groupsbypostssection.php:71 -msgid "Groups with most posts" +#: lib/action.php:335 lib/action.php:412 lib/action.php:443 lib/action.php:453 +msgid "Login to the site" msgstr "" -#: lib/grouptagcloudsection.php:56 -#, php-format -msgid "Tags in %s group's notices" +#: lib/action.php:338 lib/action.php:415 lib/action.php:440 lib/action.php:450 +msgid "Create an account" msgstr "" -#: lib/htmloutputter.php:104 -msgid "This page is not available in a media type you accept" +#: lib/action.php:341 lib/action.php:418 +msgid "Login with OpenID" msgstr "" -#: lib/imagefile.php:75 -#, php-format -msgid "That file is too big. The maximum file size is %s." +#: lib/action.php:344 lib/action.php:421 lib/action.php:446 lib/action.php:456 +msgid "Help me!" msgstr "" -#: lib/imagefile.php:80 -msgid "Partial upload." +#: lib/action.php:362 lib/action.php:441 lib/action.php:468 lib/action.php:480 +msgid "Site notice" msgstr "" -#: lib/imagefile.php:88 lib/mediafile.php:170 -msgid "System error uploading file." +#: lib/action.php:417 lib/action.php:504 lib/action.php:531 lib/action.php:546 +msgid "Local views" msgstr "" -#: lib/imagefile.php:96 -msgid "Not an image or corrupt file." +#: lib/action.php:472 lib/action.php:559 lib/action.php:597 lib/action.php:612 +msgid "Page notice" msgstr "" -#: lib/imagefile.php:105 -msgid "Unsupported image file format." +#: lib/action.php:562 lib/action.php:654 lib/action.php:699 lib/action.php:714 +msgid "Secondary site navigation" msgstr "" -#: lib/imagefile.php:118 -msgid "Lost our file." +#: lib/action.php:602 lib/action.php:623 lib/action.php:699 lib/action.php:720 +#: lib/action.php:749 lib/action.php:770 lib/action.php:764 +msgid "StatusNet software license" msgstr "" -#: lib/imagefile.php:150 lib/imagefile.php:197 -msgid "Unknown file type" +#: lib/action.php:630 lib/action.php:727 lib/action.php:779 lib/action.php:794 +msgid "All " msgstr "" -#: lib/jabber.php:192 +#: lib/action.php:635 lib/action.php:732 lib/action.php:784 lib/action.php:799 +msgid "license." +msgstr "" + +#: lib/blockform.php:123 lib/blockform.php:153 actions/groupmembers.php:343 +#: actions/groupmembers.php:346 +msgid "Block this user" +msgstr "" + +#: lib/blockform.php:153 actions/groupmembers.php:343 +#: actions/groupmembers.php:346 +msgid "Block" +msgstr "" + +#: lib/disfavorform.php:114 lib/disfavorform.php:140 +msgid "Disfavor this notice" +msgstr "" + +#: lib/facebookaction.php:268 #, php-format -msgid "notice id: %s" +msgid "To use the %s Facebook Application you need to login " msgstr "" -#: lib/joinform.php:114 -msgid "Join" +#: lib/facebookaction.php:271 lib/facebookaction.php:273 +#: lib/facebookaction.php:275 +msgid " a new account." msgstr "" -#: lib/leaveform.php:114 -msgid "Leave" +#: lib/facebookaction.php:557 lib/mailbox.php:214 lib/noticelist.php:354 +#: lib/facebookaction.php:675 lib/mailbox.php:216 lib/noticelist.php:357 +#: lib/mailbox.php:217 lib/noticelist.php:361 +msgid "Published" msgstr "" -#: lib/logingroupnav.php:80 -msgid "Login with a username and password" +#: lib/favorform.php:114 lib/favorform.php:140 +msgid "Favor this notice" msgstr "" -#: lib/logingroupnav.php:86 -msgid "Sign up for a new account" +#: lib/feedlist.php:64 +msgid "Export data" msgstr "" -#: lib/mailbox.php:89 -msgid "Only the user can read their own mailboxes." +#: lib/galleryaction.php:121 +msgid "Filter tags" msgstr "" -#: lib/mailbox.php:139 +#: lib/galleryaction.php:131 +msgid "All" +msgstr "" + +#: lib/galleryaction.php:137 lib/galleryaction.php:138 +#: lib/galleryaction.php:140 +msgid "Tag" +msgstr "" + +#: lib/galleryaction.php:138 lib/galleryaction.php:139 +#: lib/galleryaction.php:141 +msgid "Choose a tag to narrow list" +msgstr "" + +#: lib/galleryaction.php:139 lib/galleryaction.php:141 +#: lib/galleryaction.php:143 +msgid "Go" +msgstr "" + +#: lib/groupeditform.php:148 lib/groupeditform.php:163 +msgid "URL of the homepage or blog of the group or topic" +msgstr "" + +#: lib/groupeditform.php:151 lib/groupeditform.php:166 +#: lib/groupeditform.php:172 +msgid "Description" +msgstr "" + +#: lib/groupeditform.php:153 lib/groupeditform.php:168 +msgid "Describe the group or topic in 140 chars" +msgstr "" + +#: lib/groupeditform.php:158 lib/groupeditform.php:173 +#: lib/groupeditform.php:179 msgid "" -"You have no private messages. You can send private message to engage other " -"users in conversation. People can send you messages for your eyes only." +"Location for the group, if any, like \"City, State (or Region), Country\"" msgstr "" -#: lib/mailbox.php:227 lib/noticelist.php:424 -msgid "from" +#: lib/groupnav.php:84 lib/searchgroupnav.php:84 +msgid "Group" msgstr "" -#: lib/mail.php:172 -msgid "Email address confirmation" +#: lib/groupnav.php:100 actions/groupmembers.php:175 lib/groupnav.php:106 +msgid "Admin" msgstr "" -#: lib/mail.php:174 +#: lib/groupnav.php:101 lib/groupnav.php:107 #, php-format -msgid "" -"Hey, %s.\n" -"\n" -"Someone just entered this email address on %s.\n" -"\n" -"If it was you, and you want to confirm your entry, use the URL below:\n" -"\n" -"\t%s\n" -"\n" -"If not, just ignore this message.\n" -"\n" -"Thanks for your time, \n" -"%s\n" +msgid "Edit %s group properties" +msgstr "" + +#: lib/groupnav.php:106 lib/groupnav.php:112 +msgid "Logo" msgstr "" -#: lib/mail.php:235 +#: lib/groupnav.php:107 lib/groupnav.php:113 #, php-format -msgid "%1$s is now listening to your notices on %2$s." +msgid "Add or edit %s logo" +msgstr "" + +#: lib/groupsbymemberssection.php:71 +msgid "Groups with most members" +msgstr "" + +#: lib/groupsbypostssection.php:71 +msgid "Groups with most posts" +msgstr "" + +#: lib/grouptagcloudsection.php:56 +#, php-format +msgid "Tags in %s group's notices" +msgstr "" + +#: lib/htmloutputter.php:104 +msgid "This page is not available in a " +msgstr "" + +#: lib/joinform.php:114 +msgid "Join" +msgstr "" + +#: lib/leaveform.php:114 +msgid "Leave" +msgstr "" + +#: lib/logingroupnav.php:76 lib/logingroupnav.php:80 +msgid "Login with a username and password" +msgstr "" + +#: lib/logingroupnav.php:79 lib/logingroupnav.php:86 +msgid "Sign up for a new account" +msgstr "" + +#: lib/logingroupnav.php:82 +msgid "Login or register with OpenID" msgstr "" -#: lib/mail.php:240 +#: lib/mail.php:175 #, php-format msgid "" -"%1$s is now listening to your notices on %2$s.\n" -"\n" -"\t%3$s\n" -"\n" -"%4$s%5$s%6$s\n" -"Faithfully yours,\n" -"%7$s.\n" +"Hey, %s.\n" "\n" -"----\n" -"Change your email address or notification options at %8$s\n" msgstr "" -#: lib/mail.php:253 +#: lib/mail.php:236 +#, php-format +msgid "%1$s is now listening to " +msgstr "" + +#: lib/mail.php:254 lib/mail.php:253 #, php-format msgid "Location: %s\n" msgstr "" -#: lib/mail.php:255 +#: lib/mail.php:256 lib/mail.php:255 #, php-format msgid "Homepage: %s\n" msgstr "" -#: lib/mail.php:257 +#: lib/mail.php:258 lib/mail.php:257 #, php-format msgid "" "Bio: %s\n" "\n" msgstr "" -#: lib/mail.php:285 +#: lib/mail.php:461 lib/mail.php:462 #, php-format -msgid "New email address for posting to %s" +msgid "You've been nudged by %s" msgstr "" -#: lib/mail.php:288 +#: lib/mail.php:465 #, php-format -msgid "" -"You have a new posting address on %1$s.\n" -"\n" -"Send email to %2$s to post new messages.\n" -"\n" -"More email instructions at %3$s.\n" -"\n" -"Faithfully yours,\n" -"%4$s" +msgid "%1$s (%2$s) is wondering what you are up to " msgstr "" -#: lib/mail.php:412 +#: lib/mail.php:555 #, php-format -msgid "%s status" +msgid "%1$s just added your notice from %2$s" msgstr "" -#: lib/mail.php:438 -msgid "SMS confirmation" +#: lib/mailbox.php:229 lib/noticelist.php:380 lib/mailbox.php:231 +#: lib/noticelist.php:383 lib/mailbox.php:232 lib/noticelist.php:388 +msgid "From" msgstr "" -#: lib/mail.php:462 -#, php-format -msgid "You've been nudged by %s" +#: lib/messageform.php:110 lib/messageform.php:109 lib/messageform.php:120 +msgid "Send a direct notice" msgstr "" -#: lib/mail.php:466 -#, php-format -msgid "" -"%1$s (%2$s) is wondering what you are up to these days and is inviting you " -"to post some news.\n" -"\n" -"So let's hear from you :)\n" -"\n" -"%3$s\n" -"\n" -"Don't reply to this email; it won't get to them.\n" -"\n" -"With kind regards,\n" -"%4$s\n" +#: lib/noticeform.php:125 lib/noticeform.php:128 lib/noticeform.php:145 +msgid "Send a notice" msgstr "" -#: lib/mail.php:509 -#, php-format -msgid "New private message from %s" -msgstr "" - -#: lib/mail.php:513 -#, php-format -msgid "" -"%1$s (%2$s) sent you a private message:\n" -"\n" -"------------------------------------------------------\n" -"%3$s\n" -"------------------------------------------------------\n" -"\n" -"You can reply to their message here:\n" -"\n" -"%4$s\n" -"\n" -"Don't reply to this email; it won't get to them.\n" -"\n" -"With kind regards,\n" -"%5$s\n" -msgstr "" - -#: lib/mail.php:554 -#, php-format -msgid "%s (@%s) added your notice as a favorite" +#: lib/noticeform.php:152 lib/noticeform.php:149 lib/messageform.php:162 +#: lib/noticeform.php:173 +msgid "Available characters" msgstr "" -#: lib/mail.php:556 -#, php-format -msgid "" -"%1$s (@%7$s) just added your notice from %2$s as one of their favorites.\n" -"\n" -"The URL of your notice is:\n" -"\n" -"%3$s\n" -"\n" -"The text of your notice is:\n" -"\n" -"%4$s\n" -"\n" -"You can see the list of %1$s's favorites here:\n" -"\n" -"%5$s\n" -"\n" -"Faithfully yours,\n" -"%6$s\n" +#: lib/noticelist.php:426 lib/noticelist.php:429 +msgid "in reply to" msgstr "" -#: lib/mail.php:611 -#, php-format -msgid "%s (@%s) sent a notice to your attention" +#: lib/noticelist.php:447 lib/noticelist.php:450 lib/noticelist.php:451 +#: lib/noticelist.php:454 lib/noticelist.php:458 lib/noticelist.php:461 +#: lib/noticelist.php:498 +msgid "Reply to this notice" msgstr "" -#: lib/mail.php:613 -#, php-format -msgid "" -"%1$s (@%9$s) just sent a notice to your attention (an '@-reply') on %2$s.\n" -"\n" -"The notice is here:\n" -"\n" -"\t%3$s\n" -"\n" -"It reads:\n" -"\n" -"\t%4$s\n" -"\n" +#: lib/noticelist.php:451 lib/noticelist.php:455 lib/noticelist.php:462 +#: lib/noticelist.php:499 +msgid "Reply" msgstr "" -#: lib/mediafile.php:98 lib/mediafile.php:123 -msgid "There was a database error while saving your file. Please try again." +#: lib/noticelist.php:471 lib/noticelist.php:474 lib/noticelist.php:476 +#: lib/noticelist.php:479 actions/deletenotice.php:116 lib/noticelist.php:483 +#: lib/noticelist.php:486 actions/deletenotice.php:146 lib/noticelist.php:522 +msgid "Delete this notice" msgstr "" -#: lib/mediafile.php:142 -msgid "The uploaded file exceeds the upload_max_filesize directive in php.ini." +#: lib/noticelist.php:474 actions/avatarsettings.php:148 +#: lib/noticelist.php:479 lib/noticelist.php:486 lib/noticelist.php:522 +msgid "Delete" msgstr "" -#: lib/mediafile.php:147 -msgid "" -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in " -"the HTML form." +#: lib/nudgeform.php:116 +msgid "Nudge this user" msgstr "" -#: lib/mediafile.php:152 -msgid "The uploaded file was only partially uploaded." +#: lib/nudgeform.php:128 +msgid "Nudge" msgstr "" -#: lib/mediafile.php:159 -msgid "Missing a temporary folder." +#: lib/nudgeform.php:128 +msgid "Send a nudge to this user" msgstr "" -#: lib/mediafile.php:162 -msgid "Failed to write file to disk." +#: lib/personaltagcloudsection.php:56 +#, php-format +msgid "Tags in %s's notices" msgstr "" -#: lib/mediafile.php:165 -msgid "File upload stopped by extension." +#: lib/profilelist.php:182 lib/profilelist.php:180 +#: lib/subscriptionlist.php:126 +msgid "(none)" msgstr "" -#: lib/mediafile.php:179 lib/mediafile.php:216 -msgid "File exceeds user's quota!" +#: lib/publicgroupnav.php:76 lib/publicgroupnav.php:78 +msgid "Public" msgstr "" -#: lib/mediafile.php:196 lib/mediafile.php:233 -msgid "File could not be moved to destination directory." +#: lib/publicgroupnav.php:80 lib/publicgroupnav.php:82 +msgid "User groups" msgstr "" -#: lib/mediafile.php:201 lib/mediafile.php:237 -msgid "Could not determine file's mime-type!" +#: lib/publicgroupnav.php:82 lib/publicgroupnav.php:83 +#: lib/publicgroupnav.php:84 lib/publicgroupnav.php:85 +msgid "Recent tags" msgstr "" -#: lib/mediafile.php:270 -#, php-format -msgid " Try using another %s format." +#: lib/publicgroupnav.php:86 lib/publicgroupnav.php:88 +msgid "Featured" msgstr "" -#: lib/mediafile.php:275 -#, php-format -msgid "%s is not a supported filetype on this server." +#: lib/publicgroupnav.php:90 lib/publicgroupnav.php:92 +msgid "Popular" msgstr "" -#: lib/messageform.php:120 -msgid "Send a direct notice" +#: lib/searchgroupnav.php:82 +msgid "Notice" msgstr "" -#: lib/messageform.php:146 -msgid "To" +#: lib/searchgroupnav.php:85 +msgid "Find groups on this site" msgstr "" -#: lib/messageform.php:162 lib/noticeform.php:173 -msgid "Available characters" +#: lib/section.php:89 +msgid "Untitled section" msgstr "" -#: lib/noticeform.php:145 -msgid "Send a notice" +#: lib/subgroupnav.php:81 lib/subgroupnav.php:83 +#, php-format +msgid "People %s subscribes to" msgstr "" -#: lib/noticeform.php:158 +#: lib/subgroupnav.php:89 lib/subgroupnav.php:91 #, php-format -msgid "What's up, %s?" +msgid "People subscribed to %s" msgstr "" -#: lib/noticeform.php:180 -msgid "Attach" +#: lib/subgroupnav.php:97 lib/subgroupnav.php:99 +#, php-format +msgid "Groups %s is a member of" msgstr "" -#: lib/noticeform.php:184 -msgid "Attach a file" +#: lib/subgroupnav.php:104 lib/action.php:430 lib/subgroupnav.php:106 +#: lib/action.php:440 +#, php-format +msgid "Invite friends and colleagues to join you on %s" msgstr "" -#: lib/noticelist.php:478 -msgid "in context" +#: lib/subs.php:53 lib/subs.php:52 +msgid "User has blocked you." msgstr "" -#: lib/noticelist.php:498 -msgid "Reply to this notice" +#: lib/subscribeform.php:115 lib/subscribeform.php:139 +#: actions/userauthorization.php:178 actions/userauthorization.php:210 +msgid "Subscribe to this user" msgstr "" -#: lib/noticelist.php:499 -msgid "Reply" +#: lib/tagcloudsection.php:56 +msgid "None" msgstr "" -#: lib/nudgeform.php:116 -msgid "Nudge this user" +#: lib/topposterssection.php:74 +msgid "Top posters" msgstr "" -#: lib/nudgeform.php:128 -msgid "Nudge" +#: lib/unblockform.php:120 lib/unblockform.php:150 +#: actions/blockedfromgroup.php:313 +msgid "Unblock this user" msgstr "" -#: lib/nudgeform.php:128 -msgid "Send a nudge to this user" +#: lib/unblockform.php:150 actions/blockedfromgroup.php:313 +msgid "Unblock" msgstr "" -#: lib/oauthstore.php:283 -msgid "Error inserting new profile" +#: lib/unsubscribeform.php:113 lib/unsubscribeform.php:137 +msgid "Unsubscribe from this user" msgstr "" -#: lib/oauthstore.php:291 -msgid "Error inserting avatar" +#: actions/all.php:77 actions/all.php:59 actions/all.php:99 +#, php-format +msgid "Feed for friends of %s (RSS 1.0)" msgstr "" -#: lib/oauthstore.php:311 -msgid "Error inserting remote profile" +#: actions/all.php:82 actions/all.php:64 actions/all.php:107 +#, php-format +msgid "Feed for friends of %s (RSS 2.0)" msgstr "" -#: lib/oauthstore.php:345 -msgid "Duplicate notice" +#: actions/all.php:87 actions/all.php:69 actions/all.php:115 +#, php-format +msgid "Feed for friends of %s (Atom)" msgstr "" -#: lib/oauthstore.php:487 -msgid "Couldn't insert new subscription." +#: actions/all.php:112 actions/all.php:125 actions/all.php:165 +msgid "You and friends" msgstr "" -#: lib/personalgroupnav.php:99 -msgid "Personal" +#: actions/avatarsettings.php:78 +#, php-format +msgid "You can upload your personal avatar. The maximum file size is %s." msgstr "" -#: lib/personalgroupnav.php:104 -msgid "Replies" +#: actions/avatarsettings.php:373 actions/avatarsettings.php:387 +msgid "Avatar deleted." msgstr "" -#: lib/personalgroupnav.php:114 -msgid "Favorites" +#: actions/block.php:129 actions/block.php:136 +msgid "" +"Are you sure you want to block this user? Afterwards, they will be " +"unsubscribed from you, unable to subscribe to you in the future, and you " +"will not be notified of any @-replies from them." msgstr "" -#: lib/personalgroupnav.php:115 -msgid "User" +#: actions/deletenotice.php:73 actions/deletenotice.php:103 +msgid "" +"You are about to permanently delete a notice. Once this is done, it cannot " +"be undone." msgstr "" -#: lib/personalgroupnav.php:124 -msgid "Inbox" +#: actions/deletenotice.php:127 actions/deletenotice.php:157 +msgid "There was a problem with your session token. Try again, please." msgstr "" -#: lib/personalgroupnav.php:125 -msgid "Your incoming messages" +#: actions/emailsettings.php:168 actions/emailsettings.php:174 +msgid "Send me email when someone sends me an \"@-reply\"." msgstr "" -#: lib/personalgroupnav.php:129 -msgid "Outbox" +#: actions/facebookhome.php:193 actions/facebookhome.php:187 +#, php-format +msgid "" +"If you would like the %s app to automatically update your Facebook status " +"with your latest notice, you need to give it permission." msgstr "" -#: lib/personalgroupnav.php:130 -msgid "Your sent messages" +#: actions/facebookhome.php:217 actions/facebookhome.php:211 +#, php-format +msgid "Okay, do it!" msgstr "" -#: lib/personaltagcloudsection.php:56 +#: actions/facebooksettings.php:124 #, php-format -msgid "Tags in %s's notices" +msgid "" +"If you would like %s to automatically update your Facebook status with your " +"latest notice, you need to give it permission." msgstr "" -#: lib/profileaction.php:109 lib/profileaction.php:191 lib/subgroupnav.php:82 -msgid "Subscriptions" +#: actions/grouplogo.php:155 actions/grouplogo.php:150 +#, php-format +msgid "" +"You can upload a logo image for your group. The maximum file size is %s." msgstr "" -#: lib/profileaction.php:126 -msgid "All subscriptions" +#: actions/grouplogo.php:367 actions/grouplogo.php:362 +msgid "Pick a square area of the image to be the logo." msgstr "" -#: lib/profileaction.php:140 lib/profileaction.php:200 lib/subgroupnav.php:90 -msgid "Subscribers" +#: actions/grouprss.php:136 actions/grouprss.php:137 +#, php-format +msgid "Microblog by %s group" msgstr "" -#: lib/profileaction.php:157 -msgid "All subscribers" +#: actions/groupsearch.php:57 actions/groupsearch.php:52 +#, php-format +msgid "" +"Search for groups on %%site.name%% by their name, location, or description. " +"Separate the terms by spaces; they must be 3 characters or more." msgstr "" -#: lib/profileaction.php:177 -msgid "User ID" +#: actions/groups.php:90 +#, php-format +msgid "" +"%%%%site.name%%%% groups let you find and talk with people of similar " +"interests. After you join a group you can send messages to all other members " +"using the syntax \"!groupname\". Don't see a group you like? Try [searching " +"for one](%%%%action.groupsearch%%%%) or [start your own!](%%%%action.newgroup" +"%%%%)" msgstr "" -#: lib/profileaction.php:182 -msgid "Member since" +#: actions/newmessage.php:102 +msgid "Only logged-in users can send direct messages." msgstr "" -#: lib/profileaction.php:235 -msgid "All groups" +#: actions/noticesearch.php:91 +#, php-format +msgid "Search results for \"%s\" on %s" msgstr "" -#: lib/publicgroupnav.php:78 -msgid "Public" +#: actions/openidlogin.php:66 +#, php-format +msgid "" +"For security reasons, please re-login with your [OpenID](%%doc.openid%%) " +"before changing your settings." msgstr "" -#: lib/publicgroupnav.php:82 -msgid "User groups" +#: actions/public.php:125 actions/public.php:133 actions/public.php:151 +msgid "Public Stream Feed (RSS 1.0)" msgstr "" -#: lib/publicgroupnav.php:84 lib/publicgroupnav.php:85 -msgid "Recent tags" +#: actions/public.php:130 actions/public.php:138 actions/public.php:155 +msgid "Public Stream Feed (RSS 2.0)" msgstr "" -#: lib/publicgroupnav.php:88 -msgid "Featured" +#: actions/public.php:135 actions/public.php:143 actions/public.php:159 +msgid "Public Stream Feed (Atom)" msgstr "" -#: lib/publicgroupnav.php:92 -msgid "Popular" +#: actions/public.php:210 actions/public.php:241 actions/public.php:233 +#, php-format +msgid "" +"This is %%site.name%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-" +"blogging) service based on the Free Software [StatusNet](http://status.net/) " +"tool. [Join now](%%action.register%%) to share notices about yourself with " +"friends, family, and colleagues! ([Read more](%%doc.help%%))" msgstr "" -#: lib/searchaction.php:120 -msgid "Search site" +#: actions/register.php:286 actions/register.php:329 +#, php-format +msgid "" +"With this form you can create a new account. You can then post notices and " +"link up to friends and colleagues. (Have an [OpenID](http://openid.net/)? " +"Try our [OpenID registration](%%action.openidlogin%%)!)" msgstr "" -#: lib/searchaction.php:162 -msgid "Search help" +#: actions/register.php:432 actions/register.php:479 actions/register.php:489 +#: actions/register.php:495 +msgid "Creative Commons Attribution 3.0" msgstr "" -#: lib/searchgroupnav.php:80 -msgid "People" +#: actions/register.php:433 actions/register.php:480 actions/register.php:490 +#: actions/register.php:496 +msgid "" +" except this private data: password, email address, IM address, and phone " +"number." msgstr "" -#: lib/searchgroupnav.php:81 -msgid "Find people on this site" +#: actions/showgroup.php:378 actions/showgroup.php:424 +#: actions/showgroup.php:432 +msgid "Created" msgstr "" -#: lib/searchgroupnav.php:82 -msgid "Notice" +#: actions/showgroup.php:393 actions/showgroup.php:440 +#: actions/showgroup.php:448 +#, php-format +msgid "" +"**%s** is a user group on %%%%site.name%%%%, a [micro-blogging](http://en." +"wikipedia.org/wiki/Micro-blogging) service based on the Free Software " +"[StatusNet](http://status.net/) tool. Its members share short messages about " +"their life and interests. [Join now](%%%%action.register%%%%) to become part " +"of this group and many more! ([Read more](%%%%doc.help%%%%))" msgstr "" -#: lib/searchgroupnav.php:83 -msgid "Find content of notices" +#: actions/showstream.php:147 +msgid "Your profile" msgstr "" -#: lib/searchgroupnav.php:85 -msgid "Find groups on this site" +#: actions/showstream.php:149 +#, php-format +msgid "%s's profile" msgstr "" -#: lib/section.php:89 -msgid "Untitled section" +#: actions/showstream.php:163 actions/showstream.php:128 +#: actions/showstream.php:129 +#, php-format +msgid "Notice feed for %s (RSS 1.0)" msgstr "" -#: lib/section.php:106 -msgid "More..." +#: actions/showstream.php:170 actions/showstream.php:135 +#: actions/showstream.php:136 +#, php-format +msgid "Notice feed for %s (RSS 2.0)" msgstr "" -#: lib/subgroupnav.php:83 +#: actions/showstream.php:177 actions/showstream.php:142 +#: actions/showstream.php:143 #, php-format -msgid "People %s subscribes to" +msgid "Notice feed for %s (Atom)" msgstr "" -#: lib/subgroupnav.php:91 +#: actions/showstream.php:182 actions/showstream.php:147 +#: actions/showstream.php:148 #, php-format -msgid "People subscribed to %s" +msgid "FOAF for %s" +msgstr "" + +#: actions/showstream.php:237 actions/showstream.php:202 +#: actions/showstream.php:234 lib/userprofile.php:116 +msgid "Edit Avatar" +msgstr "" + +#: actions/showstream.php:316 actions/showstream.php:281 +#: actions/showstream.php:366 lib/userprofile.php:248 +msgid "Edit profile settings" msgstr "" -#: lib/subgroupnav.php:99 +#: actions/showstream.php:317 actions/showstream.php:282 +#: actions/showstream.php:367 lib/userprofile.php:249 +msgid "Edit" +msgstr "" + +#: actions/showstream.php:542 actions/showstream.php:388 +#: actions/showstream.php:487 actions/showstream.php:234 #, php-format -msgid "Groups %s is a member of" +msgid "" +"**%s** has an account on %%%%site.name%%%%, a [micro-blogging](http://en." +"wikipedia.org/wiki/Micro-blogging) service based on the Free Software " +"[StatusNet](http://status.net/) tool. [Join now](%%%%action.register%%%%) to " +"follow **%s**'s notices and many more! ([Read more](%%%%doc.help%%%%))" msgstr "" -#: lib/subscriberspeopleselftagcloudsection.php:48 -#: lib/subscriptionspeopleselftagcloudsection.php:48 -msgid "People Tagcloud as self-tagged" +#: actions/smssettings.php:335 actions/smssettings.php:347 +msgid "" +"A confirmation code was sent to the phone number you added. Check your phone " +"for the code and instructions on how to use it." msgstr "" -#: lib/subscriberspeopletagcloudsection.php:48 -#: lib/subscriptionspeopletagcloudsection.php:48 -msgid "People Tagcloud as tagged" +#: actions/twitapifavorites.php:171 lib/mail.php:556 +#: actions/twitapifavorites.php:222 +#, php-format +msgid "" +"%1$s just added your notice from %2$s as one of their favorites.\n" +"\n" +"In case you forgot, you can see the text of your notice here:\n" +"\n" +"%3$s\n" +"\n" +"You can see the list of %1$s's favorites here:\n" +"\n" +"%4$s\n" +"\n" +"Faithfully yours,\n" +"%5$s\n" msgstr "" -#: lib/subscriptionlist.php:126 -msgid "(none)" +#: actions/twitapistatuses.php:124 actions/twitapistatuses.php:82 +#: actions/twitapistatuses.php:314 actions/apiblockcreate.php:97 +#: actions/apiblockdestroy.php:96 actions/apidirectmessage.php:77 +#: actions/apidirectmessagenew.php:75 actions/apigroupcreate.php:112 +#: actions/apigroupismember.php:90 actions/apigroupjoin.php:99 +#: actions/apigroupleave.php:99 actions/apigrouplist.php:90 +#: actions/apistatusesupdate.php:125 actions/apisubscriptions.php:87 +#: actions/apitimelinefavorites.php:70 actions/apitimelinefriends.php:79 +#: actions/apitimelinementions.php:79 actions/apitimelineuser.php:81 +#: actions/apiaccountupdateprofileimage.php:91 +#: actions/apiaccountupdateprofileimage.php:105 +#: actions/apistatusesupdate.php:139 +msgid "No such user!" msgstr "" -#: lib/subs.php:48 -msgid "Already subscribed!" +#: actions/twittersettings.php:72 +msgid "" +"Add your Twitter account to automatically send your notices to Twitter, and " +"subscribe to Twitter friends already here." msgstr "" -#: lib/subs.php:52 -msgid "User has blocked you." +#: actions/twittersettings.php:345 actions/twittersettings.php:362 +#, php-format +msgid "Unable to retrieve account information For \"%s\" from Twitter." msgstr "" -#: lib/subs.php:56 -msgid "Could not subscribe." +#: actions/userauthorization.php:86 actions/userauthorization.php:81 +msgid "" +"Please check these details to make sure that you want to subscribe to this " +"user's notices. If you didn't just ask to subscribe to someone's notices, " +"click \"Reject\"." msgstr "" -#: lib/subs.php:75 -msgid "Could not subscribe other to you." +#: actions/usergroups.php:131 actions/usergroups.php:130 +msgid "Search for more groups" msgstr "" -#: lib/subs.php:124 -msgid "Not subscribed!." +#: classes/Notice.php:138 classes/Notice.php:154 classes/Notice.php:194 +msgid "" +"Too many duplicate messages too quickly; take a breather and post again in a " +"few minutes." msgstr "" -#: lib/subs.php:136 -msgid "Couldn't delete subscription." +#: lib/action.php:406 lib/action.php:425 +msgid "Connect to SMS, Twitter" msgstr "" -#: lib/tagcloudsection.php:56 -msgid "None" +#: lib/action.php:671 lib/action.php:721 lib/action.php:736 +msgid "Badge" msgstr "" -#: lib/topposterssection.php:74 -msgid "Top posters" +#: lib/command.php:113 lib/command.php:106 lib/command.php:126 +#, php-format +msgid "" +"Subscriptions: %1$s\n" +"Subscribers: %2$s\n" +"Notices: %3$s" msgstr "" -#: lib/unsubscribeform.php:113 lib/unsubscribeform.php:137 -msgid "Unsubscribe from this user" +#: lib/dberroraction.php:60 +msgid "Database error" msgstr "" -#: lib/unsubscribeform.php:137 -msgid "Unsubscribe" +#: lib/facebookaction.php:271 lib/facebookaction.php:273 +#, php-format +msgid "" +"To use the %s Facebook Application you need to login with your username and " +"password. Don't have a username yet? " msgstr "" -#: lib/userprofile.php:116 -msgid "Edit Avatar" +#: lib/feed.php:85 +msgid "RSS 1.0" msgstr "" -#: lib/userprofile.php:236 -msgid "User actions" +#: lib/feed.php:87 +msgid "RSS 2.0" msgstr "" -#: lib/userprofile.php:248 -msgid "Edit profile settings" +#: lib/feed.php:89 +msgid "Atom" msgstr "" -#: lib/userprofile.php:249 -msgid "Edit" +#: lib/feed.php:91 +msgid "FOAF" msgstr "" -#: lib/userprofile.php:272 -msgid "Send a direct message to this user" +#: lib/imagefile.php:75 +#, php-format +msgid "That file is too big. The maximum file size is %d." msgstr "" -#: lib/userprofile.php:273 -msgid "Message" +#: lib/mail.php:175 lib/mail.php:174 +#, php-format +msgid "" +"Hey, %s.\n" +"\n" +"Someone just entered this email address on %s.\n" +"\n" +"If it was you, and you want to confirm your entry, use the URL below:\n" +"\n" +"\t%s\n" +"\n" +"If not, just ignore this message.\n" +"\n" +"Thanks for your time, \n" +"%s\n" msgstr "" -#: lib/util.php:844 -msgid "a few seconds ago" +#: lib/mail.php:241 lib/mail.php:240 +#, php-format +msgid "" +"%1$s is now listening to your notices on %2$s.\n" +"\n" +"\t%3$s\n" +"\n" +"%4$s%5$s%6$s\n" +"Faithfully yours,\n" +"%7$s.\n" +"\n" +"----\n" +"Change your email address or notification options at %8$s\n" msgstr "" -#: lib/util.php:846 -msgid "about a minute ago" +#: lib/mail.php:466 +#, php-format +msgid "" +"%1$s (%2$s) is wondering what you are up to these days and is inviting you " +"to post some news.\n" +"\n" +"So let's hear from you :)\n" +"\n" +"%3$s\n" +"\n" +"Don't reply to this email; it won't get to them.\n" +"\n" +"With kind regards,\n" +"%4$s\n" msgstr "" -#: lib/util.php:848 +#: lib/mail.php:513 #, php-format -msgid "about %d minutes ago" +msgid "" +"%1$s (%2$s) sent you a private message:\n" +"\n" +"------------------------------------------------------\n" +"%3$s\n" +"------------------------------------------------------\n" +"\n" +"You can reply to their message here:\n" +"\n" +"%4$s\n" +"\n" +"Don't reply to this email; it won't get to them.\n" +"\n" +"With kind regards,\n" +"%5$s\n" msgstr "" -#: lib/util.php:850 -msgid "about an hour ago" +#: lib/mail.php:598 lib/mail.php:600 +#, php-format +msgid "%s sent a notice to your attention" msgstr "" -#: lib/util.php:852 +#: lib/mail.php:600 lib/mail.php:602 #, php-format -msgid "about %d hours ago" +msgid "" +"%1$s just sent a notice to your attention (an '@-reply') on %2$s.\n" +"\n" +"The notice is here:\n" +"\n" +"\t%3$s\n" +"\n" +"It reads:\n" +"\n" +"\t%4$s\n" +"\n" +"You can reply back here:\n" +"\n" +"\t%5$s\n" +"\n" +"The list of all @-replies for you here:\n" +"\n" +"%6$s\n" +"\n" +"Faithfully yours,\n" +"%2$s\n" +"\n" +"P.S. You can turn off these email notifications here: %7$s\n" msgstr "" -#: lib/util.php:854 -msgid "about a day ago" +#: lib/searchaction.php:122 lib/searchaction.php:120 +msgid "Search site" +msgstr "" + +#: lib/section.php:106 +msgid "More..." msgstr "" -#: lib/util.php:856 +#: actions/all.php:80 actions/all.php:127 #, php-format -msgid "about %d days ago" +msgid "" +"This is the timeline for %s and friends but no one has posted anything yet." msgstr "" -#: lib/util.php:858 -msgid "about a month ago" +#: actions/all.php:85 actions/all.php:132 +#, php-format +msgid "" +"Try subscribing to more people, [join a group](%%action.groups%%) or post " +"something yourself." msgstr "" -#: lib/util.php:860 +#: actions/all.php:87 actions/all.php:134 #, php-format -msgid "about %d months ago" +msgid "" +"You can try to [nudge %s](../%s) from his profile or [post something to his " +"or her attention](%%%%action.newnotice%%%%?status_textarea=%s)." msgstr "" -#: lib/util.php:862 -msgid "about a year ago" +#: actions/all.php:91 actions/replies.php:190 actions/showstream.php:361 +#: actions/all.php:137 actions/replies.php:209 actions/showstream.php:455 +#: actions/showstream.php:202 +#, php-format +msgid "" +"Why not [register an account](%%%%action.register%%%%) and then nudge %s or " +"post a notice to his or her attention." msgstr "" -#: lib/webcolor.php:82 +#: actions/attachment.php:73 +msgid "No such attachment." +msgstr "" + +#: actions/block.php:149 +msgid "Do not block this user from this group" +msgstr "" + +#: actions/block.php:150 +msgid "Block this user from this group" +msgstr "" + +#: actions/blockedfromgroup.php:90 #, php-format -msgid "%s is not a valid color!" +msgid "%s blocked profiles" msgstr "" -#: lib/webcolor.php:123 +#: actions/blockedfromgroup.php:93 #, php-format -msgid "%s is not a valid color! Use 3 or 6 hex chars." +msgid "%s blocked profiles, page %d" msgstr "" -#: scripts/maildaemon.php:48 -msgid "Could not parse message." +#: actions/blockedfromgroup.php:108 +msgid "A list of the users blocked from joining this group." msgstr "" -#: scripts/maildaemon.php:53 -msgid "Not a registered user." +#: actions/blockedfromgroup.php:281 +msgid "Unblock user from group" msgstr "" -#: scripts/maildaemon.php:57 -msgid "Sorry, that is not your incoming email address." +#: actions/conversation.php:99 +msgid "Conversation" msgstr "" -#: scripts/maildaemon.php:61 -msgid "Sorry, no incoming email allowed." +#: actions/deletenotice.php:115 actions/deletenotice.php:145 +msgid "Do not delete this notice" +msgstr "" + +#: actions/editgroup.php:214 actions/newgroup.php:164 +#: actions/apigroupcreate.php:291 actions/editgroup.php:215 +#: actions/newgroup.php:159 +#, php-format +msgid "Too many aliases! Maximum %d." +msgstr "" + +#: actions/editgroup.php:223 actions/newgroup.php:173 +#: actions/apigroupcreate.php:312 actions/editgroup.php:224 +#: actions/newgroup.php:168 +#, php-format +msgid "Invalid alias: \"%s\"" +msgstr "" + +#: actions/editgroup.php:227 actions/newgroup.php:177 +#: actions/apigroupcreate.php:321 actions/editgroup.php:228 +#: actions/newgroup.php:172 +#, php-format +msgid "Alias \"%s\" already in use. Try another one." +msgstr "" + +#: actions/editgroup.php:233 actions/newgroup.php:183 +#: actions/apigroupcreate.php:334 actions/editgroup.php:234 +#: actions/newgroup.php:178 +msgid "Alias can't be the same as nickname." +msgstr "" + +#: actions/editgroup.php:259 actions/newgroup.php:215 +#: actions/apigroupcreate.php:147 actions/newgroup.php:210 +msgid "Could not create aliases." +msgstr "" + +#: actions/favorited.php:150 +msgid "Favorite notices appear on this page but no one has favorited one yet." +msgstr "" + +#: actions/favorited.php:153 +msgid "" +"Be the first to add a notice to your favorites by clicking the fave button " +"next to any notice you like." +msgstr "" + +#: actions/favorited.php:156 +#, php-format +msgid "" +"Why not [register an account](%%action.register%%) and be the first to add a " +"notice to your favorites!" +msgstr "" + +#: actions/file.php:34 +msgid "No notice id" +msgstr "" + +#: actions/file.php:38 +msgid "No notice" +msgstr "" + +#: actions/file.php:42 +msgid "No attachments" +msgstr "" + +#: actions/file.php:51 +msgid "No uploaded attachments" +msgstr "" + +#: actions/finishopenidlogin.php:211 +msgid "Not a valid invitation code." +msgstr "" + +#: actions/groupblock.php:81 actions/groupunblock.php:81 +#: actions/makeadmin.php:81 +msgid "No group specified." +msgstr "" + +#: actions/groupblock.php:91 +msgid "Only an admin can block group members." +msgstr "" + +#: actions/groupblock.php:95 +msgid "User is already blocked from group." +msgstr "" + +#: actions/groupblock.php:100 +msgid "User is not a member of group." +msgstr "" + +#: actions/groupblock.php:136 actions/groupmembers.php:311 +#: actions/groupmembers.php:314 +msgid "Block user from group" +msgstr "" + +#: actions/groupblock.php:155 +#, php-format +msgid "" +"Are you sure you want to block user \"%s\" from the group \"%s\"? They will " +"be removed from the group, unable to post, and unable to subscribe to the " +"group in the future." +msgstr "" + +#: actions/groupblock.php:193 +msgid "Database error blocking user from group." +msgstr "" + +#: actions/groupdesignsettings.php:73 actions/groupdesignsettings.php:68 +msgid "You must be logged in to edit a group." +msgstr "" + +#: actions/groupdesignsettings.php:146 actions/groupdesignsettings.php:141 +msgid "Group design" +msgstr "" + +#: actions/groupdesignsettings.php:157 actions/groupdesignsettings.php:152 +msgid "" +"Customize the way your group looks with a background image and a colour " +"palette of your choice." +msgstr "" + +#: actions/groupdesignsettings.php:267 actions/userdesignsettings.php:186 +#: lib/designsettings.php:440 lib/designsettings.php:470 +#: actions/groupdesignsettings.php:262 lib/designsettings.php:431 +#: lib/designsettings.php:461 lib/designsettings.php:434 +#: lib/designsettings.php:464 +msgid "Couldn't update your design." +msgstr "" + +#: actions/groupdesignsettings.php:291 actions/groupdesignsettings.php:301 +#: actions/userdesignsettings.php:210 actions/userdesignsettings.php:220 +#: actions/userdesignsettings.php:263 actions/userdesignsettings.php:273 +#: actions/groupdesignsettings.php:286 actions/groupdesignsettings.php:296 +msgid "Unable to save your design settings!" +msgstr "" + +#: actions/groupdesignsettings.php:312 actions/userdesignsettings.php:231 +#: actions/groupdesignsettings.php:307 +msgid "Design preferences saved." +msgstr "" + +#: actions/groupmembers.php:438 actions/groupmembers.php:441 +msgid "Make user an admin of the group" +msgstr "" + +#: actions/groupmembers.php:470 actions/groupmembers.php:473 +msgid "Make Admin" +msgstr "" + +#: actions/groupmembers.php:470 actions/groupmembers.php:473 +msgid "Make this user an admin" +msgstr "" + +#: actions/groupsearch.php:79 actions/noticesearch.php:117 +#: actions/peoplesearch.php:83 +msgid "No results." +msgstr "" + +#: actions/groupsearch.php:82 +#, php-format +msgid "" +"If you can't find the group you're looking for, you can [create it](%%action." +"newgroup%%) yourself." +msgstr "" + +#: actions/groupsearch.php:85 +#, php-format +msgid "" +"Why not [register an account](%%action.register%%) and [create the group](%%" +"action.newgroup%%) yourself!" +msgstr "" + +#: actions/groupunblock.php:91 +msgid "Only an admin can unblock group members." +msgstr "" + +#: actions/groupunblock.php:95 +msgid "User is not blocked from group." +msgstr "" + +#: actions/invite.php:39 +msgid "Invites have been disabled." +msgstr "" + +#: actions/joingroup.php:100 actions/apigroupjoin.php:119 +#: actions/joingroup.php:95 lib/command.php:221 +msgid "You have been blocked from that group by the admin." +msgstr "" + +#: actions/makeadmin.php:91 +msgid "Only an admin can make another user an admin." +msgstr "" + +#: actions/makeadmin.php:95 +#, php-format +msgid "%s is already an admin for group \"%s\"." +msgstr "" + +#: actions/makeadmin.php:132 +#, php-format +msgid "Can't get membership record for %s in group %s" +msgstr "" + +#: actions/makeadmin.php:145 +#, php-format +msgid "Can't make %s an admin for group %s" +msgstr "" + +#: actions/newmessage.php:178 actions/newmessage.php:181 +msgid "Message sent" +msgstr "" + +#: actions/newnotice.php:93 lib/designsettings.php:281 +#: actions/newnotice.php:94 actions/apiaccountupdateprofileimage.php:97 +#: actions/apistatusesupdate.php:122 actions/avatarsettings.php:254 +#: lib/designsettings.php:283 +#, php-format +msgid "" +"The server was unable to handle that much POST data (%s bytes) due to its " +"current configuration." +msgstr "" + +#: actions/newnotice.php:128 scripts/maildaemon.php:185 lib/mediafile.php:270 +#, php-format +msgid " Try using another %s format." +msgstr "" + +#: actions/newnotice.php:133 scripts/maildaemon.php:190 lib/mediafile.php:275 +#, php-format +msgid "%s is not a supported filetype on this server." +msgstr "" + +#: actions/newnotice.php:205 lib/mediafile.php:142 +msgid "The uploaded file exceeds the upload_max_filesize directive in php.ini." +msgstr "" + +#: actions/newnotice.php:208 lib/mediafile.php:147 +msgid "" +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in " +"the HTML form." +msgstr "" + +#: actions/newnotice.php:211 lib/mediafile.php:152 +msgid "The uploaded file was only partially uploaded." +msgstr "" + +#: actions/newnotice.php:214 lib/mediafile.php:159 +msgid "Missing a temporary folder." +msgstr "" + +#: actions/newnotice.php:217 lib/mediafile.php:162 +msgid "Failed to write file to disk." +msgstr "" + +#: actions/newnotice.php:220 lib/mediafile.php:165 +msgid "File upload stopped by extension." +msgstr "" + +#: actions/newnotice.php:230 scripts/maildaemon.php:85 +msgid "Couldn't save file." +msgstr "" + +#: actions/newnotice.php:246 scripts/maildaemon.php:101 +msgid "Max notice size is 140 chars, including attachment URL." +msgstr "" + +#: actions/newnotice.php:297 +msgid "Somehow lost the login in saveFile" +msgstr "" + +#: actions/newnotice.php:309 scripts/maildaemon.php:127 lib/mediafile.php:196 +#: lib/mediafile.php:233 +msgid "File could not be moved to destination directory." +msgstr "" + +#: actions/newnotice.php:336 actions/newnotice.php:360 +#: scripts/maildaemon.php:148 scripts/maildaemon.php:167 lib/mediafile.php:98 +#: lib/mediafile.php:123 +msgid "There was a database error while saving your file. Please try again." +msgstr "" + +#: actions/noticesearch.php:121 +#, php-format +msgid "" +"Be the first to [post on this topic](%%%%action.newnotice%%%%?" +"status_textarea=%s)!" +msgstr "" + +#: actions/noticesearch.php:124 +#, php-format +msgid "" +"Why not [register an account](%%%%action.register%%%%) and be the first to " +"[post on this topic](%%%%action.newnotice%%%%?status_textarea=%s)!" +msgstr "" + +#: actions/openidsettings.php:70 +#, php-format +msgid "" +"[OpenID](%%doc.openid%%) lets you log into many sites with the same user " +"account. Manage your associated OpenIDs from here." +msgstr "" + +#: actions/othersettings.php:110 actions/othersettings.php:117 +msgid "Shorten URLs with" +msgstr "" + +#: actions/othersettings.php:115 actions/othersettings.php:122 +msgid "View profile designs" +msgstr "" + +#: actions/othersettings.php:116 actions/othersettings.php:123 +msgid "Show or hide profile designs." +msgstr "" + +#: actions/public.php:82 actions/public.php:83 +#, php-format +msgid "Beyond the page limit (%s)" +msgstr "" + +#: actions/public.php:179 +#, php-format +msgid "" +"This is the public timeline for %%site.name%% but no one has posted anything " +"yet." +msgstr "" + +#: actions/public.php:182 +msgid "Be the first to post!" +msgstr "" + +#: actions/public.php:186 +#, php-format +msgid "" +"Why not [register an account](%%action.register%%) and be the first to post!" +msgstr "" + +#: actions/public.php:245 actions/public.php:238 +#, php-format +msgid "" +"This is %%site.name%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-" +"blogging) service based on the Free Software [StatusNet](http://status.net/) " +"tool." +msgstr "" + +#: actions/publictagcloud.php:69 +#, php-format +msgid "No one has posted a notice with a [hashtag](%%doc.tags%%) yet." +msgstr "" + +#: actions/publictagcloud.php:72 +msgid "Be the first to post one!" +msgstr "" + +#: actions/publictagcloud.php:75 +#, php-format +msgid "" +"Why not [register an account](%%action.register%%) and be the first to post " +"one!" +msgstr "" + +#: actions/recoverpassword.php:152 +msgid "" +"If you've forgotten or lost your password, you can get a new one sent to the " +"email address you have stored in your account." +msgstr "" + +#: actions/recoverpassword.php:158 +msgid "You've been identified. Enter a new password below. " +msgstr "" + +#: actions/recoverpassword.php:188 +msgid "Password recover" +msgstr "" + +#: actions/register.php:86 actions/register.php:92 +msgid "Sorry, invalid invitation code." +msgstr "" + +#: actions/remotesubscribe.php:100 actions/remotesubscribe.php:124 +msgid "Subscribe to a remote user" +msgstr "" + +#: actions/replies.php:179 actions/replies.php:198 +#, php-format +msgid "" +"This is the timeline showing replies to %s but %s hasn't received a notice " +"to his attention yet." +msgstr "" + +#: actions/replies.php:184 actions/replies.php:203 +#, php-format +msgid "" +"You can engage other users in a conversation, subscribe to more people or " +"[join groups](%%action.groups%%)." +msgstr "" + +#: actions/replies.php:186 actions/replies.php:205 +#, php-format +msgid "" +"You can try to [nudge %s](../%s) or [post something to his or her attention]" +"(%%%%action.newnotice%%%%?status_textarea=%s)." +msgstr "" + +#: actions/showfavorites.php:79 +#, php-format +msgid "%s's favorite notices, page %d" +msgstr "" + +#: actions/showfavorites.php:170 actions/showfavorites.php:205 +msgid "" +"You haven't chosen any favorite notices yet. Click the fave button on " +"notices you like to bookmark them for later or shed a spotlight on them." +msgstr "" + +#: actions/showfavorites.php:172 actions/showfavorites.php:207 +#, php-format +msgid "" +"%s hasn't added any notices to his favorites yet. Post something interesting " +"they would add to their favorites :)" +msgstr "" + +#: actions/showfavorites.php:176 +#, php-format +msgid "" +"%s hasn't added any notices to his favorites yet. Why not [register an " +"account](%%%%action.register%%%%) and then post something interesting they " +"would add to thier favorites :)" +msgstr "" + +#: actions/showfavorites.php:226 actions/showfavorites.php:242 +msgid "This is a way to share what you like." +msgstr "" + +#: actions/showgroup.php:279 lib/groupeditform.php:178 +#: actions/showgroup.php:284 lib/groupeditform.php:184 +msgid "Aliases" +msgstr "" + +#: actions/showgroup.php:323 actions/showgroup.php:328 +#, php-format +msgid "Notice feed for %s group (RSS 1.0)" +msgstr "" + +#: actions/showgroup.php:330 actions/tag.php:84 actions/showgroup.php:334 +#, php-format +msgid "Notice feed for %s group (RSS 2.0)" +msgstr "" + +#: actions/showgroup.php:337 actions/showgroup.php:340 +#, php-format +msgid "Notice feed for %s group (Atom)" +msgstr "" + +#: actions/showgroup.php:446 actions/showgroup.php:454 +#, php-format +msgid "" +"**%s** is a user group on %%%%site.name%%%%, a [micro-blogging](http://en." +"wikipedia.org/wiki/Micro-blogging) service based on the Free Software " +"[StatusNet](http://status.net/) tool. Its members share short messages about " +"their life and interests. " +msgstr "" + +#: actions/showgroup.php:474 actions/showgroup.php:482 +msgid "Admins" +msgstr "" + +#: actions/shownotice.php:101 +msgid "Not a local notice" +msgstr "" + +#: actions/showstream.php:72 actions/showstream.php:73 +#, php-format +msgid " tagged %s" +msgstr "" + +#: actions/showstream.php:121 actions/showstream.php:122 +#, php-format +msgid "Notice feed for %s tagged %s (RSS 1.0)" +msgstr "" + +#: actions/showstream.php:350 actions/showstream.php:444 +#: actions/showstream.php:191 +#, php-format +msgid "This is the timeline for %s but %s hasn't posted anything yet." +msgstr "" + +#: actions/showstream.php:355 actions/showstream.php:449 +#: actions/showstream.php:196 +msgid "" +"Seen anything interesting recently? You haven't posted any notices yet, now " +"would be a good time to start :)" +msgstr "" + +#: actions/showstream.php:357 actions/showstream.php:451 +#: actions/showstream.php:198 +#, php-format +msgid "" +"You can try to nudge %s or [post something to his or her attention](%%%%" +"action.newnotice%%%%?status_textarea=%s)." +msgstr "" + +#: actions/showstream.php:393 actions/showstream.php:492 +#: actions/showstream.php:239 +#, php-format +msgid "" +"**%s** has an account on %%%%site.name%%%%, a [micro-blogging](http://en." +"wikipedia.org/wiki/Micro-blogging) service based on the Free Software " +"[StatusNet](http://status.net/) tool. " +msgstr "" + +#: actions/subscribers.php:108 +msgid "" +"You have no subscribers. Try subscribing to people you know and they might " +"return the favor" +msgstr "" + +#: actions/subscribers.php:110 +#, php-format +msgid "%s has no subscribers. Want to be the first?" +msgstr "" + +#: actions/subscribers.php:114 +#, php-format +msgid "" +"%s has no subscribers. Why not [register an account](%%%%action.register%%%" +"%) and be the first?" +msgstr "" + +#: actions/subscriptions.php:115 actions/subscriptions.php:121 +#, php-format +msgid "" +"You're not listening to anyone's notices right now, try subscribing to " +"people you know. Try [people search](%%action.peoplesearch%%), look for " +"members in groups you're interested in and in our [featured users](%%action." +"featured%%). If you're a [Twitter user](%%action.twittersettings%%), you can " +"automatically subscribe to people you already follow there." +msgstr "" + +#: actions/subscriptions.php:117 actions/subscriptions.php:121 +#: actions/subscriptions.php:123 actions/subscriptions.php:127 +#, php-format +msgid "%s is not listening to anyone." +msgstr "" + +#: actions/tag.php:77 actions/tag.php:86 +#, php-format +msgid "Notice feed for tag %s (RSS 1.0)" +msgstr "" + +#: actions/tag.php:91 actions/tag.php:98 +#, php-format +msgid "Notice feed for tag %s (Atom)" +msgstr "" + +#: actions/twitapifavorites.php:125 actions/apifavoritecreate.php:119 +msgid "This status is already a favorite!" +msgstr "" + +#: actions/twitapifavorites.php:179 actions/apifavoritedestroy.php:122 +msgid "That status is not a favorite!" +msgstr "" + +#: actions/twitapifriendships.php:180 actions/twitapifriendships.php:200 +#: actions/apifriendshipsshow.php:135 +msgid "Could not determine source user." +msgstr "" + +#: actions/twitapifriendships.php:215 +msgid "Target user not specified." +msgstr "" + +#: actions/twitapifriendships.php:221 actions/apifriendshipsshow.php:143 +msgid "Could not find target user." +msgstr "" + +#: actions/twitapistatuses.php:322 actions/apitimelinementions.php:116 +#, php-format +msgid "%1$s / Updates mentioning %2$s" +msgstr "" + +#: actions/twitapitags.php:74 actions/apitimelinetag.php:107 +#: actions/tagrss.php:64 +#, php-format +msgid "Updates tagged with %1$s on %2$s!" +msgstr "" + +#: actions/twittersettings.php:165 +msgid "Import my Friends Timeline." +msgstr "" + +#: actions/userauthorization.php:158 actions/userauthorization.php:188 +msgid "License" +msgstr "" + +#: actions/userauthorization.php:179 actions/userauthorization.php:212 +msgid "Reject this subscription" +msgstr "" + +#: actions/userdesignsettings.php:76 lib/designsettings.php:65 +msgid "Profile design" +msgstr "" + +#: actions/userdesignsettings.php:87 lib/designsettings.php:76 +msgid "" +"Customize the way your profile looks with a background image and a colour " +"palette of your choice." +msgstr "" + +#: actions/userdesignsettings.php:282 +msgid "Enjoy your hotdog!" +msgstr "" + +#: actions/usergroups.php:153 +#, php-format +msgid "%s is not a member of any group." +msgstr "" + +#: actions/usergroups.php:158 +#, php-format +msgid "Try [searching for groups](%%action.groupsearch%%) and joining them." +msgstr "" + +#: classes/File.php:127 classes/File.php:137 +#, php-format +msgid "" +"No file may be larger than %d bytes and the file you sent was %d bytes. Try " +"to upload a smaller version." +msgstr "" + +#: classes/File.php:137 classes/File.php:147 +#, php-format +msgid "A file this large would exceed your user quota of %d bytes." +msgstr "" + +#: classes/File.php:145 classes/File.php:154 +#, php-format +msgid "A file this large would exceed your monthly quota of %d bytes." +msgstr "" + +#: classes/Notice.php:139 classes/Notice.php:179 +msgid "Problem saving notice. Too long." +msgstr "" + +#: classes/User.php:319 classes/User.php:327 classes/User.php:334 +#: classes/User.php:333 +#, php-format +msgid "Welcome to %1$s, @%2$s!" +msgstr "" + +#: lib/accountsettingsaction.php:119 lib/groupnav.php:118 +#: lib/accountsettingsaction.php:120 +msgid "Design" +msgstr "" + +#: lib/accountsettingsaction.php:120 lib/accountsettingsaction.php:121 +msgid "Design your profile" +msgstr "" + +#: lib/action.php:712 lib/action.php:727 +msgid "TOS" +msgstr "" + +#: lib/attachmentlist.php:87 +msgid "Attachments" +msgstr "" + +#: lib/attachmentlist.php:265 +msgid "Author" +msgstr "" + +#: lib/attachmentlist.php:278 +msgid "Provider" +msgstr "" + +#: lib/attachmentnoticesection.php:67 +msgid "Notices where this attachment appears" +msgstr "" + +#: lib/attachmenttagcloudsection.php:48 +msgid "Tags for this attachment" +msgstr "" + +#: lib/designsettings.php:101 +msgid "Change background image" +msgstr "" + +#: lib/designsettings.php:105 +msgid "Upload file" +msgstr "" + +#: lib/designsettings.php:109 +msgid "" +"You can upload your personal background image. The maximum file size is 2Mb." +msgstr "" + +#: lib/designsettings.php:139 +msgid "On" +msgstr "" + +#: lib/designsettings.php:155 +msgid "Off" +msgstr "" + +#: lib/designsettings.php:156 +msgid "Turn background image on or off." +msgstr "" + +#: lib/designsettings.php:161 +msgid "Tile background image" +msgstr "" + +#: lib/designsettings.php:170 +msgid "Change colours" +msgstr "" + +#: lib/designsettings.php:178 +msgid "Background" +msgstr "" + +#: lib/designsettings.php:191 +msgid "Content" +msgstr "" + +#: lib/designsettings.php:204 +msgid "Sidebar" +msgstr "" + +#: lib/designsettings.php:230 +msgid "Links" +msgstr "" + +#: lib/designsettings.php:247 +msgid "Use defaults" +msgstr "" + +#: lib/designsettings.php:248 +msgid "Restore default designs" +msgstr "" + +#: lib/designsettings.php:254 +msgid "Reset back to default" +msgstr "" + +#: lib/designsettings.php:257 +msgid "Save design" +msgstr "" + +#: lib/designsettings.php:378 lib/designsettings.php:369 +#: lib/designsettings.php:372 +msgid "Bad default color settings: " +msgstr "" + +#: lib/designsettings.php:474 lib/designsettings.php:465 +#: lib/designsettings.php:468 +msgid "Design defaults restored." +msgstr "" + +#: lib/groupeditform.php:181 lib/groupeditform.php:187 +#, php-format +msgid "Extra nicknames for the group, comma- or space- separated, max %d" +msgstr "" + +#: lib/groupnav.php:100 +msgid "Blocked" +msgstr "" + +#: lib/groupnav.php:101 +#, php-format +msgid "%s blocked users" +msgstr "" + +#: lib/groupnav.php:119 +#, php-format +msgid "Add or edit %s design" +msgstr "" + +#: lib/mail.php:556 +#, php-format +msgid "" +"%1$s just added your notice from %2$s as one of their favorites.\n" +"\n" +"The URL of your notice is:\n" +"\n" +"%3$s\n" +"\n" +"The text of your notice is:\n" +"\n" +"%4$s\n" +"\n" +"You can see the list of %1$s's favorites here:\n" +"\n" +"%5$s\n" +"\n" +"Faithfully yours,\n" +"%6$s\n" +msgstr "" + +#: lib/mail.php:646 +#, php-format +msgid "Your Twitter bridge has been disabled." +msgstr "" + +#: lib/mail.php:648 +#, php-format +msgid "" +"Hi, %1$s. We're sorry to inform you that your link to Twitter has been " +"disabled. Your Twitter credentials have either changed (did you recently " +"change your Twitter password?) or you have otherwise revoked our access to " +"your Twitter account.\n" +"\n" +"You can re-enable your Twitter bridge by visiting your Twitter settings " +"page:\n" +"\n" +"\t%2$s\n" +"\n" +"Regards,\n" +"%3$s\n" +msgstr "" + +#: lib/mail.php:682 +#, php-format +msgid "Your %s Facebook application access has been disabled." +msgstr "" + +#: lib/mail.php:685 +#, php-format +msgid "" +"Hi, %1$s. We're sorry to inform you that we are unable to update your " +"Facebook status from %s, and have disabled the Facebook application for your " +"account. This may be because you have removed the Facebook application's " +"authorization, or have deleted your Facebook account. You can re-enable the " +"Facebook application and automatic status updating by re-installing the %1$s " +"Facebook application.\n" +"\n" +"Regards,\n" +"\n" +"%1$s" +msgstr "" + +#: lib/mailbox.php:139 +msgid "" +"You have no private messages. You can send private message to engage other " +"users in conversation. People can send you messages for your eyes only." +msgstr "" + +#: lib/noticeform.php:154 lib/noticeform.php:180 +msgid "Attach" +msgstr "" + +#: lib/noticeform.php:158 lib/noticeform.php:184 +msgid "Attach a file" +msgstr "" + +#: lib/noticelist.php:436 lib/noticelist.php:478 +msgid "in context" +msgstr "" + +#: lib/profileaction.php:177 +msgid "User ID" +msgstr "" + +#: lib/searchaction.php:156 lib/searchaction.php:162 +msgid "Search help" +msgstr "" + +#: lib/subscriberspeopleselftagcloudsection.php:48 +#: lib/subscriptionspeopleselftagcloudsection.php:48 +msgid "People Tagcloud as self-tagged" +msgstr "" + +#: lib/subscriberspeopletagcloudsection.php:48 +#: lib/subscriptionspeopletagcloudsection.php:48 +msgid "People Tagcloud as tagged" +msgstr "" + +#: lib/webcolor.php:82 +#, php-format +msgid "%s is not a valid color!" +msgstr "" + +#: lib/webcolor.php:123 +#, php-format +msgid "%s is not a valid color! Use 3 or 6 hex chars." +msgstr "" + +#: actions/all.php:63 actions/public.php:97 actions/replies.php:92 +#: actions/showfavorites.php:137 actions/tag.php:51 +msgid "No such page" +msgstr "" + +#: actions/apidirectmessage.php:89 +#, php-format +msgid "Direct messages from %s" +msgstr "" + +#: actions/apidirectmessagenew.php:135 actions/newmessage.php:150 +#, php-format +msgid "That's too long. Max message size is %d chars." +msgstr "" + +#: actions/apifriendshipsdestroy.php:109 +msgid "Could not unfollow user: User not found." +msgstr "" + +#: actions/apifriendshipsdestroy.php:120 +msgid "You cannot unfollow yourself!" +msgstr "" + +#: actions/apigroupcreate.php:261 +#, php-format +msgid "Description is too long (max %d chars)." +msgstr "" + +#: actions/apigroupjoin.php:110 +msgid "You are already a member of that group." +msgstr "" + +#: actions/apigroupjoin.php:138 +#, php-format +msgid "Could not join user %s to group %s." +msgstr "" + +#: actions/apigroupleave.php:114 +msgid "You are not a member of this group." +msgstr "" + +#: actions/apigroupleave.php:124 +#, php-format +msgid "Could not remove user %s to group %s." +msgstr "" + +#: actions/apigrouplist.php:95 +#, php-format +msgid "%s's groups" +msgstr "" + +#: actions/apigrouplist.php:103 +#, php-format +msgid "Groups %s is a member of on %s." +msgstr "" + +#: actions/apigrouplistall.php:94 +#, php-format +msgid "groups on %s" +msgstr "" + +#: actions/apistatusesshow.php:138 +msgid "Status deleted." +msgstr "" + +#: actions/apistatusesupdate.php:132 +#: actions/apiaccountupdateprofileimage.php:99 +msgid "Unable to handle that much POST data!" +msgstr "" + +#: actions/apistatusesupdate.php:145 actions/newnotice.php:155 +#: scripts/maildaemon.php:71 actions/apistatusesupdate.php:152 +#, php-format +msgid "That's too long. Max notice size is %d chars." +msgstr "" + +#: actions/apistatusesupdate.php:209 actions/newnotice.php:178 +#: actions/apistatusesupdate.php:216 +#, php-format +msgid "Max notice size is %d chars, including attachment URL." +msgstr "" + +#: actions/apisubscriptions.php:231 actions/apisubscriptions.php:261 +msgid "Unsupported format." +msgstr "" + +#: actions/bookmarklet.php:50 +msgid "Post to " +msgstr "" + +#: actions/editgroup.php:201 actions/newgroup.php:145 +#, php-format +msgid "description is too long (max %d chars)." +msgstr "" + +#: actions/favoritesrss.php:115 +#, php-format +msgid "Updates favored by %1$s on %2$s!" +msgstr "" + +#: actions/finishremotesubscribe.php:80 +msgid "User being listened to does not exist." +msgstr "" + +#: actions/finishremotesubscribe.php:106 +msgid "You are not authorized." +msgstr "" + +#: actions/finishremotesubscribe.php:109 +msgid "Could not convert request token to access token." +msgstr "" + +#: actions/finishremotesubscribe.php:114 +msgid "Remote service uses unknown version of OMB protocol." +msgstr "" + +#: actions/getfile.php:75 +msgid "No such file." +msgstr "" + +#: actions/getfile.php:79 +msgid "Cannot read file." +msgstr "" + +#: actions/grouprss.php:133 +#, php-format +msgid "Updates from members of %1$s on %2$s!" +msgstr "" + +#: actions/imsettings.php:89 +msgid "IM is not available." +msgstr "" + +#: actions/login.php:259 actions/login.php:286 +#, php-format +msgid "" +"Login with your username and password. Don't have a username yet? [Register]" +"(%%action.register%%) a new account." +msgstr "" + +#: actions/noticesearchrss.php:89 +#, php-format +msgid "Updates with \"%s\"" +msgstr "" + +#: actions/noticesearchrss.php:91 +#, php-format +msgid "Updates matching search term \"%1$s\" on %2$s!" +msgstr "" + +#: actions/oembed.php:157 +msgid "content type " +msgstr "" + +#: actions/oembed.php:160 +msgid "Only " +msgstr "" + +#: actions/postnotice.php:90 +#, php-format +msgid "Notice license ‘%s’ is not compatible with site license ‘%s’." +msgstr "" + +#: actions/profilesettings.php:122 actions/register.php:454 +#: actions/register.php:460 +#, php-format +msgid "Describe yourself and your interests in %d chars" +msgstr "" + +#: actions/profilesettings.php:125 actions/register.php:457 +#: actions/register.php:463 +msgid "Describe yourself and your interests" +msgstr "" + +#: actions/profilesettings.php:221 actions/register.php:217 +#: actions/register.php:223 +#, php-format +msgid "Bio is too long (max %d chars)." +msgstr "" + +#: actions/register.php:336 actions/register.php:342 +msgid "" +"With this form you can create a new account. You can then post notices and " +"link up to friends and colleagues. " +msgstr "" + +#: actions/remotesubscribe.php:168 +msgid "" +"Not a valid profile URL (no YADIS document or no or invalid XRDS defined)." +msgstr "" + +#: actions/remotesubscribe.php:176 +msgid "That’s a local profile! Login to subscribe." +msgstr "" + +#: actions/remotesubscribe.php:183 +msgid "Couldn’t get a request token." +msgstr "" + +#: actions/replies.php:144 +#, php-format +msgid "Replies feed for %s (RSS 1.0)" +msgstr "" + +#: actions/replies.php:151 +#, php-format +msgid "Replies feed for %s (RSS 2.0)" +msgstr "" + +#: actions/replies.php:158 +#, php-format +msgid "Replies feed for %s (Atom)" +msgstr "" + +#: actions/repliesrss.php:72 +#, php-format +msgid "Replies to %1$s on %2$s!" +msgstr "" + +#: actions/showfavorites.php:170 +#, php-format +msgid "Feed for favorites of %s (RSS 1.0)" +msgstr "" + +#: actions/showfavorites.php:177 +#, php-format +msgid "Feed for favorites of %s (RSS 2.0)" +msgstr "" + +#: actions/showfavorites.php:184 +#, php-format +msgid "Feed for favorites of %s (Atom)" +msgstr "" + +#: actions/showfavorites.php:211 +#, php-format +msgid "" +"%s hasn't added any notices to his favorites yet. Why not [register an " +"account](%%%%action.register%%%%) and then post something interesting they " +"would add to their favorites :)" +msgstr "" + +#: actions/showgroup.php:345 +#, php-format +msgid "FOAF for %s group" +msgstr "" + +#: actions/shownotice.php:90 +msgid "Notice deleted." +msgstr "" + +#: actions/smssettings.php:91 +msgid "SMS is not available." +msgstr "" + +#: actions/tag.php:92 +#, php-format +msgid "Notice feed for tag %s (RSS 2.0)" +msgstr "" + +#: actions/updateprofile.php:62 actions/userauthorization.php:330 +#, php-format +msgid "Listenee stream license ‘%s’ is not compatible with site license ‘%s’." +msgstr "" + +#: actions/userauthorization.php:110 +msgid "" +"Please check these details to make sure that you want to subscribe to this " +"user’s notices. If you didn’t just ask to subscribe to someone’s notices, " +"click “Reject”." +msgstr "" + +#: actions/userauthorization.php:249 +msgid "" +"The subscription has been authorized, but no callback URL was passed. Check " +"with the site’s instructions for details on how to authorize the " +"subscription. Your subscription token is:" +msgstr "" + +#: actions/userauthorization.php:261 +msgid "" +"The subscription has been rejected, but no callback URL was passed. Check " +"with the site’s instructions for details on how to fully reject the " +"subscription." +msgstr "" + +#: actions/userauthorization.php:296 +#, php-format +msgid "Listener URI ‘%s’ not found here" +msgstr "" + +#: actions/userauthorization.php:301 +#, php-format +msgid "Listenee URI ‘%s’ is too long." +msgstr "" + +#: actions/userauthorization.php:307 +#, php-format +msgid "Listenee URI ‘%s’ is a local user." +msgstr "" + +#: actions/userauthorization.php:322 +#, php-format +msgid "Profile URL ‘%s’ is for a local user." +msgstr "" + +#: actions/userauthorization.php:338 +#, php-format +msgid "Avatar URL ‘%s’ is not valid." +msgstr "" + +#: actions/userauthorization.php:343 +#, php-format +msgid "Can’t read avatar URL ‘%s’." +msgstr "" + +#: actions/userauthorization.php:348 +#, php-format +msgid "Wrong image type for avatar URL ‘%s’." +msgstr "" + +#: lib/action.php:435 +msgid "Connect to services" +msgstr "" + +#: lib/action.php:785 +msgid "Site content license" +msgstr "" + +#: lib/command.php:88 +#, php-format +msgid "Could not find a user with nickname %s" +msgstr "" + +#: lib/command.php:92 +msgid "It does not make a lot of sense to nudge yourself!" +msgstr "" + +#: lib/command.php:99 +#, php-format +msgid "Nudge sent to %s" +msgstr "" + +#: lib/command.php:152 lib/command.php:400 +msgid "Notice with that id does not exist" +msgstr "" + +#: lib/command.php:358 scripts/xmppdaemon.php:321 +#, php-format +msgid "Message too long - maximum is %d characters, you sent %d" +msgstr "" + +#: lib/command.php:431 +#, php-format +msgid "Notice too long - maximum is %d characters, you sent %d" +msgstr "" + +#: lib/command.php:439 +#, php-format +msgid "Reply to %s sent" +msgstr "" + +#: lib/command.php:441 +msgid "Error saving notice." +msgstr "" + +#: lib/common.php:191 +msgid "No configuration file found. " +msgstr "" + +#: lib/common.php:192 +msgid "I looked for configuration files in the following places: " +msgstr "" + +#: lib/common.php:193 +msgid "You may wish to run the installer to fix this." +msgstr "" + +#: lib/common.php:194 +msgid "Go to the installer." +msgstr "" + +#: lib/galleryaction.php:139 +msgid "Select tag to filter" +msgstr "" + +#: lib/groupeditform.php:168 +msgid "Describe the group or topic" +msgstr "" + +#: lib/groupeditform.php:170 +#, php-format +msgid "Describe the group or topic in %d characters" +msgstr "" + +#: lib/jabber.php:192 +#, php-format +msgid "notice id: %s" +msgstr "" + +#: lib/mail.php:554 +#, php-format +msgid "%s (@%s) added your notice as a favorite" +msgstr "" + +#: lib/mail.php:556 +#, php-format +msgid "" +"%1$s (@%7$s) just added your notice from %2$s as one of their favorites.\n" +"\n" +"The URL of your notice is:\n" +"\n" +"%3$s\n" +"\n" +"The text of your notice is:\n" +"\n" +"%4$s\n" +"\n" +"You can see the list of %1$s's favorites here:\n" +"\n" +"%5$s\n" +"\n" +"Faithfully yours,\n" +"%6$s\n" +msgstr "" + +#: lib/mail.php:611 +#, php-format +msgid "%s (@%s) sent a notice to your attention" +msgstr "" + +#: lib/mail.php:613 +#, php-format +msgid "" +"%1$s (@%9$s) just sent a notice to your attention (an '@-reply') on %2$s.\n" +"\n" +"The notice is here:\n" +"\n" +"\t%3$s\n" +"\n" +"It reads:\n" +"\n" +"\t%4$s\n" +"\n" +msgstr "" + +#: lib/mailbox.php:227 lib/noticelist.php:424 +msgid "from" +msgstr "" + +#: lib/mediafile.php:179 lib/mediafile.php:216 +msgid "File exceeds user's quota!" +msgstr "" + +#: lib/mediafile.php:201 lib/mediafile.php:237 +msgid "Could not determine file's mime-type!" +msgstr "" + +#: lib/oauthstore.php:345 +msgid "Duplicate notice" +msgstr "" + +#: actions/login.php:110 actions/login.php:120 +msgid "Invalid or expired token." +msgstr "" + +#: lib/command.php:597 +#, php-format +msgid "Could not create login token for %s" +msgstr "" + +#: lib/command.php:602 +#, php-format +msgid "This link is useable only once, and is good for only 2 minutes: %s" +msgstr "" + +#: lib/imagefile.php:75 +#, php-format +msgid "That file is too big. The maximum file size is %s." +msgstr "" + +#: lib/command.php:613 +msgid "" +"Commands:\n" +"on - turn on notifications\n" +"off - turn off notifications\n" +"help - show this help\n" +"follow - subscribe to user\n" +"leave - unsubscribe from user\n" +"d - direct message to user\n" +"get - get last notice from user\n" +"whois - get profile info on user\n" +"fav - add user's last notice as a 'fave'\n" +"fav # - add notice with the given id as a 'fave'\n" +"reply # - reply to notice with a given id\n" +"reply - reply to the last notice from user\n" +"join - join group\n" +"login - Get a link to login to the web interface\n" +"drop - leave group\n" +"stats - get your stats\n" +"stop - same as 'off'\n" +"quit - same as 'off'\n" +"sub - same as 'follow'\n" +"unsub - same as 'leave'\n" +"last - same as 'get'\n" +"on - not yet implemented.\n" +"off - not yet implemented.\n" +"nudge - remind a user to update.\n" +"invite - not yet implemented.\n" +"track - not yet implemented.\n" +"untrack - not yet implemented.\n" +"track off - not yet implemented.\n" +"untrack all - not yet implemented.\n" +"tracks - not yet implemented.\n" +"tracking - not yet implemented.\n" msgstr "" diff --git a/plugins/Facebook/facebook/facebookapi_php5_restlib.php b/plugins/Facebook/facebook/facebookapi_php5_restlib.php index e2a6fe88b..55cb7fb86 100755 --- a/plugins/Facebook/facebook/facebookapi_php5_restlib.php +++ b/plugins/Facebook/facebook/facebookapi_php5_restlib.php @@ -2951,7 +2951,7 @@ function toggleDisplay(id, type) { /** - * Bans a list of users from the app. Banned users cannot + * Bans a list of users from the app. Banned users can't * access the app's canvas page and forums. * * @param array $uids an array of user ids diff --git a/plugins/Facebook/facebook/jsonwrapper/JSON/JSON.php b/plugins/Facebook/facebook/jsonwrapper/JSON/JSON.php index 92542b47d..0cddbddb4 100644 --- a/plugins/Facebook/facebook/jsonwrapper/JSON/JSON.php +++ b/plugins/Facebook/facebook/jsonwrapper/JSON/JSON.php @@ -124,7 +124,7 @@ class Services_JSON * "{...}" syntax creates associative arrays * instead of objects in decode(). * - SERVICES_JSON_SUPPRESS_ERRORS: error suppression. - * Values which cannot be encoded (e.g. resources) + * Values which can't be encoded (e.g. resources) * appear as NULL instead of throwing errors. * By default, a deeply-nested resource will * bubble up with an error, so all return values diff --git a/plugins/Facebook/facebookaction.php b/plugins/Facebook/facebookaction.php index 1d8b5217b..a10fdf90d 100644 --- a/plugins/Facebook/facebookaction.php +++ b/plugins/Facebook/facebookaction.php @@ -513,7 +513,7 @@ class FacebookNoticeList extends NoticeList /** * show the list of notices * - * "Uses up" the stream by looping through it. So, probably cannot + * "Uses up" the stream by looping through it. So, probably can't * be called twice on the same list. * * @return int count of notices listed. diff --git a/plugins/Facebook/facebookhome.php b/plugins/Facebook/facebookhome.php index ee6e6620b..91c0cc6b8 100644 --- a/plugins/Facebook/facebookhome.php +++ b/plugins/Facebook/facebookhome.php @@ -108,7 +108,7 @@ class FacebookhomeAction extends FacebookAction $user = User::staticGet('nickname', $nickname); if (!$user) { - $this->showLoginForm(_("Server error. Could not get user.")); + $this->showLoginForm(_("Server error - couldn't get user!")); } $flink = DB_DataObject::factory('foreign_link'); diff --git a/plugins/LinkbackPlugin.php b/plugins/LinkbackPlugin.php index bc433b896..915d15c07 100644 --- a/plugins/LinkbackPlugin.php +++ b/plugins/LinkbackPlugin.php @@ -125,7 +125,7 @@ class LinkbackPlugin extends Plugin if (!extension_loaded('xmlrpc')) { if (!dl('xmlrpc.so')) { - common_log(LOG_ERR, "Cannot pingback; xmlrpc extension not available."); + common_log(LOG_ERR, "Can't pingback; xmlrpc extension not available."); } } diff --git a/plugins/Meteor/MeteorPlugin.php b/plugins/Meteor/MeteorPlugin.php index f3cbc3eea..5b345d7c2 100644 --- a/plugins/Meteor/MeteorPlugin.php +++ b/plugins/Meteor/MeteorPlugin.php @@ -85,7 +85,7 @@ class MeteorPlugin extends RealtimePlugin // May throw an exception. $this->_socket = stream_socket_client("tcp://{$controlserver}:{$this->controlport}"); if (!$this->_socket) { - throw new Exception("Could not connect to {$controlserver} on {$this->controlport}"); + throw new Exception("Couldn't connect to {$controlserver} on {$this->controlport}"); } } diff --git a/plugins/OpenID/openid.php b/plugins/OpenID/openid.php index cd042226b..ff7a93899 100644 --- a/plugins/OpenID/openid.php +++ b/plugins/OpenID/openid.php @@ -36,7 +36,7 @@ function oid_store() { static $store = null; if (!$store) { - # Cannot be called statically + # Can't be called statically $user = new User(); $conn = $user->getDatabaseConnection(); $store = new Auth_OpenID_MySQLStore($conn); @@ -192,7 +192,7 @@ function oid_authenticate($openid_url, $returnto, $immediate=false) $form_html = preg_replace('/&/', '&', $form_html); - // Display an error if the form markup could not be generated; + // Display an error if the form markup couldn't be generated; // otherwise, render the HTML. if (Auth_OpenID::isFailure($form_html)) { common_server_error(sprintf(_('Could not create OpenID form: %s'), $form_html->message)); diff --git a/plugins/TwitterBridge/daemons/synctwitterfriends.php b/plugins/TwitterBridge/daemons/synctwitterfriends.php index 6a155b301..671e3c7af 100755 --- a/plugins/TwitterBridge/daemons/synctwitterfriends.php +++ b/plugins/TwitterBridge/daemons/synctwitterfriends.php @@ -126,7 +126,7 @@ class SyncTwitterFriendsDaemon extends ParallelizingDaemon $conn->disconnect(); - // XXX: Could not find a less brutal way to blow + // XXX: Couldn't find a less brutal way to blow // away a cached connection global $_DB_DATAOBJECT; @@ -188,7 +188,7 @@ class SyncTwitterFriendsDaemon extends ParallelizingDaemon if (empty($more_friends)) { common_log(LOG_WARNING, $this->name() . - " - Could not retrieve page $i " . + " - Couldn't retrieve page $i " . "of Twitter user $flink->foreign_id friends."); continue; } else { @@ -222,11 +222,11 @@ class SyncTwitterFriendsDaemon extends ParallelizingDaemon if (!save_twitter_user($friend_id, $friend_name)) { common_log(LOG_WARNING, $this-name() . - " - Could not save $screen_name's friend, $friend_name."); + " - Couldn't save $screen_name's friend, $friend_name."); continue; } - // Check to see if there is a related local user + // Check to see if there's a related local user $friend_flink = Foreign_link::getByForeignID($friend_id, TWITTER_SERVICE); diff --git a/plugins/TwitterBridge/daemons/twitterstatusfetcher.php b/plugins/TwitterBridge/daemons/twitterstatusfetcher.php index ab610e553..b5428316b 100755 --- a/plugins/TwitterBridge/daemons/twitterstatusfetcher.php +++ b/plugins/TwitterBridge/daemons/twitterstatusfetcher.php @@ -147,7 +147,7 @@ class TwitterStatusFetcher extends ParallelizingDaemon $conn->disconnect(); - // XXX: Could not find a less brutal way to blow + // XXX: Couldn't find a less brutal way to blow // away a cached connection global $_DB_DATAOBJECT; @@ -158,7 +158,7 @@ class TwitterStatusFetcher extends ParallelizingDaemon { if (empty($flink)) { common_log(LOG_WARNING, $this->name() . - " - Cannot retrieve Foreign_link for foreign ID $fid"); + " - Can't retrieve Foreign_link for foreign ID $fid"); return; } @@ -458,7 +458,7 @@ class TwitterStatusFetcher extends ParallelizingDaemon $profile = Profile::staticGet($profile_id); if (empty($profile)) { - common_debug($this->name() . " - Could not get profile: $profile_id!"); + common_debug($this->name() . " - Couldn't get profile: $profile_id!"); return; } @@ -537,7 +537,7 @@ class TwitterStatusFetcher extends ParallelizingDaemon $ok = file_put_contents($avatarfile, $response->getBody()); if (!$ok) { common_log(LOG_WARNING, $this->name() . - " - Could not open file $filename"); + " - Couldn't open file $filename"); return false; } } else { diff --git a/plugins/UserFlag/flagprofile.php b/plugins/UserFlag/flagprofile.php index 84c343c48..c72b74c6a 100644 --- a/plugins/UserFlag/flagprofile.php +++ b/plugins/UserFlag/flagprofile.php @@ -135,7 +135,7 @@ class FlagprofileAction extends Action $ufp->created = common_sql_now(); if (!$ufp->insert()) { - throw new ServerException(sprintf(_("Could not flag profile '%s' with flag '%s'."), + throw new ServerException(sprintf(_("Couldn't flag profile '%s' with flag '%s'."), $this->profile->nickname, $this->flag)); } diff --git a/scripts/console.php b/scripts/console.php index 2413f5079..41dd43f28 100755 --- a/scripts/console.php +++ b/scripts/console.php @@ -90,7 +90,7 @@ function readline_emulation($prompt) if ($retval == 0) { return $line; } elseif ($retval == 127) { - // Could not execute bash even though we thought we saw it. + // Couldn't execute bash even though we thought we saw it. // Shell probably spit out an error message, sorry :( // Fall through to fgets()... } else { diff --git a/scripts/createsim.php b/scripts/createsim.php index 592853f86..1266a9700 100644 --- a/scripts/createsim.php +++ b/scripts/createsim.php @@ -85,7 +85,7 @@ function newSub($i) $from = User::staticGet('nickname', $fromnick); if (empty($from)) { - throw new Exception("Cannot find user '$fromnick'."); + throw new Exception("Can't find user '$fromnick'."); } $t = rand(0, $i - 1); @@ -102,7 +102,7 @@ function newSub($i) $to = User::staticGet('nickname', $tunic); if (empty($to)) { - throw new Exception("Cannot find user '$tunic'."); + throw new Exception("Can't find user '$tunic'."); } subs_subscribe_to($from, $to); diff --git a/scripts/deleteuser.php b/scripts/deleteuser.php index 39331f1a8..52389123c 100644 --- a/scripts/deleteuser.php +++ b/scripts/deleteuser.php @@ -39,14 +39,14 @@ if (have_option('i', 'id')) { $id = get_option_value('i', 'id'); $user = User::staticGet('id', $id); if (empty($user)) { - print "Cannot find user with ID $id\n"; + print "Can't find user with ID $id\n"; exit(1); } } else if (have_option('n', 'nickname')) { $nickname = get_option_value('n', 'nickname'); $user = User::staticGet('nickname', $nickname); if (empty($user)) { - print "Cannot find user with nickname '$nickname'\n"; + print "Can't find user with nickname '$nickname'\n"; exit(1); } } else { diff --git a/scripts/fixup_utf8.php b/scripts/fixup_utf8.php index 5581633ec..5a9fba7c3 100755 --- a/scripts/fixup_utf8.php +++ b/scripts/fixup_utf8.php @@ -76,7 +76,7 @@ class UTF8FixerUpper $succ = mysqli_set_charset($conn, $charset); if (!$succ) { - echo "ERROR: Could not set charset\n"; + echo "ERROR: couldn't set charset\n"; $db->disconnect(); return NULL; } diff --git a/scripts/makegroupadmin.php b/scripts/makegroupadmin.php index 07f980d58..a68798451 100644 --- a/scripts/makegroupadmin.php +++ b/scripts/makegroupadmin.php @@ -67,7 +67,7 @@ try { $member->created = common_sql_now(); if (!$member->insert()) { - throw new Exception("Cannot add '$nickname' to '$groupname'."); + throw new Exception("Can't add '$nickname' to '$groupname'."); } } @@ -80,7 +80,7 @@ try { $member->is_admin = 1; if (!$member->update($orig)) { - throw new Exception("Cannot make '$nickname' admin of '$groupname'."); + throw new Exception("Can't make '$nickname' admin of '$groupname'."); } } catch (Exception $e) { diff --git a/scripts/registeruser.php b/scripts/registeruser.php index 8aab325b7..5d9c8862d 100644 --- a/scripts/registeruser.php +++ b/scripts/registeruser.php @@ -60,7 +60,7 @@ try { 'fullname' => $fullname)); if (empty($user)) { - throw new Exception("Cannot register user '$nickname' with password '$password' and fullname '$fullname'."); + throw new Exception("Can't register user '$nickname' with password '$password' and fullname '$fullname'."); } if (!empty($email)) { @@ -71,7 +71,7 @@ try { if (!$user->updateKeys($orig)) { print "Failed!\n"; - throw new Exception("Cannot update email address."); + throw new Exception("Can't update email address."); } } diff --git a/scripts/showcache.php b/scripts/showcache.php index 6b00a8f7b..f17979572 100644 --- a/scripts/showcache.php +++ b/scripts/showcache.php @@ -58,7 +58,7 @@ print "Checking key '$k'...\n"; $c = common_memcache(); if (empty($c)) { - die("Cannot initialize cache object!\n"); + die("Can't initialize cache object!\n"); } $obj = $c->get($k); diff --git a/scripts/sitemap.php b/scripts/sitemap.php index ee5d33e1e..f8c392146 100755 --- a/scripts/sitemap.php +++ b/scripts/sitemap.php @@ -377,11 +377,11 @@ function write_file($path, $data) } if (($fh_out = fopen($path,'w')) === false) { - error("Could not open $path for writing."); + error("couldn't open $path for writing."); } if (fwrite($fh_out, $data) === false) { - error("Could not write to $path."); + error("couldn't write to $path."); } } diff --git a/scripts/update_translations.php b/scripts/update_translations.php index 8d4c9d3d2..580c472ee 100755 --- a/scripts/update_translations.php +++ b/scripts/update_translations.php @@ -98,7 +98,7 @@ foreach ($languages as $language) { $new_file = curl_get_file($file_url); if ($new_file === FALSE) { - echo "Could not retrieve .po file for $code: $file_url\n"; + echo "Couldn't retrieve .po file for $code: $file_url\n"; continue; } -- cgit v1.2.3-54-g00ecf From 5ab709b73977131813884558bf56d97172a7aa26 Mon Sep 17 00:00:00 2001 From: Siebrand Mazeland Date: Sun, 8 Nov 2009 23:32:15 +0100 Subject: Remove more contractions * doesn't * won't * isn't * don't --- actions/allrss.php | 2 +- actions/apiaccountratelimitstatus.php | 2 +- actions/apifriendshipsdestroy.php | 2 +- actions/attachment.php | 4 ++-- actions/avatarbynickname.php | 2 +- actions/groupblock.php | 2 +- actions/login.php | 2 +- actions/logout.php | 2 +- actions/newmessage.php | 2 +- actions/newnotice.php | 2 +- actions/opensearch.php | 2 +- actions/passwordsettings.php | 2 +- actions/register.php | 2 +- actions/showgroup.php | 2 +- actions/showmessage.php | 8 ++++---- actions/shownotice.php | 6 +++--- actions/showstream.php | 2 +- actions/sup.php | 2 +- actions/twitapisearchatom.php | 2 +- actions/twitapitrends.php | 2 +- classes/File_redirection.php | 8 ++++---- classes/Notice.php | 6 +++--- classes/Profile.php | 4 ++-- classes/User.php | 6 +++--- lib/api.php | 14 +++++++------- lib/apiauth.php | 2 +- lib/dberroraction.php | 6 +++--- lib/error.php | 4 ++-- lib/htmloutputter.php | 2 +- lib/imagefile.php | 2 +- lib/jabber.php | 2 +- lib/mail.php | 6 +++--- lib/noticelist.php | 4 ++-- lib/queuehandler.php | 12 ++++++------ lib/rssaction.php | 2 +- lib/search_engines.php | 2 +- lib/util.php | 12 ++++++------ lib/xmloutputter.php | 2 +- lib/xmppqueuehandler.php | 2 +- plugins/Autocomplete/autocomplete.php | 2 +- plugins/BlogspamNetPlugin.php | 2 +- plugins/Facebook/FBConnectAuth.php | 4 ++-- plugins/Facebook/FacebookPlugin.php | 4 ++-- plugins/Facebook/facebook/facebook.php | 8 ++++---- plugins/Facebook/facebook/facebook_desktop.php | 2 +- plugins/Facebook/facebook/facebookapi_php5_restlib.php | 6 +++--- plugins/Facebook/facebook/jsonwrapper/jsonwrapper.php | 2 +- plugins/Facebook/facebookaction.php | 6 +++--- plugins/GeonamesPlugin.php | 8 ++++---- plugins/OpenID/finishopenidlogin.php | 4 ++-- plugins/OpenID/openid.php | 2 +- plugins/PiwikAnalyticsPlugin.php | 2 +- plugins/Realtime/RealtimePlugin.php | 2 +- plugins/TwitterBridge/daemons/synctwitterfriends.php | 2 +- plugins/TwitterBridge/daemons/twitterstatusfetcher.php | 4 ++-- plugins/TwitterBridge/twitter.php | 2 +- scripts/console.php | 4 ++-- scripts/maildaemon.php | 2 +- scripts/xmppconfirmhandler.php | 2 +- 59 files changed, 110 insertions(+), 110 deletions(-) (limited to 'plugins/TwitterBridge/daemons') diff --git a/actions/allrss.php b/actions/allrss.php index 28b1be27d..4a5d15c7b 100644 --- a/actions/allrss.php +++ b/actions/allrss.php @@ -56,7 +56,7 @@ class AllrssAction extends Rss10Action * * @param array $args Web and URL arguments * - * @return boolean false if user doesn't exist + * @return boolean false if user does not exist */ function prepare($args) { diff --git a/actions/apiaccountratelimitstatus.php b/actions/apiaccountratelimitstatus.php index 96179f175..c7c0e7c00 100644 --- a/actions/apiaccountratelimitstatus.php +++ b/actions/apiaccountratelimitstatus.php @@ -36,7 +36,7 @@ if (!defined('STATUSNET')) { require_once INSTALLDIR . '/lib/apibareauth.php'; /** - * We don't have a rate limit, but some clients check this method. + * We do not have a rate limit, but some clients check this method. * It always returns the same thing: 150 hits left. * * @category API diff --git a/actions/apifriendshipsdestroy.php b/actions/apifriendshipsdestroy.php index 3d9b7e001..fb73624c9 100644 --- a/actions/apifriendshipsdestroy.php +++ b/actions/apifriendshipsdestroy.php @@ -113,7 +113,7 @@ class ApiFriendshipsDestroyAction extends ApiAuthAction return; } - // Don't allow unsubscribing from yourself! + // Do not allow unsubscribing from yourself! if ($this->user->id == $this->other->id) { $this->clientError( diff --git a/actions/attachment.php b/actions/attachment.php index 6981354d1..ca9e57845 100644 --- a/actions/attachment.php +++ b/actions/attachment.php @@ -146,7 +146,7 @@ class AttachmentAction extends Action } /** - * Don't show local navigation + * Do not show local navigation * * @return void */ @@ -170,7 +170,7 @@ class AttachmentAction extends Action } /** - * Don't show page notice + * Do not show page notice * * @return void */ diff --git a/actions/avatarbynickname.php b/actions/avatarbynickname.php index 537950792..1a6925e11 100644 --- a/actions/avatarbynickname.php +++ b/actions/avatarbynickname.php @@ -49,7 +49,7 @@ class AvatarbynicknameAction extends Action * * @param array $args query arguments * - * @return boolean false if nickname or user isn't found + * @return boolean false if nickname or user is not found */ function handle($args) { diff --git a/actions/groupblock.php b/actions/groupblock.php index 979a56a81..133101eb7 100644 --- a/actions/groupblock.php +++ b/actions/groupblock.php @@ -95,7 +95,7 @@ class GroupblockAction extends Action $this->clientError(_('User is already blocked from group.')); return false; } - // XXX: could have proactive blocks, but we don't have UI for it. + // XXX: could have proactive blocks, but we do not have UI for it. if (!$this->profile->isMember($this->group)) { $this->clientError(_('User is not a member of group.')); return false; diff --git a/actions/login.php b/actions/login.php index ad57dd667..679817520 100644 --- a/actions/login.php +++ b/actions/login.php @@ -159,7 +159,7 @@ class LoginAction extends Action $url = common_get_returnto(); if ($url) { - // We don't have to return to it again + // We do not have to return to it again common_set_returnto(null); } else { $url = common_local_url('all', diff --git a/actions/logout.php b/actions/logout.php index 1e0adae57..7e768fca6 100644 --- a/actions/logout.php +++ b/actions/logout.php @@ -81,7 +81,7 @@ class LogoutAction extends Action { common_set_user(null); common_real_login(false); // not logged in - common_forgetme(); // don't log back in! + common_forgetme(); // do not log back in! } } diff --git a/actions/newmessage.php b/actions/newmessage.php index 0db2e7181..73307fdfc 100644 --- a/actions/newmessage.php +++ b/actions/newmessage.php @@ -61,7 +61,7 @@ class NewmessageAction extends Action /** * Title of the page * - * Note that this usually doesn't get called unless something went wrong + * Note that this usually does not get called unless something went wrong * * @return string page title */ diff --git a/actions/newnotice.php b/actions/newnotice.php index fbd7ab6bc..fc06e5c98 100644 --- a/actions/newnotice.php +++ b/actions/newnotice.php @@ -59,7 +59,7 @@ class NewnoticeAction extends Action /** * Title of the page * - * Note that this usually doesn't get called unless something went wrong + * Note that this usually does not get called unless something went wrong * * @return string page title */ diff --git a/actions/opensearch.php b/actions/opensearch.php index 8ebb5fc82..3136380b0 100644 --- a/actions/opensearch.php +++ b/actions/opensearch.php @@ -52,7 +52,7 @@ class OpensearchAction extends Action * * @param array $args query arguments * - * @return boolean false if user doesn't exist + * @return boolean false if user does not exist */ function handle($args) { diff --git a/actions/passwordsettings.php b/actions/passwordsettings.php index 87eb45a7d..6658d279f 100644 --- a/actions/passwordsettings.php +++ b/actions/passwordsettings.php @@ -97,7 +97,7 @@ class PasswordsettingsAction extends AccountSettingsAction $this->elementStart('ul', 'form_data'); - // Users who logged in with OpenID won't have a pwd + // Users who logged in with OpenID will not have a pwd if ($user->password) { $this->elementStart('li'); $this->password('oldpassword', _('Old password')); diff --git a/actions/register.php b/actions/register.php index 584ad3ead..69c50faca 100644 --- a/actions/register.php +++ b/actions/register.php @@ -174,7 +174,7 @@ class RegisterAction extends Action $bio = $this->trimmed('bio'); $location = $this->trimmed('location'); - // We don't trim these... whitespace is OK in a password! + // We do not trim these... whitespace is OK in a password! $password = $this->arg('password'); $confirm = $this->arg('confirm'); diff --git a/actions/showgroup.php b/actions/showgroup.php index a4af29391..ae956befa 100644 --- a/actions/showgroup.php +++ b/actions/showgroup.php @@ -418,7 +418,7 @@ class ShowgroupAction extends GroupDesignAction // XXX: WORM cache this $members = $this->group->getMembers(); $members_count = 0; - /** $member->count() doesn't work. */ + /** $member->count() does not work. */ while ($members->fetch()) { $members_count++; } diff --git a/actions/showmessage.php b/actions/showmessage.php index db757948b..cf3a819c1 100644 --- a/actions/showmessage.php +++ b/actions/showmessage.php @@ -137,7 +137,7 @@ class ShowmessageAction extends MailboxAction } /** - * Don't show local navigation + * Do not show local navigation * * @return void */ @@ -147,7 +147,7 @@ class ShowmessageAction extends MailboxAction } /** - * Don't show page notice + * Do not show page notice * * @return void */ @@ -157,7 +157,7 @@ class ShowmessageAction extends MailboxAction } /** - * Don't show aside + * Do not show aside * * @return void */ @@ -167,7 +167,7 @@ class ShowmessageAction extends MailboxAction } /** - * Don't show any instructions + * Do not show any instructions * * @return string */ diff --git a/actions/shownotice.php b/actions/shownotice.php index 5d16fdad9..688089f02 100644 --- a/actions/shownotice.php +++ b/actions/shownotice.php @@ -208,7 +208,7 @@ class ShownoticeAction extends OwnerDesignAction } /** - * Don't show local navigation + * Do not show local navigation * * @return void */ @@ -234,7 +234,7 @@ class ShownoticeAction extends OwnerDesignAction } /** - * Don't show page notice + * Do not show page notice * * @return void */ @@ -244,7 +244,7 @@ class ShownoticeAction extends OwnerDesignAction } /** - * Don't show aside + * Do not show aside * * @return void */ diff --git a/actions/showstream.php b/actions/showstream.php index 663638c18..4952ebdb7 100644 --- a/actions/showstream.php +++ b/actions/showstream.php @@ -253,7 +253,7 @@ class ShowstreamAction extends ProfileAction } } -// We don't show the author for a profile, since we already know who it is! +// We do not show the author for a profile, since we already know who it is! class ProfileNoticeList extends NoticeList { diff --git a/actions/sup.php b/actions/sup.php index 5daf0a1c1..a199f247e 100644 --- a/actions/sup.php +++ b/actions/sup.php @@ -61,7 +61,7 @@ class SupAction extends Action $notice = new Notice(); # XXX: cache this. Depends on how big this protocol becomes; - # Re-doing this query every 15 seconds isn't the end of the world. + # Re-doing this query every 15 seconds is not the end of the world. $divider = common_sql_date(time() - $seconds); diff --git a/actions/twitapisearchatom.php b/actions/twitapisearchatom.php index 7d618c471..511d7cdc6 100644 --- a/actions/twitapisearchatom.php +++ b/actions/twitapisearchatom.php @@ -250,7 +250,7 @@ class TwitapisearchatomAction extends ApiAction } // FIXME: this alternate link is not quite right because our - // web-based notice search doesn't support a rpp (responses per + // web-based notice search does not support a rpp (responses per // page) param yet $this->element('link', array('type' => 'text/html', diff --git a/actions/twitapitrends.php b/actions/twitapitrends.php index 779405e6d..2d17e77cc 100644 --- a/actions/twitapitrends.php +++ b/actions/twitapitrends.php @@ -55,7 +55,7 @@ class TwitapitrendsAction extends ApiAction * * @param array $args Web and URL arguments * - * @return boolean false if user doesn't exist + * @return boolean false if user does not exist */ function prepare($args) { diff --git a/classes/File_redirection.php b/classes/File_redirection.php index 08a6e8d8b..c951c1ee7 100644 --- a/classes/File_redirection.php +++ b/classes/File_redirection.php @@ -53,7 +53,7 @@ class File_redirection extends Memcached_DataObject 'connect_timeout' => 10, // # seconds to wait 'max_redirs' => $redirs, // # max number of http redirections to follow 'follow_redirects' => true, // Follow redirects - 'store_body' => false, // We won't need body content here. + 'store_body' => false, // We will not need body content here. )); return $request; } @@ -81,12 +81,12 @@ class File_redirection extends Memcached_DataObject } try { $request = self::_commonHttp($short_url, $redirs); - // Don't include body in output + // Do not include body in output $request->setMethod(HTTP_Request2::METHOD_HEAD); $response = $request->send(); if (405 == $response->getStatus()) { - // Server doesn't support HEAD method? Can this really happen? + // Server does not support HEAD method? Can this really happen? // We'll try again as a GET and ignore the response data. $request = self::_commonHttp($short_url, $redirs); $response = $request->send(); @@ -178,7 +178,7 @@ class File_redirection extends Memcached_DataObject case 'aim': case 'jabber': case 'xmpp': - // don't touch anything + // do not touch anything break; default: diff --git a/classes/Notice.php b/classes/Notice.php index 862d4c762..0c54b6b67 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -146,7 +146,7 @@ class Notice extends Memcached_DataObject /* Add them to the database */ foreach(array_unique($hashtags) as $hashtag) { - /* elide characters we don't want in the tag */ + /* elide characters we do not want in the tag */ $this->saveTag($hashtag); } return true; @@ -1105,7 +1105,7 @@ class Notice extends Memcached_DataObject if (empty($recipient)) { continue; } - // Don't save replies from blocked profile to local user + // Do not save replies from blocked profile to local user $recipient_user = User::staticGet('id', $recipient->id); if (!empty($recipient_user) && $recipient_user->hasBlocked($sender)) { continue; @@ -1131,7 +1131,7 @@ class Notice extends Memcached_DataObject $tagged = Profile_tag::getTagged($sender->id, $tag); foreach ($tagged as $t) { if (!$replied[$t->id]) { - // Don't save replies from blocked profile to local user + // Do not save replies from blocked profile to local user $t_user = User::staticGet('id', $t->id); if ($t_user && $t_user->hasBlocked($sender)) { continue; diff --git a/classes/Profile.php b/classes/Profile.php index 7c1e9db33..a50f4951d 100644 --- a/classes/Profile.php +++ b/classes/Profile.php @@ -101,7 +101,7 @@ class Profile extends Memcached_DataObject } foreach (array(AVATAR_PROFILE_SIZE, AVATAR_STREAM_SIZE, AVATAR_MINI_SIZE) as $size) { - # We don't do a scaled one if original is our scaled size + # We do not do a scaled one if original is our scaled size if (!($avatar->width == $size && $avatar->height == $size)) { $scaled_filename = $imagefile->resize($size); @@ -174,7 +174,7 @@ class Profile extends Memcached_DataObject function getNotices($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0, $since=null) { - // XXX: I'm not sure this is going to be any faster. It probably isn't. + // XXX: I'm not sure this is going to be any faster. It probably is not. $ids = Notice::stream(array($this, '_streamDirect'), array(), 'profile:notice_ids:' . $this->id, diff --git a/classes/User.php b/classes/User.php index 9b90ce61b..c529b82e0 100644 --- a/classes/User.php +++ b/classes/User.php @@ -87,7 +87,7 @@ class User extends Memcached_DataObject return (is_null($sub)) ? false : true; } - // 'update' won't write key columns, so we have to do it ourselves. + // 'update' will not write key columns, so we have to do it ourselves. function updateKeys(&$orig) { @@ -384,7 +384,7 @@ class User extends Memcached_DataObject return false; } - // Otherwise, cache doesn't have all faves; + // Otherwise, cache does not have all faves; // fall through to the default } @@ -463,7 +463,7 @@ class User extends Memcached_DataObject { $cache = common_memcache(); if ($cache) { - // Faves don't happen chronologically, so we need to blow + // Faves do not happen chronologically, so we need to blow // ;last cache, too $cache->delete(common_cache_key('fave:ids_by_user:'.$this->id)); $cache->delete(common_cache_key('fave:ids_by_user:'.$this->id.';last')); diff --git a/lib/api.php b/lib/api.php index a1236ab7e..fb4c4289b 100644 --- a/lib/api.php +++ b/lib/api.php @@ -66,7 +66,7 @@ class ApiAction extends Action * * @param array $args Web and URL arguments * - * @return boolean false if user doesn't exist + * @return boolean false if user does not exist */ function prepare($args) @@ -138,7 +138,7 @@ class ApiAction extends Action $design = null; $user = $profile->getUser(); - // Note: some profiles don't have an associated user + // Note: some profiles do not have an associated user if (!empty($user)) { $design = $user->getDesign(); @@ -203,7 +203,7 @@ class ApiAction extends Action if ($get_notice) { $notice = $profile->getCurrentNotice(); if ($notice) { - # don't get user! + # do not get user! $twitter_user['status'] = $this->twitterStatusArray($notice, false); } } @@ -263,7 +263,7 @@ class ApiAction extends Action } if ($include_user) { - # Don't get notice (recursive!) + # Do not get notice (recursive!) $twitter_user = $this->twitterUserArray($profile, false); $twitter_status['user'] = $twitter_user; } @@ -1074,7 +1074,7 @@ class ApiAction extends Action function initTwitterAtom() { $this->startXML(); - // FIXME: don't hardcode the language here! + // FIXME: do not hardcode the language here! $this->elementStart('feed', array('xmlns' => 'http://www.w3.org/2005/Atom', 'xml:lang' => 'en-US', 'xmlns:thr' => 'http://purl.org/syndication/thread/1.0')); @@ -1116,7 +1116,7 @@ class ApiAction extends Action return User::staticGet('nickname', $nickname); } else if ($this->arg('user_id')) { // This is to ensure that a non-numeric user_id still - // overrides screen_name even if it doesn't get used + // overrides screen_name even if it does not get used if (is_numeric($this->arg('user_id'))) { return User::staticGet('id', $this->arg('user_id')); } @@ -1146,7 +1146,7 @@ class ApiAction extends Action return User_group::staticGet('nickname', $nickname); } else if ($this->arg('group_id')) { // This is to ensure that a non-numeric user_id still - // overrides screen_name even if it doesn't get used + // overrides screen_name even if it does not get used if (is_numeric($this->arg('group_id'))) { return User_group::staticGet('id', $this->arg('group_id')); } diff --git a/lib/apiauth.php b/lib/apiauth.php index 2f2e44a26..b8189f15d 100644 --- a/lib/apiauth.php +++ b/lib/apiauth.php @@ -87,7 +87,7 @@ class ApiAuthAction extends ApiAction } /** - * Check for a user specified via HTTP basic auth. If there isn't + * Check for a user specified via HTTP basic auth. If there is not * one, try to get one by outputting the basic auth header. * * @return boolean true or false diff --git a/lib/dberroraction.php b/lib/dberroraction.php index 2cb66a022..893797b70 100644 --- a/lib/dberroraction.php +++ b/lib/dberroraction.php @@ -39,7 +39,7 @@ require_once INSTALLDIR.'/lib/servererroraction.php'; * * This only occurs if there's been a DB_DataObject_Error that's * reported through PEAR, so we try to avoid doing anything that connects - * to the DB, so we don't trigger it again. + * to the DB, so we do not trigger it again. * * @category Action * @package StatusNet @@ -62,12 +62,12 @@ class DBErrorAction extends ServerErrorAction function getLanguage() { - // Don't try to figure out user's language; just show the page + // Do not try to figure out user's language; just show the page return common_config('site', 'language'); } function showPrimaryNav() { - // don't show primary nav + // do not show primary nav } } diff --git a/lib/error.php b/lib/error.php index 3162cfe65..5ed5dec1b 100644 --- a/lib/error.php +++ b/lib/error.php @@ -104,11 +104,11 @@ class ErrorAction extends Action { parent::showPage(); - // We don't want to have any more output after this + // We do not want to have any more output after this exit(); } - // Overload a bunch of stuff so the page isn't too bloated + // Overload a bunch of stuff so the page is not too bloated function showBody() { diff --git a/lib/htmloutputter.php b/lib/htmloutputter.php index c2ec83c28..73bd9ce81 100644 --- a/lib/htmloutputter.php +++ b/lib/htmloutputter.php @@ -76,7 +76,7 @@ class HTMLOutputter extends XMLOutputter /** * Start an HTML document * - * If $type isn't specified, will attempt to do content negotiation. + * If $type is not specified, will attempt to do content negotiation. * * Attempts to do content negotiation for language, also. * diff --git a/lib/imagefile.php b/lib/imagefile.php index cf1668f20..edc7218d0 100644 --- a/lib/imagefile.php +++ b/lib/imagefile.php @@ -119,7 +119,7 @@ class ImageFile return; } - // Don't crop/scale if it isn't necessary + // Do not crop/scale if it is not necessary if ($size === $this->width && $size === $this->height && $x === 0 diff --git a/lib/jabber.php b/lib/jabber.php index 73f2ec660..d666fcbb3 100644 --- a/lib/jabber.php +++ b/lib/jabber.php @@ -437,7 +437,7 @@ function jabber_public_notice($notice) $public = common_config('xmpp', 'public'); - // FIXME PRIV don't send out private messages here + // FIXME PRIV do not send out private messages here // XXX: should we send out non-local messages if public,localonly // = false? I think not diff --git a/lib/mail.php b/lib/mail.php index 5218059e9..79630b721 100644 --- a/lib/mail.php +++ b/lib/mail.php @@ -467,7 +467,7 @@ function mail_notify_nudge($from, $to) "these days and is inviting you to post some news.\n\n". "So let's hear from you :)\n\n". "%3\$s\n\n". - "Don't reply to this email; it won't get to them.\n\n". + "Do not reply to this email. It will not get to them.\n\n". "With kind regards,\n". "%4\$s\n"), $from_profile->getBestName(), @@ -516,7 +516,7 @@ function mail_notify_message($message, $from=null, $to=null) "------------------------------------------------------\n\n". "You can reply to their message here:\n\n". "%4\$s\n\n". - "Don't reply to this email; it won't get to them.\n\n". + "Do not reply to this email. It will not get to them.\n\n". "With kind regards,\n". "%5\$s\n"), $from_profile->getBestName(), @@ -532,7 +532,7 @@ function mail_notify_message($message, $from=null, $to=null) /** * notify a user that one of their notices has been chosen as a 'fave' * - * Doesn't check that the user has an email address nor if they + * Does not check that the user has an email address nor if they * want to receive notification of faves. Maybe this happens higher * up the stack...? * diff --git a/lib/noticelist.php b/lib/noticelist.php index 027db2b3e..206724676 100644 --- a/lib/noticelist.php +++ b/lib/noticelist.php @@ -347,7 +347,7 @@ class NoticeListItem extends Widget * show the link to the main page for the notice * * Displays a link to the page for a notice, with "relative" time. Tries to - * get remote notice URLs correct, but doesn't always succeed. + * get remote notice URLs correct, but does not always succeed. * * @return void */ @@ -483,7 +483,7 @@ class NoticeListItem extends Widget * show a link to reply to the current notice * * Should either do the reply in the current notice form (if available), or - * link out to the notice-posting form. A little flakey, doesn't always work. + * link out to the notice-posting form. A little flakey, does not always work. * * @return void */ diff --git a/lib/queuehandler.php b/lib/queuehandler.php index cd43b1e09..7c07ca4f9 100644 --- a/lib/queuehandler.php +++ b/lib/queuehandler.php @@ -96,8 +96,8 @@ class QueueHandler extends Daemon * Initialization, run when the queue handler starts. * If this function indicates failure, the handler run will be aborted. * - * @fixme run() will abort if this doesn't return true, - * but some subclasses don't bother. + * @fixme run() will abort if this does not return true, + * but some subclasses do not bother. * @return boolean true on success, false on failure */ function start() @@ -108,8 +108,8 @@ class QueueHandler extends Daemon * Cleanup, run when the queue handler ends. * If this function indicates failure, a warning will be logged. * - * @fixme run() will throw warnings if this doesn't return true, - * but many subclasses don't bother. + * @fixme run() will throw warnings if this does not return true, + * but many subclasses do not bother. * @return boolean true on success, false on failure */ function finish() @@ -137,7 +137,7 @@ class QueueHandler extends Daemon * method, which passes control back to our handle_notice() method for * each notice that comes in on the queue. * - * Most of the time this won't need to be overridden in a subclass. + * Most of the time this will not need to be overridden in a subclass. * * @return boolean true on success, false on failure */ @@ -173,7 +173,7 @@ class QueueHandler extends Daemon * Called by QueueHandler after each handled item or empty polling cycle. * This is a good time to e.g. service your XMPP connection. * - * Doesn't need to be overridden if there's no maintenance to do. + * Does not need to be overridden if there's no maintenance to do. * * @param int $timeout seconds to sleep if there's nothing to do */ diff --git a/lib/rssaction.php b/lib/rssaction.php index faf6bec7d..0e84a65e9 100644 --- a/lib/rssaction.php +++ b/lib/rssaction.php @@ -386,7 +386,7 @@ class Rss10Action extends Action return null; } - // FIXME: doesn't handle modified profiles, avatars, deleted notices + // FIXME: does not handle modified profiles, avatars, deleted notices return strtotime($this->notices[0]->created); } diff --git a/lib/search_engines.php b/lib/search_engines.php index 69f6ff468..82713235c 100644 --- a/lib/search_engines.php +++ b/lib/search_engines.php @@ -119,7 +119,7 @@ class MySQLSearch extends SearchEngine return true; } else if ('identica_notices' === $this->table) { - // Don't show imported notices + // Do not show imported notices $this->target->whereAdd('notice.is_local != ' . Notice::GATEWAY); if (strtolower($q) != $q) { diff --git a/lib/util.php b/lib/util.php index dde3fb48f..8f7521e59 100644 --- a/lib/util.php +++ b/lib/util.php @@ -62,7 +62,7 @@ function common_init_language() $locale_set = common_init_locale($language); setlocale(LC_CTYPE, 'C'); - // So we don't have to make people install the gettext locales + // So we do not have to make people install the gettext locales $path = common_config('site','locale_path'); bindtextdomain("statusnet", $path); bind_textdomain_codeset("statusnet", "UTF-8"); @@ -139,7 +139,7 @@ function common_check_user($nickname, $password) } } }else{ - //no handler indicated the credentials were valid, and we know their not valid because the user isn't in the database + //no handler indicated the credentials were valid, and we know their not valid because the user is not in the database return false; } } else { @@ -396,7 +396,7 @@ function common_current_user() } // Logins that are 'remembered' aren't 'real' -- they're subject to -// cookie-stealing. So, we don't let them do certain things. New reg, +// cookie-stealing. So, we do not let them do certain things. New reg, // OpenID, and password logins _are_ real. function common_real_login($real=true) @@ -1147,7 +1147,7 @@ function common_accept_to_prefs($accept, $def = '*/*') $parts = explode(',', $accept); foreach($parts as $part) { - // FIXME: doesn't deal with params like 'text/html; level=1' + // FIXME: does not deal with params like 'text/html; level=1' @list($value, $qpart) = explode(';', trim($part)); $match = array(); if(!isset($qpart)) { @@ -1346,7 +1346,7 @@ function common_error_handler($errno, $errstr, $errfile, $errline, $errcontext) } // FIXME: show error page if we're on the Web - /* Don't execute PHP internal error handler */ + /* Do not execute PHP internal error handler */ return true; } @@ -1448,7 +1448,7 @@ function common_shorten_url($long_url) } global $_shorteners; if (!isset($_shorteners[$svc])) { - //the user selected service doesn't exist, so default to ur1.ca + //the user selected service does not exist, so default to ur1.ca $svc = 'ur1.ca'; } if (!isset($_shorteners[$svc])) { diff --git a/lib/xmloutputter.php b/lib/xmloutputter.php index 5f06e491d..9d862b2d0 100644 --- a/lib/xmloutputter.php +++ b/lib/xmloutputter.php @@ -112,7 +112,7 @@ class XMLOutputter * * Utility for outputting an XML element. A convenient wrapper * for a bunch of longer XMLWriter calls. This is best for - * when an element doesn't have any sub-elements; if that's the + * when an element does not have any sub-elements; if that's the * case, use elementStart() and elementEnd() instead. * * The $content element will be escaped for XML. If you need diff --git a/lib/xmppqueuehandler.php b/lib/xmppqueuehandler.php index 8acdcafe7..29008da64 100644 --- a/lib/xmppqueuehandler.php +++ b/lib/xmppqueuehandler.php @@ -37,7 +37,7 @@ class XmppQueueHandler extends QueueHandler function start() { - # Low priority; we don't want to receive messages + # Low priority; we do not want to receive messages $this->log(LOG_INFO, "INITIALIZE"); $this->conn = jabber_connect($this->_id.$this->transport()); diff --git a/plugins/Autocomplete/autocomplete.php b/plugins/Autocomplete/autocomplete.php index 379390ffd..aeb100cfa 100644 --- a/plugins/Autocomplete/autocomplete.php +++ b/plugins/Autocomplete/autocomplete.php @@ -79,7 +79,7 @@ class AutocompleteAction extends Action function etag() { return '"' . implode(':', array($this->arg('action'), - crc32($this->arg('q')), //the actual string can have funny characters in we don't want showing up in the etag + crc32($this->arg('q')), //the actual string can have funny characters in we do not want showing up in the etag $this->arg('limit'), $this->lastModified())) . '"'; } diff --git a/plugins/BlogspamNetPlugin.php b/plugins/BlogspamNetPlugin.php index 51236001a..bf60fdcaf 100644 --- a/plugins/BlogspamNetPlugin.php +++ b/plugins/BlogspamNetPlugin.php @@ -85,7 +85,7 @@ class BlogspamNetPlugin extends Plugin } else if (preg_match('/^SPAM(:(.*))?$/', $response, $match)) { throw new ClientException(sprintf(_("Spam checker results: %s"), $match[2]), 400); } else if (preg_match('/^OK$/', $response)) { - // don't do anything + // do not do anything } else { throw new ServerException(sprintf(_("Unexpected response from %s: %s"), $this->baseUrl, $response), 500); } diff --git a/plugins/Facebook/FBConnectAuth.php b/plugins/Facebook/FBConnectAuth.php index b909a4977..165477419 100644 --- a/plugins/Facebook/FBConnectAuth.php +++ b/plugins/Facebook/FBConnectAuth.php @@ -71,7 +71,7 @@ class FBConnectauthAction extends Action 'There is already a local user (' . $flink->user_id . ') linked with this Facebook (' . $this->fbuid . ').'); - // We don't want these cookies + // We do not want these cookies getFacebook()->clear_cookie_state(); $this->clientError(_('There is already a local user linked with this Facebook.')); @@ -364,7 +364,7 @@ class FBConnectauthAction extends Action { $url = common_get_returnto(); if ($url) { - // We don't have to return to it again + // We do not have to return to it again common_set_returnto(null); } else { $url = common_local_url('all', diff --git a/plugins/Facebook/FacebookPlugin.php b/plugins/Facebook/FacebookPlugin.php index b68534b24..cd1ad7b45 100644 --- a/plugins/Facebook/FacebookPlugin.php +++ b/plugins/Facebook/FacebookPlugin.php @@ -182,7 +182,7 @@ class FacebookPlugin extends Plugin $login_url = common_local_url('FBConnectAuth'); $logout_url = common_local_url('logout'); - // XXX: Facebook says we don't need this FB_RequireFeatures(), + // XXX: Facebook says we do not need this FB_RequireFeatures(), // but we actually do, for IE and Safari. Gar. $js = '"; } else { diff --git a/plugins/Facebook/facebook/facebook_desktop.php b/plugins/Facebook/facebook/facebook_desktop.php index e79a2ca34..425bb5c7b 100644 --- a/plugins/Facebook/facebook/facebook_desktop.php +++ b/plugins/Facebook/facebook/facebook_desktop.php @@ -93,7 +93,7 @@ class FacebookDesktop extends Facebook { } public function verify_signature($fb_params, $expected_sig) { - // we don't want to verify the signature until we have a valid + // we do not want to verify the signature until we have a valid // session secret if ($this->verify_sig) { return parent::verify_signature($fb_params, $expected_sig); diff --git a/plugins/Facebook/facebook/facebookapi_php5_restlib.php b/plugins/Facebook/facebook/facebookapi_php5_restlib.php index e2a6fe88b..781390002 100755 --- a/plugins/Facebook/facebook/facebookapi_php5_restlib.php +++ b/plugins/Facebook/facebook/facebookapi_php5_restlib.php @@ -46,7 +46,7 @@ class FacebookRestClient { // on canvas pages public $added; public $is_user; - // we don't pass friends list to iframes, but we want to make + // we do not pass friends list to iframes, but we want to make // friends_get really simple in the canvas_user (non-logged in) case. // So we use the canvas_user as default arg to friends_get public $canvas_user; @@ -657,7 +657,7 @@ function toggleDisplay(id, type) { * deleted. * * IMPORTANT: If your application has registered public tags - * that other applications may be using, don't delete those tags! + * that other applications may be using, do not delete those tags! * Doing so can break the FBML ofapplications that are using them. * * @param array $tag_names the names of the tags to delete (optinal) @@ -820,7 +820,7 @@ function toggleDisplay(id, type) { if (is_array($target_ids)) { $target_ids = json_encode($target_ids); - $target_ids = trim($target_ids, "[]"); // we don't want square brackets + $target_ids = trim($target_ids, "[]"); // we do not want square brackets } return $this->call_method('facebook.feed.publishUserAction', diff --git a/plugins/Facebook/facebook/jsonwrapper/jsonwrapper.php b/plugins/Facebook/facebook/jsonwrapper/jsonwrapper.php index 29509deba..9c6c62663 100644 --- a/plugins/Facebook/facebook/jsonwrapper/jsonwrapper.php +++ b/plugins/Facebook/facebook/jsonwrapper/jsonwrapper.php @@ -1,5 +1,5 @@ location_id = $n->geonameId; $location->location_ns = self::NAMESPACE; - // handled, don't continue processing! + // handled, do not continue processing! return false; } } - // Continue processing; we don't have the answer + // Continue processing; we do not have the answer return true; } @@ -217,7 +217,7 @@ class GeonamesPlugin extends Plugin } } - // For some reason we don't know, so pass. + // For some reason we do not know, so pass. return true; } @@ -299,7 +299,7 @@ class GeonamesPlugin extends Plugin $url = 'http://www.geonames.org/' . $location->location_id; - // it's been filled, so don't process further. + // it's been filled, so do not process further. return false; } } diff --git a/plugins/OpenID/finishopenidlogin.php b/plugins/OpenID/finishopenidlogin.php index ff0b451d3..b5d978294 100644 --- a/plugins/OpenID/finishopenidlogin.php +++ b/plugins/OpenID/finishopenidlogin.php @@ -341,7 +341,7 @@ class FinishopenidloginAction extends Action { $url = common_get_returnto(); if ($url) { - # We don't have to return to it again + # We do not have to return to it again common_set_returnto(null); } else { $url = common_local_url('all', @@ -421,7 +421,7 @@ class FinishopenidloginAction extends Action $parts = parse_url($openid); - # If any of these parts exist, this won't work + # If any of these parts exist, this will not work foreach ($bad as $badpart) { if (array_key_exists($badpart, $parts)) { diff --git a/plugins/OpenID/openid.php b/plugins/OpenID/openid.php index cd042226b..4a76a8791 100644 --- a/plugins/OpenID/openid.php +++ b/plugins/OpenID/openid.php @@ -187,7 +187,7 @@ function oid_authenticate($openid_url, $returnto, $immediate=false) $form_html = $auth_request->formMarkup($trust_root, $process_url, $immediate, array('id' => $form_id)); - # XXX: This is cheap, but things choke if we don't escape ampersands + # XXX: This is cheap, but things choke if we do not escape ampersands # in the HTML attributes $form_html = preg_replace('/&/', '&', $form_html); diff --git a/plugins/PiwikAnalyticsPlugin.php b/plugins/PiwikAnalyticsPlugin.php index 54faa0bdb..81ef7c683 100644 --- a/plugins/PiwikAnalyticsPlugin.php +++ b/plugins/PiwikAnalyticsPlugin.php @@ -44,7 +44,7 @@ if (!defined('STATUSNET')) { * 'piwikId' => 'id')); * * Replace 'example.com/piwik/' with the URL to your Piwik installation and - * make sure you don't forget the final /. + * make sure you do not forget the final /. * Replace 'id' with the ID your statusnet installation has in your Piwik * analytics setup - for example '8'. * diff --git a/plugins/Realtime/RealtimePlugin.php b/plugins/Realtime/RealtimePlugin.php index 0c7c1240c..88a87dcf9 100644 --- a/plugins/Realtime/RealtimePlugin.php +++ b/plugins/Realtime/RealtimePlugin.php @@ -240,7 +240,7 @@ class RealtimePlugin extends Plugin // FIXME: this code should be abstracted to a neutral third // party, like Notice::asJson(). I'm not sure of the ethics // of refactoring from within a plugin, so I'm just abusing - // the ApiAction method. Don't do this unless you're me! + // the ApiAction method. Do not do this unless you're me! require_once(INSTALLDIR.'/lib/api.php'); diff --git a/plugins/TwitterBridge/daemons/synctwitterfriends.php b/plugins/TwitterBridge/daemons/synctwitterfriends.php index 6a155b301..76410c7cb 100755 --- a/plugins/TwitterBridge/daemons/synctwitterfriends.php +++ b/plugins/TwitterBridge/daemons/synctwitterfriends.php @@ -115,7 +115,7 @@ class SyncTwitterFriendsDaemon extends ParallelizingDaemon // Each child ps needs its own DB connection // Note: DataObject::getDatabaseConnection() creates - // a new connection if there isn't one already + // a new connection if there is not one already $conn = &$flink->getDatabaseConnection(); diff --git a/plugins/TwitterBridge/daemons/twitterstatusfetcher.php b/plugins/TwitterBridge/daemons/twitterstatusfetcher.php index ab610e553..5d0d83be3 100755 --- a/plugins/TwitterBridge/daemons/twitterstatusfetcher.php +++ b/plugins/TwitterBridge/daemons/twitterstatusfetcher.php @@ -136,7 +136,7 @@ class TwitterStatusFetcher extends ParallelizingDaemon // Each child ps needs its own DB connection // Note: DataObject::getDatabaseConnection() creates - // a new connection if there isn't one already + // a new connection if there is not one already $conn = &$flink->getDatabaseConnection(); @@ -499,7 +499,7 @@ class TwitterStatusFetcher extends ParallelizingDaemon $avatar->height = 73; } - $avatar->original = 0; // we don't have the original + $avatar->original = 0; // we do not have the original $avatar->mediatype = $mediatype; $avatar->filename = $filename; $avatar->url = Avatar::url($filename); diff --git a/plugins/TwitterBridge/twitter.php b/plugins/TwitterBridge/twitter.php index 3c6803e49..d48089caa 100644 --- a/plugins/TwitterBridge/twitter.php +++ b/plugins/TwitterBridge/twitter.php @@ -33,7 +33,7 @@ function updateTwitter_user($twitter_id, $screen_name) $fuser->query('BEGIN'); - // Dropping down to SQL because regular DB_DataObject udpate stuff doesn't seem + // Dropping down to SQL because regular DB_DataObject udpate stuff does not seem // to work so good with tables that have multiple column primary keys // Any time we update the uri for a forein user we have to make sure there diff --git a/scripts/console.php b/scripts/console.php index 2413f5079..fecb75b4a 100755 --- a/scripts/console.php +++ b/scripts/console.php @@ -60,9 +60,9 @@ function read_input_line($prompt) } /** - * On Unix-like systems where PHP readline extension isn't present, + * On Unix-like systems where PHP readline extension is not present, * -cough- Mac OS X -cough- we can shell out to bash to do it for us. - * This lets us at least handle things like arrow keys, but we don't + * This lets us at least handle things like arrow keys, but we do not * get any entry history. :( * * Shamelessly ripped from when I wrote the same code for MediaWiki. :) diff --git a/scripts/maildaemon.php b/scripts/maildaemon.php index b4e4d9f08..4ec4526ef 100755 --- a/scripts/maildaemon.php +++ b/scripts/maildaemon.php @@ -231,7 +231,7 @@ class MailerDaemon foreach ($parsed->parts as $part) { $this->extract_part($part,$msg,$attachments); } - //we don't want any attachments that are a result of this parsing + //we do not want any attachments that are a result of this parsing return $msg; } diff --git a/scripts/xmppconfirmhandler.php b/scripts/xmppconfirmhandler.php index c7ed15e49..f5f824dee 100755 --- a/scripts/xmppconfirmhandler.php +++ b/scripts/xmppconfirmhandler.php @@ -69,7 +69,7 @@ class XmppConfirmHandler extends XmppQueueHandler continue; } else { $this->log(LOG_INFO, 'Confirmation sent for ' . $confirm->address); - # Mark confirmation sent; need a dupe so we don't have the WHERE clause + # Mark confirmation sent; need a dupe so we do not have the WHERE clause $dupe = Confirm_address::staticGet('code', $confirm->code); if (!$dupe) { common_log(LOG_WARNING, 'Could not refetch confirm', __FILE__); -- cgit v1.2.3-54-g00ecf From 088081675fb7d5250a9b9dfe5015de0822cb5ac2 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Mon, 9 Nov 2009 20:01:46 +0100 Subject: Revert "Remove more contractions" This reverts commit 5ab709b73977131813884558bf56d97172a7aa26. Missed this one yesterday... --- actions/allrss.php | 2 +- actions/apiaccountratelimitstatus.php | 2 +- actions/apifriendshipsdestroy.php | 2 +- actions/attachment.php | 4 ++-- actions/avatarbynickname.php | 2 +- actions/groupblock.php | 2 +- actions/login.php | 2 +- actions/logout.php | 2 +- actions/newmessage.php | 2 +- actions/newnotice.php | 2 +- actions/opensearch.php | 2 +- actions/passwordsettings.php | 2 +- actions/register.php | 2 +- actions/showgroup.php | 2 +- actions/showmessage.php | 8 ++++---- actions/shownotice.php | 6 +++--- actions/showstream.php | 2 +- actions/sup.php | 2 +- actions/twitapisearchatom.php | 2 +- actions/twitapitrends.php | 2 +- classes/File_redirection.php | 8 ++++---- classes/Notice.php | 6 +++--- classes/Profile.php | 4 ++-- classes/User.php | 6 +++--- lib/api.php | 14 +++++++------- lib/apiauth.php | 2 +- lib/dberroraction.php | 6 +++--- lib/error.php | 4 ++-- lib/htmloutputter.php | 2 +- lib/imagefile.php | 2 +- lib/jabber.php | 2 +- lib/mail.php | 6 +++--- lib/noticelist.php | 4 ++-- lib/queuehandler.php | 12 ++++++------ lib/rssaction.php | 2 +- lib/search_engines.php | 2 +- lib/util.php | 12 ++++++------ lib/xmloutputter.php | 2 +- lib/xmppqueuehandler.php | 2 +- plugins/Autocomplete/autocomplete.php | 2 +- plugins/BlogspamNetPlugin.php | 2 +- plugins/Facebook/FBConnectAuth.php | 4 ++-- plugins/Facebook/FacebookPlugin.php | 4 ++-- plugins/Facebook/facebook/facebook.php | 8 ++++---- plugins/Facebook/facebook/facebook_desktop.php | 2 +- plugins/Facebook/facebook/facebookapi_php5_restlib.php | 6 +++--- plugins/Facebook/facebook/jsonwrapper/jsonwrapper.php | 2 +- plugins/Facebook/facebookaction.php | 6 +++--- plugins/GeonamesPlugin.php | 8 ++++---- plugins/OpenID/finishopenidlogin.php | 4 ++-- plugins/OpenID/openid.php | 2 +- plugins/PiwikAnalyticsPlugin.php | 2 +- plugins/Realtime/RealtimePlugin.php | 2 +- plugins/TwitterBridge/daemons/synctwitterfriends.php | 2 +- plugins/TwitterBridge/daemons/twitterstatusfetcher.php | 4 ++-- plugins/TwitterBridge/twitter.php | 2 +- scripts/console.php | 4 ++-- scripts/maildaemon.php | 2 +- scripts/xmppconfirmhandler.php | 2 +- 59 files changed, 110 insertions(+), 110 deletions(-) (limited to 'plugins/TwitterBridge/daemons') diff --git a/actions/allrss.php b/actions/allrss.php index 4a5d15c7b..28b1be27d 100644 --- a/actions/allrss.php +++ b/actions/allrss.php @@ -56,7 +56,7 @@ class AllrssAction extends Rss10Action * * @param array $args Web and URL arguments * - * @return boolean false if user does not exist + * @return boolean false if user doesn't exist */ function prepare($args) { diff --git a/actions/apiaccountratelimitstatus.php b/actions/apiaccountratelimitstatus.php index c7c0e7c00..96179f175 100644 --- a/actions/apiaccountratelimitstatus.php +++ b/actions/apiaccountratelimitstatus.php @@ -36,7 +36,7 @@ if (!defined('STATUSNET')) { require_once INSTALLDIR . '/lib/apibareauth.php'; /** - * We do not have a rate limit, but some clients check this method. + * We don't have a rate limit, but some clients check this method. * It always returns the same thing: 150 hits left. * * @category API diff --git a/actions/apifriendshipsdestroy.php b/actions/apifriendshipsdestroy.php index fb73624c9..3d9b7e001 100644 --- a/actions/apifriendshipsdestroy.php +++ b/actions/apifriendshipsdestroy.php @@ -113,7 +113,7 @@ class ApiFriendshipsDestroyAction extends ApiAuthAction return; } - // Do not allow unsubscribing from yourself! + // Don't allow unsubscribing from yourself! if ($this->user->id == $this->other->id) { $this->clientError( diff --git a/actions/attachment.php b/actions/attachment.php index ca9e57845..6981354d1 100644 --- a/actions/attachment.php +++ b/actions/attachment.php @@ -146,7 +146,7 @@ class AttachmentAction extends Action } /** - * Do not show local navigation + * Don't show local navigation * * @return void */ @@ -170,7 +170,7 @@ class AttachmentAction extends Action } /** - * Do not show page notice + * Don't show page notice * * @return void */ diff --git a/actions/avatarbynickname.php b/actions/avatarbynickname.php index 1a6925e11..537950792 100644 --- a/actions/avatarbynickname.php +++ b/actions/avatarbynickname.php @@ -49,7 +49,7 @@ class AvatarbynicknameAction extends Action * * @param array $args query arguments * - * @return boolean false if nickname or user is not found + * @return boolean false if nickname or user isn't found */ function handle($args) { diff --git a/actions/groupblock.php b/actions/groupblock.php index 133101eb7..979a56a81 100644 --- a/actions/groupblock.php +++ b/actions/groupblock.php @@ -95,7 +95,7 @@ class GroupblockAction extends Action $this->clientError(_('User is already blocked from group.')); return false; } - // XXX: could have proactive blocks, but we do not have UI for it. + // XXX: could have proactive blocks, but we don't have UI for it. if (!$this->profile->isMember($this->group)) { $this->clientError(_('User is not a member of group.')); return false; diff --git a/actions/login.php b/actions/login.php index 679817520..ad57dd667 100644 --- a/actions/login.php +++ b/actions/login.php @@ -159,7 +159,7 @@ class LoginAction extends Action $url = common_get_returnto(); if ($url) { - // We do not have to return to it again + // We don't have to return to it again common_set_returnto(null); } else { $url = common_local_url('all', diff --git a/actions/logout.php b/actions/logout.php index 7e768fca6..1e0adae57 100644 --- a/actions/logout.php +++ b/actions/logout.php @@ -81,7 +81,7 @@ class LogoutAction extends Action { common_set_user(null); common_real_login(false); // not logged in - common_forgetme(); // do not log back in! + common_forgetme(); // don't log back in! } } diff --git a/actions/newmessage.php b/actions/newmessage.php index 73307fdfc..0db2e7181 100644 --- a/actions/newmessage.php +++ b/actions/newmessage.php @@ -61,7 +61,7 @@ class NewmessageAction extends Action /** * Title of the page * - * Note that this usually does not get called unless something went wrong + * Note that this usually doesn't get called unless something went wrong * * @return string page title */ diff --git a/actions/newnotice.php b/actions/newnotice.php index fc06e5c98..fbd7ab6bc 100644 --- a/actions/newnotice.php +++ b/actions/newnotice.php @@ -59,7 +59,7 @@ class NewnoticeAction extends Action /** * Title of the page * - * Note that this usually does not get called unless something went wrong + * Note that this usually doesn't get called unless something went wrong * * @return string page title */ diff --git a/actions/opensearch.php b/actions/opensearch.php index b205d2fe2..861b53d7d 100644 --- a/actions/opensearch.php +++ b/actions/opensearch.php @@ -52,7 +52,7 @@ class OpensearchAction extends Action * * @param array $args query arguments * - * @return boolean false if user does not exist + * @return boolean false if user doesn't exist */ function handle($args) { diff --git a/actions/passwordsettings.php b/actions/passwordsettings.php index 6658d279f..87eb45a7d 100644 --- a/actions/passwordsettings.php +++ b/actions/passwordsettings.php @@ -97,7 +97,7 @@ class PasswordsettingsAction extends AccountSettingsAction $this->elementStart('ul', 'form_data'); - // Users who logged in with OpenID will not have a pwd + // Users who logged in with OpenID won't have a pwd if ($user->password) { $this->elementStart('li'); $this->password('oldpassword', _('Old password')); diff --git a/actions/register.php b/actions/register.php index c4f6760aa..57f8e7bdf 100644 --- a/actions/register.php +++ b/actions/register.php @@ -174,7 +174,7 @@ class RegisterAction extends Action $bio = $this->trimmed('bio'); $location = $this->trimmed('location'); - // We do not trim these... whitespace is OK in a password! + // We don't trim these... whitespace is OK in a password! $password = $this->arg('password'); $confirm = $this->arg('confirm'); diff --git a/actions/showgroup.php b/actions/showgroup.php index ae956befa..a4af29391 100644 --- a/actions/showgroup.php +++ b/actions/showgroup.php @@ -418,7 +418,7 @@ class ShowgroupAction extends GroupDesignAction // XXX: WORM cache this $members = $this->group->getMembers(); $members_count = 0; - /** $member->count() does not work. */ + /** $member->count() doesn't work. */ while ($members->fetch()) { $members_count++; } diff --git a/actions/showmessage.php b/actions/showmessage.php index cf3a819c1..db757948b 100644 --- a/actions/showmessage.php +++ b/actions/showmessage.php @@ -137,7 +137,7 @@ class ShowmessageAction extends MailboxAction } /** - * Do not show local navigation + * Don't show local navigation * * @return void */ @@ -147,7 +147,7 @@ class ShowmessageAction extends MailboxAction } /** - * Do not show page notice + * Don't show page notice * * @return void */ @@ -157,7 +157,7 @@ class ShowmessageAction extends MailboxAction } /** - * Do not show aside + * Don't show aside * * @return void */ @@ -167,7 +167,7 @@ class ShowmessageAction extends MailboxAction } /** - * Do not show any instructions + * Don't show any instructions * * @return string */ diff --git a/actions/shownotice.php b/actions/shownotice.php index 688089f02..5d16fdad9 100644 --- a/actions/shownotice.php +++ b/actions/shownotice.php @@ -208,7 +208,7 @@ class ShownoticeAction extends OwnerDesignAction } /** - * Do not show local navigation + * Don't show local navigation * * @return void */ @@ -234,7 +234,7 @@ class ShownoticeAction extends OwnerDesignAction } /** - * Do not show page notice + * Don't show page notice * * @return void */ @@ -244,7 +244,7 @@ class ShownoticeAction extends OwnerDesignAction } /** - * Do not show aside + * Don't show aside * * @return void */ diff --git a/actions/showstream.php b/actions/showstream.php index 4952ebdb7..663638c18 100644 --- a/actions/showstream.php +++ b/actions/showstream.php @@ -253,7 +253,7 @@ class ShowstreamAction extends ProfileAction } } -// We do not show the author for a profile, since we already know who it is! +// We don't show the author for a profile, since we already know who it is! class ProfileNoticeList extends NoticeList { diff --git a/actions/sup.php b/actions/sup.php index a199f247e..5daf0a1c1 100644 --- a/actions/sup.php +++ b/actions/sup.php @@ -61,7 +61,7 @@ class SupAction extends Action $notice = new Notice(); # XXX: cache this. Depends on how big this protocol becomes; - # Re-doing this query every 15 seconds is not the end of the world. + # Re-doing this query every 15 seconds isn't the end of the world. $divider = common_sql_date(time() - $seconds); diff --git a/actions/twitapisearchatom.php b/actions/twitapisearchatom.php index 511d7cdc6..7d618c471 100644 --- a/actions/twitapisearchatom.php +++ b/actions/twitapisearchatom.php @@ -250,7 +250,7 @@ class TwitapisearchatomAction extends ApiAction } // FIXME: this alternate link is not quite right because our - // web-based notice search does not support a rpp (responses per + // web-based notice search doesn't support a rpp (responses per // page) param yet $this->element('link', array('type' => 'text/html', diff --git a/actions/twitapitrends.php b/actions/twitapitrends.php index 2d17e77cc..779405e6d 100644 --- a/actions/twitapitrends.php +++ b/actions/twitapitrends.php @@ -55,7 +55,7 @@ class TwitapitrendsAction extends ApiAction * * @param array $args Web and URL arguments * - * @return boolean false if user does not exist + * @return boolean false if user doesn't exist */ function prepare($args) { diff --git a/classes/File_redirection.php b/classes/File_redirection.php index c951c1ee7..08a6e8d8b 100644 --- a/classes/File_redirection.php +++ b/classes/File_redirection.php @@ -53,7 +53,7 @@ class File_redirection extends Memcached_DataObject 'connect_timeout' => 10, // # seconds to wait 'max_redirs' => $redirs, // # max number of http redirections to follow 'follow_redirects' => true, // Follow redirects - 'store_body' => false, // We will not need body content here. + 'store_body' => false, // We won't need body content here. )); return $request; } @@ -81,12 +81,12 @@ class File_redirection extends Memcached_DataObject } try { $request = self::_commonHttp($short_url, $redirs); - // Do not include body in output + // Don't include body in output $request->setMethod(HTTP_Request2::METHOD_HEAD); $response = $request->send(); if (405 == $response->getStatus()) { - // Server does not support HEAD method? Can this really happen? + // Server doesn't support HEAD method? Can this really happen? // We'll try again as a GET and ignore the response data. $request = self::_commonHttp($short_url, $redirs); $response = $request->send(); @@ -178,7 +178,7 @@ class File_redirection extends Memcached_DataObject case 'aim': case 'jabber': case 'xmpp': - // do not touch anything + // don't touch anything break; default: diff --git a/classes/Notice.php b/classes/Notice.php index 32a8b693c..9886875cb 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -146,7 +146,7 @@ class Notice extends Memcached_DataObject /* Add them to the database */ foreach(array_unique($hashtags) as $hashtag) { - /* elide characters we do not want in the tag */ + /* elide characters we don't want in the tag */ $this->saveTag($hashtag); } return true; @@ -1105,7 +1105,7 @@ class Notice extends Memcached_DataObject if (empty($recipient)) { continue; } - // Do not save replies from blocked profile to local user + // Don't save replies from blocked profile to local user $recipient_user = User::staticGet('id', $recipient->id); if (!empty($recipient_user) && $recipient_user->hasBlocked($sender)) { continue; @@ -1131,7 +1131,7 @@ class Notice extends Memcached_DataObject $tagged = Profile_tag::getTagged($sender->id, $tag); foreach ($tagged as $t) { if (!$replied[$t->id]) { - // Do not save replies from blocked profile to local user + // Don't save replies from blocked profile to local user $t_user = User::staticGet('id', $t->id); if ($t_user && $t_user->hasBlocked($sender)) { continue; diff --git a/classes/Profile.php b/classes/Profile.php index a50f4951d..7c1e9db33 100644 --- a/classes/Profile.php +++ b/classes/Profile.php @@ -101,7 +101,7 @@ class Profile extends Memcached_DataObject } foreach (array(AVATAR_PROFILE_SIZE, AVATAR_STREAM_SIZE, AVATAR_MINI_SIZE) as $size) { - # We do not do a scaled one if original is our scaled size + # We don't do a scaled one if original is our scaled size if (!($avatar->width == $size && $avatar->height == $size)) { $scaled_filename = $imagefile->resize($size); @@ -174,7 +174,7 @@ class Profile extends Memcached_DataObject function getNotices($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $max_id=0, $since=null) { - // XXX: I'm not sure this is going to be any faster. It probably is not. + // XXX: I'm not sure this is going to be any faster. It probably isn't. $ids = Notice::stream(array($this, '_streamDirect'), array(), 'profile:notice_ids:' . $this->id, diff --git a/classes/User.php b/classes/User.php index c529b82e0..9b90ce61b 100644 --- a/classes/User.php +++ b/classes/User.php @@ -87,7 +87,7 @@ class User extends Memcached_DataObject return (is_null($sub)) ? false : true; } - // 'update' will not write key columns, so we have to do it ourselves. + // 'update' won't write key columns, so we have to do it ourselves. function updateKeys(&$orig) { @@ -384,7 +384,7 @@ class User extends Memcached_DataObject return false; } - // Otherwise, cache does not have all faves; + // Otherwise, cache doesn't have all faves; // fall through to the default } @@ -463,7 +463,7 @@ class User extends Memcached_DataObject { $cache = common_memcache(); if ($cache) { - // Faves do not happen chronologically, so we need to blow + // Faves don't happen chronologically, so we need to blow // ;last cache, too $cache->delete(common_cache_key('fave:ids_by_user:'.$this->id)); $cache->delete(common_cache_key('fave:ids_by_user:'.$this->id.';last')); diff --git a/lib/api.php b/lib/api.php index fb4c4289b..a1236ab7e 100644 --- a/lib/api.php +++ b/lib/api.php @@ -66,7 +66,7 @@ class ApiAction extends Action * * @param array $args Web and URL arguments * - * @return boolean false if user does not exist + * @return boolean false if user doesn't exist */ function prepare($args) @@ -138,7 +138,7 @@ class ApiAction extends Action $design = null; $user = $profile->getUser(); - // Note: some profiles do not have an associated user + // Note: some profiles don't have an associated user if (!empty($user)) { $design = $user->getDesign(); @@ -203,7 +203,7 @@ class ApiAction extends Action if ($get_notice) { $notice = $profile->getCurrentNotice(); if ($notice) { - # do not get user! + # don't get user! $twitter_user['status'] = $this->twitterStatusArray($notice, false); } } @@ -263,7 +263,7 @@ class ApiAction extends Action } if ($include_user) { - # Do not get notice (recursive!) + # Don't get notice (recursive!) $twitter_user = $this->twitterUserArray($profile, false); $twitter_status['user'] = $twitter_user; } @@ -1074,7 +1074,7 @@ class ApiAction extends Action function initTwitterAtom() { $this->startXML(); - // FIXME: do not hardcode the language here! + // FIXME: don't hardcode the language here! $this->elementStart('feed', array('xmlns' => 'http://www.w3.org/2005/Atom', 'xml:lang' => 'en-US', 'xmlns:thr' => 'http://purl.org/syndication/thread/1.0')); @@ -1116,7 +1116,7 @@ class ApiAction extends Action return User::staticGet('nickname', $nickname); } else if ($this->arg('user_id')) { // This is to ensure that a non-numeric user_id still - // overrides screen_name even if it does not get used + // overrides screen_name even if it doesn't get used if (is_numeric($this->arg('user_id'))) { return User::staticGet('id', $this->arg('user_id')); } @@ -1146,7 +1146,7 @@ class ApiAction extends Action return User_group::staticGet('nickname', $nickname); } else if ($this->arg('group_id')) { // This is to ensure that a non-numeric user_id still - // overrides screen_name even if it does not get used + // overrides screen_name even if it doesn't get used if (is_numeric($this->arg('group_id'))) { return User_group::staticGet('id', $this->arg('group_id')); } diff --git a/lib/apiauth.php b/lib/apiauth.php index b8189f15d..2f2e44a26 100644 --- a/lib/apiauth.php +++ b/lib/apiauth.php @@ -87,7 +87,7 @@ class ApiAuthAction extends ApiAction } /** - * Check for a user specified via HTTP basic auth. If there is not + * Check for a user specified via HTTP basic auth. If there isn't * one, try to get one by outputting the basic auth header. * * @return boolean true or false diff --git a/lib/dberroraction.php b/lib/dberroraction.php index 893797b70..2cb66a022 100644 --- a/lib/dberroraction.php +++ b/lib/dberroraction.php @@ -39,7 +39,7 @@ require_once INSTALLDIR.'/lib/servererroraction.php'; * * This only occurs if there's been a DB_DataObject_Error that's * reported through PEAR, so we try to avoid doing anything that connects - * to the DB, so we do not trigger it again. + * to the DB, so we don't trigger it again. * * @category Action * @package StatusNet @@ -62,12 +62,12 @@ class DBErrorAction extends ServerErrorAction function getLanguage() { - // Do not try to figure out user's language; just show the page + // Don't try to figure out user's language; just show the page return common_config('site', 'language'); } function showPrimaryNav() { - // do not show primary nav + // don't show primary nav } } diff --git a/lib/error.php b/lib/error.php index 5ed5dec1b..3162cfe65 100644 --- a/lib/error.php +++ b/lib/error.php @@ -104,11 +104,11 @@ class ErrorAction extends Action { parent::showPage(); - // We do not want to have any more output after this + // We don't want to have any more output after this exit(); } - // Overload a bunch of stuff so the page is not too bloated + // Overload a bunch of stuff so the page isn't too bloated function showBody() { diff --git a/lib/htmloutputter.php b/lib/htmloutputter.php index 73bd9ce81..c2ec83c28 100644 --- a/lib/htmloutputter.php +++ b/lib/htmloutputter.php @@ -76,7 +76,7 @@ class HTMLOutputter extends XMLOutputter /** * Start an HTML document * - * If $type is not specified, will attempt to do content negotiation. + * If $type isn't specified, will attempt to do content negotiation. * * Attempts to do content negotiation for language, also. * diff --git a/lib/imagefile.php b/lib/imagefile.php index edc7218d0..cf1668f20 100644 --- a/lib/imagefile.php +++ b/lib/imagefile.php @@ -119,7 +119,7 @@ class ImageFile return; } - // Do not crop/scale if it is not necessary + // Don't crop/scale if it isn't necessary if ($size === $this->width && $size === $this->height && $x === 0 diff --git a/lib/jabber.php b/lib/jabber.php index d666fcbb3..73f2ec660 100644 --- a/lib/jabber.php +++ b/lib/jabber.php @@ -437,7 +437,7 @@ function jabber_public_notice($notice) $public = common_config('xmpp', 'public'); - // FIXME PRIV do not send out private messages here + // FIXME PRIV don't send out private messages here // XXX: should we send out non-local messages if public,localonly // = false? I think not diff --git a/lib/mail.php b/lib/mail.php index 79630b721..5218059e9 100644 --- a/lib/mail.php +++ b/lib/mail.php @@ -467,7 +467,7 @@ function mail_notify_nudge($from, $to) "these days and is inviting you to post some news.\n\n". "So let's hear from you :)\n\n". "%3\$s\n\n". - "Do not reply to this email. It will not get to them.\n\n". + "Don't reply to this email; it won't get to them.\n\n". "With kind regards,\n". "%4\$s\n"), $from_profile->getBestName(), @@ -516,7 +516,7 @@ function mail_notify_message($message, $from=null, $to=null) "------------------------------------------------------\n\n". "You can reply to their message here:\n\n". "%4\$s\n\n". - "Do not reply to this email. It will not get to them.\n\n". + "Don't reply to this email; it won't get to them.\n\n". "With kind regards,\n". "%5\$s\n"), $from_profile->getBestName(), @@ -532,7 +532,7 @@ function mail_notify_message($message, $from=null, $to=null) /** * notify a user that one of their notices has been chosen as a 'fave' * - * Does not check that the user has an email address nor if they + * Doesn't check that the user has an email address nor if they * want to receive notification of faves. Maybe this happens higher * up the stack...? * diff --git a/lib/noticelist.php b/lib/noticelist.php index 4e5623ded..bf12bb73c 100644 --- a/lib/noticelist.php +++ b/lib/noticelist.php @@ -347,7 +347,7 @@ class NoticeListItem extends Widget * show the link to the main page for the notice * * Displays a link to the page for a notice, with "relative" time. Tries to - * get remote notice URLs correct, but does not always succeed. + * get remote notice URLs correct, but doesn't always succeed. * * @return void */ @@ -483,7 +483,7 @@ class NoticeListItem extends Widget * show a link to reply to the current notice * * Should either do the reply in the current notice form (if available), or - * link out to the notice-posting form. A little flakey, does not always work. + * link out to the notice-posting form. A little flakey, doesn't always work. * * @return void */ diff --git a/lib/queuehandler.php b/lib/queuehandler.php index 7c07ca4f9..cd43b1e09 100644 --- a/lib/queuehandler.php +++ b/lib/queuehandler.php @@ -96,8 +96,8 @@ class QueueHandler extends Daemon * Initialization, run when the queue handler starts. * If this function indicates failure, the handler run will be aborted. * - * @fixme run() will abort if this does not return true, - * but some subclasses do not bother. + * @fixme run() will abort if this doesn't return true, + * but some subclasses don't bother. * @return boolean true on success, false on failure */ function start() @@ -108,8 +108,8 @@ class QueueHandler extends Daemon * Cleanup, run when the queue handler ends. * If this function indicates failure, a warning will be logged. * - * @fixme run() will throw warnings if this does not return true, - * but many subclasses do not bother. + * @fixme run() will throw warnings if this doesn't return true, + * but many subclasses don't bother. * @return boolean true on success, false on failure */ function finish() @@ -137,7 +137,7 @@ class QueueHandler extends Daemon * method, which passes control back to our handle_notice() method for * each notice that comes in on the queue. * - * Most of the time this will not need to be overridden in a subclass. + * Most of the time this won't need to be overridden in a subclass. * * @return boolean true on success, false on failure */ @@ -173,7 +173,7 @@ class QueueHandler extends Daemon * Called by QueueHandler after each handled item or empty polling cycle. * This is a good time to e.g. service your XMPP connection. * - * Does not need to be overridden if there's no maintenance to do. + * Doesn't need to be overridden if there's no maintenance to do. * * @param int $timeout seconds to sleep if there's nothing to do */ diff --git a/lib/rssaction.php b/lib/rssaction.php index 0e84a65e9..faf6bec7d 100644 --- a/lib/rssaction.php +++ b/lib/rssaction.php @@ -386,7 +386,7 @@ class Rss10Action extends Action return null; } - // FIXME: does not handle modified profiles, avatars, deleted notices + // FIXME: doesn't handle modified profiles, avatars, deleted notices return strtotime($this->notices[0]->created); } diff --git a/lib/search_engines.php b/lib/search_engines.php index 82713235c..69f6ff468 100644 --- a/lib/search_engines.php +++ b/lib/search_engines.php @@ -119,7 +119,7 @@ class MySQLSearch extends SearchEngine return true; } else if ('identica_notices' === $this->table) { - // Do not show imported notices + // Don't show imported notices $this->target->whereAdd('notice.is_local != ' . Notice::GATEWAY); if (strtolower($q) != $q) { diff --git a/lib/util.php b/lib/util.php index b4f5af1af..a4865c46c 100644 --- a/lib/util.php +++ b/lib/util.php @@ -62,7 +62,7 @@ function common_init_language() $locale_set = common_init_locale($language); setlocale(LC_CTYPE, 'C'); - // So we do not have to make people install the gettext locales + // So we don't have to make people install the gettext locales $path = common_config('site','locale_path'); bindtextdomain("statusnet", $path); bind_textdomain_codeset("statusnet", "UTF-8"); @@ -139,7 +139,7 @@ function common_check_user($nickname, $password) } } }else{ - //no handler indicated the credentials were valid, and we know their not valid because the user is not in the database + //no handler indicated the credentials were valid, and we know their not valid because the user isn't in the database return false; } } else { @@ -396,7 +396,7 @@ function common_current_user() } // Logins that are 'remembered' aren't 'real' -- they're subject to -// cookie-stealing. So, we do not let them do certain things. New reg, +// cookie-stealing. So, we don't let them do certain things. New reg, // OpenID, and password logins _are_ real. function common_real_login($real=true) @@ -1147,7 +1147,7 @@ function common_accept_to_prefs($accept, $def = '*/*') $parts = explode(',', $accept); foreach($parts as $part) { - // FIXME: does not deal with params like 'text/html; level=1' + // FIXME: doesn't deal with params like 'text/html; level=1' @list($value, $qpart) = explode(';', trim($part)); $match = array(); if(!isset($qpart)) { @@ -1346,7 +1346,7 @@ function common_error_handler($errno, $errstr, $errfile, $errline, $errcontext) } // FIXME: show error page if we're on the Web - /* Do not execute PHP internal error handler */ + /* Don't execute PHP internal error handler */ return true; } @@ -1448,7 +1448,7 @@ function common_shorten_url($long_url) } global $_shorteners; if (!isset($_shorteners[$svc])) { - //the user selected service does not exist, so default to ur1.ca + //the user selected service doesn't exist, so default to ur1.ca $svc = 'ur1.ca'; } if (!isset($_shorteners[$svc])) { diff --git a/lib/xmloutputter.php b/lib/xmloutputter.php index 9d862b2d0..5f06e491d 100644 --- a/lib/xmloutputter.php +++ b/lib/xmloutputter.php @@ -112,7 +112,7 @@ class XMLOutputter * * Utility for outputting an XML element. A convenient wrapper * for a bunch of longer XMLWriter calls. This is best for - * when an element does not have any sub-elements; if that's the + * when an element doesn't have any sub-elements; if that's the * case, use elementStart() and elementEnd() instead. * * The $content element will be escaped for XML. If you need diff --git a/lib/xmppqueuehandler.php b/lib/xmppqueuehandler.php index 7caa078ae..f28fc9088 100644 --- a/lib/xmppqueuehandler.php +++ b/lib/xmppqueuehandler.php @@ -37,7 +37,7 @@ class XmppQueueHandler extends QueueHandler function start() { - # Low priority; we do not want to receive messages + # Low priority; we don't want to receive messages $this->log(LOG_INFO, "INITIALIZE"); $this->conn = jabber_connect($this->_id.$this->transport()); diff --git a/plugins/Autocomplete/autocomplete.php b/plugins/Autocomplete/autocomplete.php index aeb100cfa..379390ffd 100644 --- a/plugins/Autocomplete/autocomplete.php +++ b/plugins/Autocomplete/autocomplete.php @@ -79,7 +79,7 @@ class AutocompleteAction extends Action function etag() { return '"' . implode(':', array($this->arg('action'), - crc32($this->arg('q')), //the actual string can have funny characters in we do not want showing up in the etag + crc32($this->arg('q')), //the actual string can have funny characters in we don't want showing up in the etag $this->arg('limit'), $this->lastModified())) . '"'; } diff --git a/plugins/BlogspamNetPlugin.php b/plugins/BlogspamNetPlugin.php index bf60fdcaf..51236001a 100644 --- a/plugins/BlogspamNetPlugin.php +++ b/plugins/BlogspamNetPlugin.php @@ -85,7 +85,7 @@ class BlogspamNetPlugin extends Plugin } else if (preg_match('/^SPAM(:(.*))?$/', $response, $match)) { throw new ClientException(sprintf(_("Spam checker results: %s"), $match[2]), 400); } else if (preg_match('/^OK$/', $response)) { - // do not do anything + // don't do anything } else { throw new ServerException(sprintf(_("Unexpected response from %s: %s"), $this->baseUrl, $response), 500); } diff --git a/plugins/Facebook/FBConnectAuth.php b/plugins/Facebook/FBConnectAuth.php index 165477419..b909a4977 100644 --- a/plugins/Facebook/FBConnectAuth.php +++ b/plugins/Facebook/FBConnectAuth.php @@ -71,7 +71,7 @@ class FBConnectauthAction extends Action 'There is already a local user (' . $flink->user_id . ') linked with this Facebook (' . $this->fbuid . ').'); - // We do not want these cookies + // We don't want these cookies getFacebook()->clear_cookie_state(); $this->clientError(_('There is already a local user linked with this Facebook.')); @@ -364,7 +364,7 @@ class FBConnectauthAction extends Action { $url = common_get_returnto(); if ($url) { - // We do not have to return to it again + // We don't have to return to it again common_set_returnto(null); } else { $url = common_local_url('all', diff --git a/plugins/Facebook/FacebookPlugin.php b/plugins/Facebook/FacebookPlugin.php index cd1ad7b45..b68534b24 100644 --- a/plugins/Facebook/FacebookPlugin.php +++ b/plugins/Facebook/FacebookPlugin.php @@ -182,7 +182,7 @@ class FacebookPlugin extends Plugin $login_url = common_local_url('FBConnectAuth'); $logout_url = common_local_url('logout'); - // XXX: Facebook says we do not need this FB_RequireFeatures(), + // XXX: Facebook says we don't need this FB_RequireFeatures(), // but we actually do, for IE and Safari. Gar. $js = '"; } else { diff --git a/plugins/Facebook/facebook/facebook_desktop.php b/plugins/Facebook/facebook/facebook_desktop.php index 425bb5c7b..e79a2ca34 100644 --- a/plugins/Facebook/facebook/facebook_desktop.php +++ b/plugins/Facebook/facebook/facebook_desktop.php @@ -93,7 +93,7 @@ class FacebookDesktop extends Facebook { } public function verify_signature($fb_params, $expected_sig) { - // we do not want to verify the signature until we have a valid + // we don't want to verify the signature until we have a valid // session secret if ($this->verify_sig) { return parent::verify_signature($fb_params, $expected_sig); diff --git a/plugins/Facebook/facebook/facebookapi_php5_restlib.php b/plugins/Facebook/facebook/facebookapi_php5_restlib.php index c742df748..55cb7fb86 100755 --- a/plugins/Facebook/facebook/facebookapi_php5_restlib.php +++ b/plugins/Facebook/facebook/facebookapi_php5_restlib.php @@ -46,7 +46,7 @@ class FacebookRestClient { // on canvas pages public $added; public $is_user; - // we do not pass friends list to iframes, but we want to make + // we don't pass friends list to iframes, but we want to make // friends_get really simple in the canvas_user (non-logged in) case. // So we use the canvas_user as default arg to friends_get public $canvas_user; @@ -657,7 +657,7 @@ function toggleDisplay(id, type) { * deleted. * * IMPORTANT: If your application has registered public tags - * that other applications may be using, do not delete those tags! + * that other applications may be using, don't delete those tags! * Doing so can break the FBML ofapplications that are using them. * * @param array $tag_names the names of the tags to delete (optinal) @@ -820,7 +820,7 @@ function toggleDisplay(id, type) { if (is_array($target_ids)) { $target_ids = json_encode($target_ids); - $target_ids = trim($target_ids, "[]"); // we do not want square brackets + $target_ids = trim($target_ids, "[]"); // we don't want square brackets } return $this->call_method('facebook.feed.publishUserAction', diff --git a/plugins/Facebook/facebook/jsonwrapper/jsonwrapper.php b/plugins/Facebook/facebook/jsonwrapper/jsonwrapper.php index 9c6c62663..29509deba 100644 --- a/plugins/Facebook/facebook/jsonwrapper/jsonwrapper.php +++ b/plugins/Facebook/facebook/jsonwrapper/jsonwrapper.php @@ -1,5 +1,5 @@ location_id = $n->geonameId; $location->location_ns = self::NAMESPACE; - // handled, do not continue processing! + // handled, don't continue processing! return false; } } - // Continue processing; we do not have the answer + // Continue processing; we don't have the answer return true; } @@ -217,7 +217,7 @@ class GeonamesPlugin extends Plugin } } - // For some reason we do not know, so pass. + // For some reason we don't know, so pass. return true; } @@ -299,7 +299,7 @@ class GeonamesPlugin extends Plugin $url = 'http://www.geonames.org/' . $location->location_id; - // it's been filled, so do not process further. + // it's been filled, so don't process further. return false; } } diff --git a/plugins/OpenID/finishopenidlogin.php b/plugins/OpenID/finishopenidlogin.php index b5d978294..ff0b451d3 100644 --- a/plugins/OpenID/finishopenidlogin.php +++ b/plugins/OpenID/finishopenidlogin.php @@ -341,7 +341,7 @@ class FinishopenidloginAction extends Action { $url = common_get_returnto(); if ($url) { - # We do not have to return to it again + # We don't have to return to it again common_set_returnto(null); } else { $url = common_local_url('all', @@ -421,7 +421,7 @@ class FinishopenidloginAction extends Action $parts = parse_url($openid); - # If any of these parts exist, this will not work + # If any of these parts exist, this won't work foreach ($bad as $badpart) { if (array_key_exists($badpart, $parts)) { diff --git a/plugins/OpenID/openid.php b/plugins/OpenID/openid.php index c5f6d1713..ff7a93899 100644 --- a/plugins/OpenID/openid.php +++ b/plugins/OpenID/openid.php @@ -187,7 +187,7 @@ function oid_authenticate($openid_url, $returnto, $immediate=false) $form_html = $auth_request->formMarkup($trust_root, $process_url, $immediate, array('id' => $form_id)); - # XXX: This is cheap, but things choke if we do not escape ampersands + # XXX: This is cheap, but things choke if we don't escape ampersands # in the HTML attributes $form_html = preg_replace('/&/', '&', $form_html); diff --git a/plugins/PiwikAnalyticsPlugin.php b/plugins/PiwikAnalyticsPlugin.php index 81ef7c683..54faa0bdb 100644 --- a/plugins/PiwikAnalyticsPlugin.php +++ b/plugins/PiwikAnalyticsPlugin.php @@ -44,7 +44,7 @@ if (!defined('STATUSNET')) { * 'piwikId' => 'id')); * * Replace 'example.com/piwik/' with the URL to your Piwik installation and - * make sure you do not forget the final /. + * make sure you don't forget the final /. * Replace 'id' with the ID your statusnet installation has in your Piwik * analytics setup - for example '8'. * diff --git a/plugins/Realtime/RealtimePlugin.php b/plugins/Realtime/RealtimePlugin.php index 88a87dcf9..0c7c1240c 100644 --- a/plugins/Realtime/RealtimePlugin.php +++ b/plugins/Realtime/RealtimePlugin.php @@ -240,7 +240,7 @@ class RealtimePlugin extends Plugin // FIXME: this code should be abstracted to a neutral third // party, like Notice::asJson(). I'm not sure of the ethics // of refactoring from within a plugin, so I'm just abusing - // the ApiAction method. Do not do this unless you're me! + // the ApiAction method. Don't do this unless you're me! require_once(INSTALLDIR.'/lib/api.php'); diff --git a/plugins/TwitterBridge/daemons/synctwitterfriends.php b/plugins/TwitterBridge/daemons/synctwitterfriends.php index c89c02eed..671e3c7af 100755 --- a/plugins/TwitterBridge/daemons/synctwitterfriends.php +++ b/plugins/TwitterBridge/daemons/synctwitterfriends.php @@ -115,7 +115,7 @@ class SyncTwitterFriendsDaemon extends ParallelizingDaemon // Each child ps needs its own DB connection // Note: DataObject::getDatabaseConnection() creates - // a new connection if there is not one already + // a new connection if there isn't one already $conn = &$flink->getDatabaseConnection(); diff --git a/plugins/TwitterBridge/daemons/twitterstatusfetcher.php b/plugins/TwitterBridge/daemons/twitterstatusfetcher.php index 25df0d839..b5428316b 100755 --- a/plugins/TwitterBridge/daemons/twitterstatusfetcher.php +++ b/plugins/TwitterBridge/daemons/twitterstatusfetcher.php @@ -136,7 +136,7 @@ class TwitterStatusFetcher extends ParallelizingDaemon // Each child ps needs its own DB connection // Note: DataObject::getDatabaseConnection() creates - // a new connection if there is not one already + // a new connection if there isn't one already $conn = &$flink->getDatabaseConnection(); @@ -499,7 +499,7 @@ class TwitterStatusFetcher extends ParallelizingDaemon $avatar->height = 73; } - $avatar->original = 0; // we do not have the original + $avatar->original = 0; // we don't have the original $avatar->mediatype = $mediatype; $avatar->filename = $filename; $avatar->url = Avatar::url($filename); diff --git a/plugins/TwitterBridge/twitter.php b/plugins/TwitterBridge/twitter.php index d48089caa..3c6803e49 100644 --- a/plugins/TwitterBridge/twitter.php +++ b/plugins/TwitterBridge/twitter.php @@ -33,7 +33,7 @@ function updateTwitter_user($twitter_id, $screen_name) $fuser->query('BEGIN'); - // Dropping down to SQL because regular DB_DataObject udpate stuff does not seem + // Dropping down to SQL because regular DB_DataObject udpate stuff doesn't seem // to work so good with tables that have multiple column primary keys // Any time we update the uri for a forein user we have to make sure there diff --git a/scripts/console.php b/scripts/console.php index 2a000d39b..41dd43f28 100755 --- a/scripts/console.php +++ b/scripts/console.php @@ -60,9 +60,9 @@ function read_input_line($prompt) } /** - * On Unix-like systems where PHP readline extension is not present, + * On Unix-like systems where PHP readline extension isn't present, * -cough- Mac OS X -cough- we can shell out to bash to do it for us. - * This lets us at least handle things like arrow keys, but we do not + * This lets us at least handle things like arrow keys, but we don't * get any entry history. :( * * Shamelessly ripped from when I wrote the same code for MediaWiki. :) diff --git a/scripts/maildaemon.php b/scripts/maildaemon.php index 4ec4526ef..b4e4d9f08 100755 --- a/scripts/maildaemon.php +++ b/scripts/maildaemon.php @@ -231,7 +231,7 @@ class MailerDaemon foreach ($parsed->parts as $part) { $this->extract_part($part,$msg,$attachments); } - //we do not want any attachments that are a result of this parsing + //we don't want any attachments that are a result of this parsing return $msg; } diff --git a/scripts/xmppconfirmhandler.php b/scripts/xmppconfirmhandler.php index f5f824dee..c7ed15e49 100755 --- a/scripts/xmppconfirmhandler.php +++ b/scripts/xmppconfirmhandler.php @@ -69,7 +69,7 @@ class XmppConfirmHandler extends XmppQueueHandler continue; } else { $this->log(LOG_INFO, 'Confirmation sent for ' . $confirm->address); - # Mark confirmation sent; need a dupe so we do not have the WHERE clause + # Mark confirmation sent; need a dupe so we don't have the WHERE clause $dupe = Confirm_address::staticGet('code', $confirm->code); if (!$dupe) { common_log(LOG_WARNING, 'Could not refetch confirm', __FILE__); -- cgit v1.2.3-54-g00ecf