From d3d499879c4d01bde46033a3a98f9190ea18cb63 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 16 Jun 2010 14:29:24 -0700 Subject: [PATCH 01/25] - More useful group info from api/statusnet/group/show - Add statusnet:group_info tag to group Atom feeds --- actions/showgroup.php | 10 +--------- classes/User_group.php | 15 ++++++++++++++ lib/apiaction.php | 40 ++++++++++++++++++++++++------------- lib/atomgroupnoticefeed.php | 19 ++++++++++++++++++ 4 files changed, 61 insertions(+), 23 deletions(-) diff --git a/actions/showgroup.php b/actions/showgroup.php index 3d369e9ebf..17c37e4d79 100644 --- a/actions/showgroup.php +++ b/actions/showgroup.php @@ -430,14 +430,6 @@ class ShowgroupAction extends GroupDesignAction function showStatistics() { - // XXX: WORM cache this - $members = $this->group->getMembers(); - $members_count = 0; - /** $member->count() doesn't work. */ - while ($members->fetch()) { - $members_count++; - } - $this->elementStart('div', array('id' => 'entity_statistics', 'class' => 'section')); @@ -451,7 +443,7 @@ class ShowgroupAction extends GroupDesignAction $this->elementStart('dl', 'entity_members'); $this->element('dt', null, _('Members')); - $this->element('dd', null, (is_int($members_count)) ? $members_count : '0'); + $this->element('dd', null, $this->group->getMemberCount()); $this->elementEnd('dl'); $this->elementEnd('div'); diff --git a/classes/User_group.php b/classes/User_group.php index 110f083012..e04c466266 100644 --- a/classes/User_group.php +++ b/classes/User_group.php @@ -154,6 +154,21 @@ class User_group extends Memcached_DataObject return $members; } + function getMemberCount() + { + // XXX: WORM cache this + + $members = $this->getMembers(); + $member_count = 0; + + /** $member->count() doesn't work. */ + while ($members->fetch()) { + $member_count++; + } + + return $member_count; + } + function getAdmins($offset=0, $limit=null) { $qry = diff --git a/lib/apiaction.php b/lib/apiaction.php index 320aa03160..7cc473d512 100644 --- a/lib/apiaction.php +++ b/lib/apiaction.php @@ -346,20 +346,32 @@ class ApiAction extends Action function twitterGroupArray($group) { - $twitter_group=array(); - $twitter_group['id']=$group->id; - $twitter_group['url']=$group->permalink(); - $twitter_group['nickname']=$group->nickname; - $twitter_group['fullname']=$group->fullname; - $twitter_group['original_logo']=$group->original_logo; - $twitter_group['homepage_logo']=$group->homepage_logo; - $twitter_group['stream_logo']=$group->stream_logo; - $twitter_group['mini_logo']=$group->mini_logo; - $twitter_group['homepage']=$group->homepage; - $twitter_group['description']=$group->description; - $twitter_group['location']=$group->location; - $twitter_group['created']=$this->dateTwitter($group->created); - $twitter_group['modified']=$this->dateTwitter($group->modified); + $twitter_group = array(); + + $twitter_group['id'] = $group->id; + $twitter_group['url'] = $group->permalink(); + $twitter_group['nickname'] = $group->nickname; + $twitter_group['fullname'] = $group->fullname; + + if (isset($this->auth_user)) { + $twitter_group['member'] = $this->auth_user->isMember($group); + $twitter_group['blocked'] = Group_block::isBlocked( + $group, + $this->auth_user->getProfile() + ); + } + + $twitter_group['member_count'] = $group->getMemberCount(); + $twitter_group['original_logo'] = $group->original_logo; + $twitter_group['homepage_logo'] = $group->homepage_logo; + $twitter_group['stream_logo'] = $group->stream_logo; + $twitter_group['mini_logo'] = $group->mini_logo; + $twitter_group['homepage'] = $group->homepage; + $twitter_group['description'] = $group->description; + $twitter_group['location'] = $group->location; + $twitter_group['created'] = $this->dateTwitter($group->created); + $twitter_group['modified'] = $this->dateTwitter($group->modified); + return $twitter_group; } diff --git a/lib/atomgroupnoticefeed.php b/lib/atomgroupnoticefeed.php index 7934a4f9e5..761df587ce 100644 --- a/lib/atomgroupnoticefeed.php +++ b/lib/atomgroupnoticefeed.php @@ -93,4 +93,23 @@ class AtomGroupNoticeFeed extends AtomNoticeFeed return $this->group; } + function initFeed() + { + parent::initFeed(); + + $attrs = array(); + + if (!empty($this->cur)) { + $attrs['member'] = $this->cur->isMember($this->group) + ? 'true' : 'false'; + $attrs['blocked'] = Group_block::isBlocked( + $this->group, + $this->cur->getProfile() + ) ? 'true' : 'false'; + } + + $attrs['member_count'] = $this->group->getMemberCount(); + + $this->element('statusnet:group_info', $attrs, null); + } } From a6ce4eef0df225dd863baf45d5615cbe22dcdea6 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 16 Jun 2010 18:27:51 -0700 Subject: [PATCH 02/25] Fix problem with AvatarLink in which it was sometimes leaving the width attribute empty --- lib/avatarlink.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/avatarlink.php b/lib/avatarlink.php index e67799e2eb..7d4256d6e1 100644 --- a/lib/avatarlink.php +++ b/lib/avatarlink.php @@ -76,8 +76,8 @@ class AvatarLink $alink = new AvatarLink(); $alink->url = $filename; $alink->height = $size; + $alink->width = $size; if (!empty($filename)) { - $alink->width = $size; $alink->type = self::mediatype($filename); } else { $alink->url = User_group::defaultLogo($size); From b66709215309126969104ad114874360785f3d57 Mon Sep 17 00:00:00 2001 From: James Walker Date: Thu, 17 Jun 2010 13:44:17 -0400 Subject: [PATCH 03/25] adding a Status_network::updateKeys() method, since DB_DataObject update doesn't do keys. --- classes/Status_network.php | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/classes/Status_network.php b/classes/Status_network.php index 4a1f2c3747..64016dd790 100644 --- a/classes/Status_network.php +++ b/classes/Status_network.php @@ -144,6 +144,35 @@ class Status_network extends Safe_DataObject return parent::update($orig); } + /** + * DB_DataObject doesn't allow updating keys (even non-primary) + */ + function updateKeys(&$orig) + { + $this->_connect(); + foreach (array('hostname', 'pathname') as $k) { + if (strcmp($this->$k, $orig->$k) != 0) { + $parts[] = $k . ' = ' . $this->_quote($this->$k); + } + } + if (count($parts) == 0) { + // No changes + return true; + } + + $toupdate = implode(', ', $parts); + + $table = common_database_tablename($this->tableName()); + $qry = 'UPDATE ' . $table . ' SET ' . $toupdate . + ' WHERE nickname = ' . $this->_quote($this->nickname); + $orig->decache(); + $result = $this->query($qry); + if ($result) { + $this->encache(); + } + return $result; + } + function delete() { $this->decache(); # while we still have the values! From 105c1a22d6513d9a5cb33d6134a6d60d423ee462 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 17 Jun 2010 23:08:40 +0000 Subject: [PATCH 04/25] Include source client's related URL (if any) in source attribution for Atom notice feeds --- classes/Notice.php | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/classes/Notice.php b/classes/Notice.php index 0838ca2a2c..f8eda5777d 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -1238,9 +1238,25 @@ class Notice extends Memcached_DataObject $xs->element('published', null, common_date_w3dtf($this->created)); $xs->element('updated', null, common_date_w3dtf($this->created)); + $source = null; + + $ns = $this->getSource(); + + if ($ns) { + if (!empty($ns->name) && !empty($ns->url)) { + $source = '' + . htmlspecialchars($ns->name) + . ''; + } else { + $source = $ns->code; + } + } + $noticeInfoAttr = array( - 'local_id' => $this->id, // local notice ID (useful to clients for ordering) - 'source' => $this->source, // the client name (source attribution) + 'local_id' => $this->id, // local notice ID (useful to clients for ordering) + 'source' => $source, // the client name (source attribution) ); $ns = $this->getSource(); @@ -1252,8 +1268,8 @@ class Notice extends Memcached_DataObject if (!empty($cur)) { $noticeInfoAttr['favorite'] = ($cur->hasFave($this)) ? "true" : "false"; - $profile = $cur->getProfile(); - $noticeInfoAttr['repeated'] = ($profile->hasRepeated($this->id)) ? "true" : "false"; + $profile = $cur->getProfile(); + $noticeInfoAttr['repeated'] = ($profile->hasRepeated($this->id)) ? "true" : "false"; } if (!empty($this->repeat_of)) { From 9d890e2be07364487cb3b333b49650b820dd7176 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Fri, 18 Jun 2010 09:59:11 -0700 Subject: [PATCH 05/25] Catch a couple of missing XML namespace declarations on API XML output. Missing NS declarations were breaking XML parsing for some clients since beaecb18d5b92b913473dfffd545dc436f50cf66 --- actions/apiaccountverifycredentials.php | 2 +- actions/apisubscriptions.php | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/actions/apiaccountverifycredentials.php b/actions/apiaccountverifycredentials.php index ea61a32059..79416e9b26 100644 --- a/actions/apiaccountverifycredentials.php +++ b/actions/apiaccountverifycredentials.php @@ -75,7 +75,7 @@ class ApiAccountVerifyCredentialsAction extends ApiAuthAction if ($this->format == 'xml') { $this->initDocument('xml'); - $this->showTwitterXmlUser($twitter_user); + $this->showTwitterXmlUser($twitter_user, 'user', true); $this->endDocument('xml'); } elseif ($this->format == 'json') { $this->initDocument('json'); diff --git a/actions/apisubscriptions.php b/actions/apisubscriptions.php index 0ba324057e..63d65f2893 100644 --- a/actions/apisubscriptions.php +++ b/actions/apisubscriptions.php @@ -206,7 +206,8 @@ class ApiSubscriptionsAction extends ApiBareAuthAction { switch ($this->format) { case 'xml': - $this->elementStart('users', array('type' => 'array')); + $this->elementStart('users', array('type' => 'array', + 'xmlns:statusnet' => 'http://status.net/schema/api/1/')); foreach ($this->profiles as $profile) { $this->showProfile( $profile, From 2e98a48f2b992c0a566689d3246880f6e81fbee3 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Sun, 20 Jun 2010 19:30:12 +0000 Subject: [PATCH 06/25] RecaptchaPlugin: fix for missing captcha on iPhone/Android. MobileProfile serves pages out to iPhone and Android as application/xhtml+xml, which doesn't work with the default we we were loading recaptcha (as it used document.write). Switched to filling out a
from the AJAX API, which doesn't use document.write in the XHTML context. Tested that view & submission works ok in following browsers: Mobile: iPhone 3.1, Android 2.1, iPad 3.2 (this last doesn't trigger mobile theme tweaks) Ubuntu 10.04: Firefox 3.6.3, Chrome 6 Mac 10.6: Safari 5/OS X 10.6.4 Windows 7: IE 8, Opera 10.56 --- plugins/Recaptcha/RecaptchaPlugin.php | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/plugins/Recaptcha/RecaptchaPlugin.php b/plugins/Recaptcha/RecaptchaPlugin.php index c585da43c4..f09d81ec00 100644 --- a/plugins/Recaptcha/RecaptchaPlugin.php +++ b/plugins/Recaptcha/RecaptchaPlugin.php @@ -62,12 +62,29 @@ class RecaptchaPlugin extends Plugin { $action->elementStart('li'); $action->raw(''); - if($this->checkssl() === true) { - $action->raw(recaptcha_get_html($this->public_key), null, true); - } else { - $action->raw(recaptcha_get_html($this->public_key)); - } + + // AJAX API will fill this div out. + // We're calling that instead of the regular one so we stay compatible + // with application/xml+xhtml output as for mobile. + $action->element('div', array('id' => 'recaptcha')); $action->elementEnd('li'); + + $action->recaptchaPluginNeedsOutput = true; + return true; + } + + function onEndShowScripts($action) + { + if (isset($action->recaptchaPluginNeedsOutput) && $action->recaptchaPluginNeedsOutput) { + // Load the AJAX API + $proto = $this->checkssl() ? 'https' : 'http'; + $url = "$proto://api.recaptcha.net/js/recaptcha_ajax.js"; + $action->script($url); + + // And when we're ready, fill out the captcha! + $key = json_encode($this->public_key); + $action->inlinescript("\$(function(){Recaptcha.create($key, 'recaptcha');});"); + } return true; } From 1852eae36f9ed9a57d37f2048dfbf2257c7eccb4 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Mon, 21 Jun 2010 08:07:12 -0700 Subject: [PATCH 07/25] quick-fix for localization typo per #2366 (also fixed upstream in translatewiki) --- locale/de/LC_MESSAGES/statusnet.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locale/de/LC_MESSAGES/statusnet.po b/locale/de/LC_MESSAGES/statusnet.po index eda01937ab..e453e80252 100644 --- a/locale/de/LC_MESSAGES/statusnet.po +++ b/locale/de/LC_MESSAGES/statusnet.po @@ -2620,7 +2620,7 @@ msgstr "Profil-Einstellungen ansehen" #: actions/othersettings.php:123 msgid "Show or hide profile designs." -msgstr "Prifil-Designs anzeigen oder verstecken." +msgstr "Profil-Designs anzeigen oder verstecken." #: actions/othersettings.php:153 msgid "URL shortening service is too long (max 50 chars)." From f31a6de311cfed99eb4cf27bd4ff3d0df27d5434 Mon Sep 17 00:00:00 2001 From: Siebrand Mazeland Date: Mon, 21 Jun 2010 20:10:37 +0200 Subject: [PATCH 08/25] Localisation updates from http://translatewiki.net --- locale/af/LC_MESSAGES/statusnet.po | 4 +- locale/ar/LC_MESSAGES/statusnet.po | 4 +- locale/arz/LC_MESSAGES/statusnet.po | 4 +- locale/bg/LC_MESSAGES/statusnet.po | 4 +- locale/br/LC_MESSAGES/statusnet.po | 4 +- locale/ca/LC_MESSAGES/statusnet.po | 33 +++-- locale/cs/LC_MESSAGES/statusnet.po | 4 +- locale/de/LC_MESSAGES/statusnet.po | 13 +- locale/el/LC_MESSAGES/statusnet.po | 4 +- locale/en_GB/LC_MESSAGES/statusnet.po | 4 +- locale/es/LC_MESSAGES/statusnet.po | 36 ++--- locale/fa/LC_MESSAGES/statusnet.po | 7 +- locale/fi/LC_MESSAGES/statusnet.po | 4 +- locale/fr/LC_MESSAGES/statusnet.po | 33 +++-- locale/ga/LC_MESSAGES/statusnet.po | 4 +- locale/gl/LC_MESSAGES/statusnet.po | 33 +++-- locale/he/LC_MESSAGES/statusnet.po | 4 +- locale/hsb/LC_MESSAGES/statusnet.po | 34 ++--- locale/ia/LC_MESSAGES/statusnet.po | 35 +++-- locale/is/LC_MESSAGES/statusnet.po | 4 +- locale/it/LC_MESSAGES/statusnet.po | 33 ++--- locale/ja/LC_MESSAGES/statusnet.po | 7 +- locale/ko/LC_MESSAGES/statusnet.po | 4 +- locale/mk/LC_MESSAGES/statusnet.po | 190 +++++++++++++------------- locale/nb/LC_MESSAGES/statusnet.po | 4 +- locale/nl/LC_MESSAGES/statusnet.po | 33 +++-- locale/nn/LC_MESSAGES/statusnet.po | 4 +- locale/pl/LC_MESSAGES/statusnet.po | 33 ++--- locale/pt/LC_MESSAGES/statusnet.po | 9 +- locale/pt_BR/LC_MESSAGES/statusnet.po | 13 +- locale/ru/LC_MESSAGES/statusnet.po | 36 ++--- locale/statusnet.pot | 2 +- locale/sv/LC_MESSAGES/statusnet.po | 4 +- locale/te/LC_MESSAGES/statusnet.po | 4 +- locale/tr/LC_MESSAGES/statusnet.po | 4 +- locale/uk/LC_MESSAGES/statusnet.po | 38 +++--- locale/vi/LC_MESSAGES/statusnet.po | 4 +- locale/zh_CN/LC_MESSAGES/statusnet.po | 4 +- locale/zh_TW/LC_MESSAGES/statusnet.po | 4 +- 39 files changed, 359 insertions(+), 343 deletions(-) diff --git a/locale/af/LC_MESSAGES/statusnet.po b/locale/af/LC_MESSAGES/statusnet.po index 8601961a1d..aa82c30f62 100644 --- a/locale/af/LC_MESSAGES/statusnet.po +++ b/locale/af/LC_MESSAGES/statusnet.po @@ -9,11 +9,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:18:33+0000\n" +"PO-Revision-Date: 2010-06-21 18:02:38+0000\n" "Language-Team: Afrikaans\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: af\n" "X-Message-Group: out-statusnet\n" diff --git a/locale/ar/LC_MESSAGES/statusnet.po b/locale/ar/LC_MESSAGES/statusnet.po index 9ce943fd63..3f9f582751 100644 --- a/locale/ar/LC_MESSAGES/statusnet.po +++ b/locale/ar/LC_MESSAGES/statusnet.po @@ -10,11 +10,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:18:37+0000\n" +"PO-Revision-Date: 2010-06-21 18:02:42+0000\n" "Language-Team: Arabic\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: ar\n" "X-Message-Group: out-statusnet\n" diff --git a/locale/arz/LC_MESSAGES/statusnet.po b/locale/arz/LC_MESSAGES/statusnet.po index a172687bcf..8fc6294537 100644 --- a/locale/arz/LC_MESSAGES/statusnet.po +++ b/locale/arz/LC_MESSAGES/statusnet.po @@ -11,11 +11,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:18:44+0000\n" +"PO-Revision-Date: 2010-06-21 18:02:48+0000\n" "Language-Team: Egyptian Spoken Arabic\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: arz\n" "X-Message-Group: out-statusnet\n" diff --git a/locale/bg/LC_MESSAGES/statusnet.po b/locale/bg/LC_MESSAGES/statusnet.po index c40c6b40a4..6f87d49bec 100644 --- a/locale/bg/LC_MESSAGES/statusnet.po +++ b/locale/bg/LC_MESSAGES/statusnet.po @@ -10,11 +10,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:18:49+0000\n" +"PO-Revision-Date: 2010-06-21 18:02:52+0000\n" "Language-Team: Bulgarian\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: bg\n" "X-Message-Group: out-statusnet\n" diff --git a/locale/br/LC_MESSAGES/statusnet.po b/locale/br/LC_MESSAGES/statusnet.po index fefd1b382b..0989677134 100644 --- a/locale/br/LC_MESSAGES/statusnet.po +++ b/locale/br/LC_MESSAGES/statusnet.po @@ -10,11 +10,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:18:54+0000\n" +"PO-Revision-Date: 2010-06-21 18:02:56+0000\n" "Language-Team: Dutch\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: br\n" "X-Message-Group: out-statusnet\n" diff --git a/locale/ca/LC_MESSAGES/statusnet.po b/locale/ca/LC_MESSAGES/statusnet.po index 79ea768e04..2b5a2076d7 100644 --- a/locale/ca/LC_MESSAGES/statusnet.po +++ b/locale/ca/LC_MESSAGES/statusnet.po @@ -11,11 +11,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:18:58+0000\n" +"PO-Revision-Date: 2010-06-21 18:03:01+0000\n" "Language-Team: Catalan\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: ca\n" "X-Message-Group: out-statusnet\n" @@ -1135,13 +1135,12 @@ msgid "Theme for the site." msgstr "Tema del lloc." #: actions/designadminpanel.php:467 -#, fuzzy msgid "Custom theme" -msgstr "Tema del lloc" +msgstr "Tema personalitzat" #: actions/designadminpanel.php:471 msgid "You can upload a custom StatusNet theme as a .ZIP archive." -msgstr "" +msgstr "Podeu pujar un tema personalitzat de l'StatusNet amb un arxiu ZIP." #: actions/designadminpanel.php:486 lib/designsettings.php:101 msgid "Change background image" @@ -1200,11 +1199,11 @@ msgstr "Enllaços" #: actions/designadminpanel.php:651 msgid "Advanced" -msgstr "" +msgstr "Avançat" #: actions/designadminpanel.php:655 msgid "Custom CSS" -msgstr "" +msgstr "CSS personalitzat" #: actions/designadminpanel.php:676 lib/designsettings.php:247 msgid "Use defaults" @@ -6876,48 +6875,48 @@ msgstr "Cap" #: lib/themeuploader.php:50 msgid "This server cannot handle theme uploads without ZIP support." -msgstr "" +msgstr "El servidor no pot gestionar la pujada de temes si no pot tractar ZIP." #: lib/themeuploader.php:58 lib/themeuploader.php:61 -#, fuzzy msgid "Theme upload missing or failed." -msgstr "Error del sistema en pujar el fitxer." +msgstr "La pujada del tema ha fallat o no hi és." #: lib/themeuploader.php:91 lib/themeuploader.php:102 #: lib/themeuploader.php:253 lib/themeuploader.php:257 #: lib/themeuploader.php:265 lib/themeuploader.php:272 -#, fuzzy msgid "Failed saving theme." -msgstr "Error en actualitzar avatar." +msgstr "Ha fallat el desament del tema." #: lib/themeuploader.php:139 msgid "Invalid theme: bad directory structure." -msgstr "" +msgstr "El tema no és vàlid: l'estructura del directori no és correcta" #: lib/themeuploader.php:166 #, php-format msgid "Uploaded theme is too large; must be less than %d bytes uncompressed." msgstr "" +"El tema pujat és massa gran; ha de tenir menys de %d bytes descomprimit." #: lib/themeuploader.php:178 msgid "Invalid theme archive: missing file css/display.css" -msgstr "" +msgstr "L'arxiu del tema no és vàlid: manca el fitxer de css / display.css" #: lib/themeuploader.php:205 msgid "" "Theme contains invalid file or folder name. Stick with ASCII letters, " "digits, underscore, and minus sign." msgstr "" +"El tema conté un fitxer o un nom de carpeta que no és vàlida. Feu servir " +"només lletres ASCII, dígits, caràcters de subratllat i el símbol de menys." #: lib/themeuploader.php:216 #, php-format msgid "Theme contains file of type '.%s', which is not allowed." -msgstr "" +msgstr "El tema conté un tipus de fitxer «.%s», que no està permès." #: lib/themeuploader.php:234 -#, fuzzy msgid "Error opening theme archive." -msgstr "S'ha produït un error en actualitzar el perfil remot." +msgstr "S'ha produït un error en obrir l'arxiu del tema." #: lib/topposterssection.php:74 msgid "Top posters" diff --git a/locale/cs/LC_MESSAGES/statusnet.po b/locale/cs/LC_MESSAGES/statusnet.po index 63162ccc28..f9bd7ded92 100644 --- a/locale/cs/LC_MESSAGES/statusnet.po +++ b/locale/cs/LC_MESSAGES/statusnet.po @@ -10,11 +10,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:19:03+0000\n" +"PO-Revision-Date: 2010-06-21 18:03:06+0000\n" "Language-Team: Czech\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: cs\n" "X-Message-Group: out-statusnet\n" diff --git a/locale/de/LC_MESSAGES/statusnet.po b/locale/de/LC_MESSAGES/statusnet.po index d5598d9652..3f16402f20 100644 --- a/locale/de/LC_MESSAGES/statusnet.po +++ b/locale/de/LC_MESSAGES/statusnet.po @@ -1,6 +1,7 @@ # Translation of StatusNet to German # # Author@translatewiki.net: Bavatar +# Author@translatewiki.net: Brion # Author@translatewiki.net: Lutzgh # Author@translatewiki.net: March # Author@translatewiki.net: McDutchie @@ -17,11 +18,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:19:08+0000\n" +"PO-Revision-Date: 2010-06-21 18:03:12+0000\n" "Language-Team: German\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: de\n" "X-Message-Group: out-statusnet\n" @@ -706,7 +707,7 @@ msgstr "%1$s / Aktualisierungen erwähnen %2$s" #: actions/apitimelinementions.php:131 #, php-format msgid "%1$s updates that reply to updates from %2$s / %3$s." -msgstr "Nachrichten von %1$, die auf Nachrichten von %2$ / %3$ antworten." +msgstr "Nachrichten von %1$s, die auf Nachrichten von %2$s / %3$s antworten." #: actions/apitimelinepublic.php:197 actions/publicrss.php:103 #, php-format @@ -1208,11 +1209,11 @@ msgstr "Links" #: actions/designadminpanel.php:651 msgid "Advanced" -msgstr "" +msgstr "Erweitert" #: actions/designadminpanel.php:655 msgid "Custom CSS" -msgstr "" +msgstr "Eigene CSS" #: actions/designadminpanel.php:676 lib/designsettings.php:247 msgid "Use defaults" @@ -2638,7 +2639,7 @@ msgstr "Profil-Einstellungen ansehen" #: actions/othersettings.php:123 msgid "Show or hide profile designs." -msgstr "Prifil-Designs anzeigen oder verstecken." +msgstr "Profil-Designs anzeigen oder verstecken." #: actions/othersettings.php:153 msgid "URL shortening service is too long (max 50 chars)." diff --git a/locale/el/LC_MESSAGES/statusnet.po b/locale/el/LC_MESSAGES/statusnet.po index b4d3dda98b..803c3b34b4 100644 --- a/locale/el/LC_MESSAGES/statusnet.po +++ b/locale/el/LC_MESSAGES/statusnet.po @@ -11,11 +11,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:19:12+0000\n" +"PO-Revision-Date: 2010-06-21 18:03:17+0000\n" "Language-Team: Greek\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: el\n" "X-Message-Group: out-statusnet\n" diff --git a/locale/en_GB/LC_MESSAGES/statusnet.po b/locale/en_GB/LC_MESSAGES/statusnet.po index dd815ca40a..96dc69be6f 100644 --- a/locale/en_GB/LC_MESSAGES/statusnet.po +++ b/locale/en_GB/LC_MESSAGES/statusnet.po @@ -12,11 +12,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:19:18+0000\n" +"PO-Revision-Date: 2010-06-21 18:03:21+0000\n" "Language-Team: British English\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: en-gb\n" "X-Message-Group: out-statusnet\n" diff --git a/locale/es/LC_MESSAGES/statusnet.po b/locale/es/LC_MESSAGES/statusnet.po index abaab83fc0..56f866af8c 100644 --- a/locale/es/LC_MESSAGES/statusnet.po +++ b/locale/es/LC_MESSAGES/statusnet.po @@ -1,5 +1,6 @@ # Translation of StatusNet to Spanish # +# Author@translatewiki.net: Brion # Author@translatewiki.net: Crazymadlover # Author@translatewiki.net: Locos epraix # Author@translatewiki.net: McDutchie @@ -15,11 +16,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:19:22+0000\n" +"PO-Revision-Date: 2010-06-21 18:03:25+0000\n" "Language-Team: Spanish\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: es\n" "X-Message-Group: out-statusnet\n" @@ -1135,13 +1136,12 @@ msgid "Theme for the site." msgstr "Tema para el sitio." #: actions/designadminpanel.php:467 -#, fuzzy msgid "Custom theme" -msgstr "Tema del sitio" +msgstr "Personalizar tema" #: actions/designadminpanel.php:471 msgid "You can upload a custom StatusNet theme as a .ZIP archive." -msgstr "" +msgstr "Puedes subir un tema personalizado StatusNet como un archivo .ZIP." #: actions/designadminpanel.php:486 lib/designsettings.php:101 msgid "Change background image" @@ -1201,11 +1201,11 @@ msgstr "Vínculos" #: actions/designadminpanel.php:651 msgid "Advanced" -msgstr "" +msgstr "Avanzado" #: actions/designadminpanel.php:655 msgid "Custom CSS" -msgstr "" +msgstr "Personalizar CSS" #: actions/designadminpanel.php:676 lib/designsettings.php:247 msgid "Use defaults" @@ -1640,7 +1640,7 @@ msgstr "Avisos favoritos de %s" #: actions/favoritesrss.php:115 #, php-format msgid "Updates favored by %1$s on %2$s!" -msgstr "¡Actualizaciones favorecidas por %1$ s en %2$s!" +msgstr "¡Actualizaciones favorecidas por %1$s en %2$s!" #: actions/featured.php:69 lib/featureduserssection.php:87 #: lib/publicgroupnav.php:89 @@ -6885,48 +6885,48 @@ msgstr "Ninguno" #: lib/themeuploader.php:50 msgid "This server cannot handle theme uploads without ZIP support." -msgstr "" +msgstr "Este servidor no puede manejar cargas de temas sin soporte ZIP." #: lib/themeuploader.php:58 lib/themeuploader.php:61 -#, fuzzy msgid "Theme upload missing or failed." -msgstr "Error del sistema subir el archivo" +msgstr "Sudida del tema perdido o errado." #: lib/themeuploader.php:91 lib/themeuploader.php:102 #: lib/themeuploader.php:253 lib/themeuploader.php:257 #: lib/themeuploader.php:265 lib/themeuploader.php:272 -#, fuzzy msgid "Failed saving theme." -msgstr "Error al actualizar la imagen." +msgstr "Grabado de tema errado." #: lib/themeuploader.php:139 msgid "Invalid theme: bad directory structure." -msgstr "" +msgstr "Tema inválido: mala estructura de directorio." #: lib/themeuploader.php:166 #, php-format msgid "Uploaded theme is too large; must be less than %d bytes uncompressed." msgstr "" +"Tema subido es demasiado grande; debe ser menor que %d bytes sin comprimir." #: lib/themeuploader.php:178 msgid "Invalid theme archive: missing file css/display.css" -msgstr "" +msgstr "Archivo de tema inválido: archivo perdido css/display.css" #: lib/themeuploader.php:205 msgid "" "Theme contains invalid file or folder name. Stick with ASCII letters, " "digits, underscore, and minus sign." msgstr "" +"El tema contiene archivo o nombre de carpeta inválido. Restrínjase a letras " +"ASCII, dígitos, carácter de subrayado, y signo menos." #: lib/themeuploader.php:216 #, php-format msgid "Theme contains file of type '.%s', which is not allowed." -msgstr "" +msgstr "El tema contiene archivo de tipo '.%s', que no está permitido." #: lib/themeuploader.php:234 -#, fuzzy msgid "Error opening theme archive." -msgstr "Error al actualizar el perfil remoto." +msgstr "Error al abrir archivo de tema." #: lib/topposterssection.php:74 msgid "Top posters" diff --git a/locale/fa/LC_MESSAGES/statusnet.po b/locale/fa/LC_MESSAGES/statusnet.po index 6115c832ba..22997fc917 100644 --- a/locale/fa/LC_MESSAGES/statusnet.po +++ b/locale/fa/LC_MESSAGES/statusnet.po @@ -1,6 +1,7 @@ # Translation of StatusNet to Persian # # Author@translatewiki.net: ArianHT +# Author@translatewiki.net: Brion # Author@translatewiki.net: Choxos # Author@translatewiki.net: Everplays # Author@translatewiki.net: Narcissus @@ -12,7 +13,7 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:19:31+0000\n" +"PO-Revision-Date: 2010-06-21 18:03:35+0000\n" "Last-Translator: Ahmad Sufi Mahmudi\n" "Language-Team: Persian\n" "MIME-Version: 1.0\n" @@ -21,7 +22,7 @@ msgstr "" "X-Language-Code: fa\n" "X-Message-Group: out-statusnet\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" #. TRANS: Page title @@ -197,7 +198,7 @@ msgstr "شما و دوستان" #: actions/apitimelinehome.php:122 #, php-format msgid "Updates from %1$s and friends on %2$s!" -msgstr "به روز رسانی از %1$ و دوستان در %2$" +msgstr "به روز رسانی از %1$s و دوستان در %2$s" #: actions/apiaccountratelimitstatus.php:72 #: actions/apiaccountupdatedeliverydevice.php:94 diff --git a/locale/fi/LC_MESSAGES/statusnet.po b/locale/fi/LC_MESSAGES/statusnet.po index dccd62a1b0..2b5f91e410 100644 --- a/locale/fi/LC_MESSAGES/statusnet.po +++ b/locale/fi/LC_MESSAGES/statusnet.po @@ -11,11 +11,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:19:27+0000\n" +"PO-Revision-Date: 2010-06-21 18:03:30+0000\n" "Language-Team: Finnish\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: fi\n" "X-Message-Group: out-statusnet\n" diff --git a/locale/fr/LC_MESSAGES/statusnet.po b/locale/fr/LC_MESSAGES/statusnet.po index cfa141165e..5adb8b3607 100644 --- a/locale/fr/LC_MESSAGES/statusnet.po +++ b/locale/fr/LC_MESSAGES/statusnet.po @@ -16,11 +16,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:19:36+0000\n" +"PO-Revision-Date: 2010-06-21 18:03:40+0000\n" "Language-Team: French\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: fr\n" "X-Message-Group: out-statusnet\n" @@ -1144,13 +1144,13 @@ msgid "Theme for the site." msgstr "Thème pour le site." #: actions/designadminpanel.php:467 -#, fuzzy msgid "Custom theme" -msgstr "Thème du site" +msgstr "Thème personnalisé" #: actions/designadminpanel.php:471 msgid "You can upload a custom StatusNet theme as a .ZIP archive." msgstr "" +"Vous pouvez importer un thème StatusNet personnalisé dans une archive .ZIP." #: actions/designadminpanel.php:486 lib/designsettings.php:101 msgid "Change background image" @@ -1210,11 +1210,11 @@ msgstr "Liens" #: actions/designadminpanel.php:651 msgid "Advanced" -msgstr "" +msgstr "Avancé" #: actions/designadminpanel.php:655 msgid "Custom CSS" -msgstr "" +msgstr "CSS personnalisé" #: actions/designadminpanel.php:676 lib/designsettings.php:247 msgid "Use defaults" @@ -6919,47 +6919,50 @@ msgstr "Aucun" #: lib/themeuploader.php:50 msgid "This server cannot handle theme uploads without ZIP support." msgstr "" +"Le serveur ne peut pas gérer l’import de thèmes sans le support du format " +"ZIP." #: lib/themeuploader.php:58 lib/themeuploader.php:61 -#, fuzzy msgid "Theme upload missing or failed." -msgstr "Erreur système lors du transfert du fichier." +msgstr "Le thème est manquant ou son import a échoué." #: lib/themeuploader.php:91 lib/themeuploader.php:102 #: lib/themeuploader.php:253 lib/themeuploader.php:257 #: lib/themeuploader.php:265 lib/themeuploader.php:272 -#, fuzzy msgid "Failed saving theme." -msgstr "La mise à jour de l’avatar a échoué." +msgstr "L’enregistrement du thème a échoué." #: lib/themeuploader.php:139 msgid "Invalid theme: bad directory structure." -msgstr "" +msgstr "Thème invalide : mauvaise arborescence." #: lib/themeuploader.php:166 #, php-format msgid "Uploaded theme is too large; must be less than %d bytes uncompressed." msgstr "" +"Le thème importé est trop volumineux. Non compressé, il doit occuper moins " +"de %d octets." #: lib/themeuploader.php:178 msgid "Invalid theme archive: missing file css/display.css" -msgstr "" +msgstr "Archive de thème invalide : fichier css/display.css manquant" #: lib/themeuploader.php:205 msgid "" "Theme contains invalid file or folder name. Stick with ASCII letters, " "digits, underscore, and minus sign." msgstr "" +"Le thème contient un nom de fichier ou de dossier invalide. Limitez-vous aux " +"lettres ASCII et aux chiffres, caractère de soulignement et signe moins." #: lib/themeuploader.php:216 #, php-format msgid "Theme contains file of type '.%s', which is not allowed." -msgstr "" +msgstr "Le thème contient un fichier de type « .%s », qui n'est pas autorisé." #: lib/themeuploader.php:234 -#, fuzzy msgid "Error opening theme archive." -msgstr "Erreur lors de la mise à jour du profil distant." +msgstr "Erreur lors de l’ouverture de l’archive du thème." #: lib/topposterssection.php:74 msgid "Top posters" diff --git a/locale/ga/LC_MESSAGES/statusnet.po b/locale/ga/LC_MESSAGES/statusnet.po index 58ed21473d..ac7ad1b5f6 100644 --- a/locale/ga/LC_MESSAGES/statusnet.po +++ b/locale/ga/LC_MESSAGES/statusnet.po @@ -9,11 +9,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:19:40+0000\n" +"PO-Revision-Date: 2010-06-21 18:03:45+0000\n" "Language-Team: Irish\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: ga\n" "X-Message-Group: out-statusnet\n" diff --git a/locale/gl/LC_MESSAGES/statusnet.po b/locale/gl/LC_MESSAGES/statusnet.po index c505db01cb..14cbd03c7d 100644 --- a/locale/gl/LC_MESSAGES/statusnet.po +++ b/locale/gl/LC_MESSAGES/statusnet.po @@ -10,11 +10,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:19:45+0000\n" +"PO-Revision-Date: 2010-06-21 18:03:49+0000\n" "Language-Team: Galician\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: gl\n" "X-Message-Group: out-statusnet\n" @@ -1132,13 +1132,13 @@ msgid "Theme for the site." msgstr "Tema visual para o sitio." #: actions/designadminpanel.php:467 -#, fuzzy msgid "Custom theme" -msgstr "Tema visual do sitio" +msgstr "Tema visual personalizado" #: actions/designadminpanel.php:471 msgid "You can upload a custom StatusNet theme as a .ZIP archive." msgstr "" +"Pode cargar como arquivo .ZIP un tema visual personalizado para StatusNet" #: actions/designadminpanel.php:486 lib/designsettings.php:101 msgid "Change background image" @@ -1198,11 +1198,11 @@ msgstr "Ligazóns" #: actions/designadminpanel.php:651 msgid "Advanced" -msgstr "" +msgstr "Avanzado" #: actions/designadminpanel.php:655 msgid "Custom CSS" -msgstr "" +msgstr "CSS personalizado" #: actions/designadminpanel.php:676 lib/designsettings.php:247 msgid "Use defaults" @@ -6878,47 +6878,50 @@ msgstr "Ningún" #: lib/themeuploader.php:50 msgid "This server cannot handle theme uploads without ZIP support." msgstr "" +"O servidor non pode xestionar as cargas de temas visuais sen soporte para o " +"formato ZIP." #: lib/themeuploader.php:58 lib/themeuploader.php:61 -#, fuzzy msgid "Theme upload missing or failed." -msgstr "Houbo un erro no sistema ao cargar o ficheiro." +msgstr "Houbo un erro no sistema ao cargar o tema visual." #: lib/themeuploader.php:91 lib/themeuploader.php:102 #: lib/themeuploader.php:253 lib/themeuploader.php:257 #: lib/themeuploader.php:265 lib/themeuploader.php:272 -#, fuzzy msgid "Failed saving theme." -msgstr "Non se puido actualizar o avatar." +msgstr "Non se puido gardar o tema visual." #: lib/themeuploader.php:139 msgid "Invalid theme: bad directory structure." -msgstr "" +msgstr "Tema visual inválido: a estrutura do directorio é incorrecta" #: lib/themeuploader.php:166 #, php-format msgid "Uploaded theme is too large; must be less than %d bytes uncompressed." msgstr "" +"O tema visual cargado é grande de máis; o tamaño descomprimido non pode " +"superar os %d bytes." #: lib/themeuploader.php:178 msgid "Invalid theme archive: missing file css/display.css" -msgstr "" +msgstr "Arquivo de tema visual inválido: falta o ficheiro css/display.css" #: lib/themeuploader.php:205 msgid "" "Theme contains invalid file or folder name. Stick with ASCII letters, " "digits, underscore, and minus sign." msgstr "" +"O tema visual contén un ficheiro inválido ou nome de cartafol incorrecto. " +"Limíteo a letras ASCII, díxitos, barras baixas e signos menos." #: lib/themeuploader.php:216 #, php-format msgid "Theme contains file of type '.%s', which is not allowed." -msgstr "" +msgstr "O tema visual contén o tipo de ficheiro \".%s\". Non está permitido." #: lib/themeuploader.php:234 -#, fuzzy msgid "Error opening theme archive." -msgstr "Houbo un erro ao actualizar o perfil remoto." +msgstr "Houbo un erro ao abrir o arquivo do tema visual." #: lib/topposterssection.php:74 msgid "Top posters" diff --git a/locale/he/LC_MESSAGES/statusnet.po b/locale/he/LC_MESSAGES/statusnet.po index fe5c02d482..d1b13a29ad 100644 --- a/locale/he/LC_MESSAGES/statusnet.po +++ b/locale/he/LC_MESSAGES/statusnet.po @@ -8,11 +8,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:19:49+0000\n" +"PO-Revision-Date: 2010-06-21 18:03:54+0000\n" "Language-Team: Hebrew\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: he\n" "X-Message-Group: out-statusnet\n" diff --git a/locale/hsb/LC_MESSAGES/statusnet.po b/locale/hsb/LC_MESSAGES/statusnet.po index 0555459d1c..1c5781d511 100644 --- a/locale/hsb/LC_MESSAGES/statusnet.po +++ b/locale/hsb/LC_MESSAGES/statusnet.po @@ -10,11 +10,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:19:54+0000\n" +"PO-Revision-Date: 2010-06-21 18:03:58+0000\n" "Language-Team: Dutch\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: hsb\n" "X-Message-Group: out-statusnet\n" @@ -1099,9 +1099,8 @@ msgid "Theme for the site." msgstr "Šat za sydło." #: actions/designadminpanel.php:467 -#, fuzzy msgid "Custom theme" -msgstr "Šat sydła" +msgstr "Swójski šat" #: actions/designadminpanel.php:471 msgid "You can upload a custom StatusNet theme as a .ZIP archive." @@ -1164,11 +1163,11 @@ msgstr "Wotkazy" #: actions/designadminpanel.php:651 msgid "Advanced" -msgstr "" +msgstr "Rozšěrjeny" #: actions/designadminpanel.php:655 msgid "Custom CSS" -msgstr "" +msgstr "Swójski CSS" #: actions/designadminpanel.php:676 lib/designsettings.php:247 msgid "Use defaults" @@ -1423,7 +1422,7 @@ msgstr "" #. TRANS: Checkbox label in e-mail preferences form. #: actions/emailsettings.php:193 msgid "Send me email when someone sends me a private message." -msgstr "" +msgstr "E-mejl pósłać, hdyž něchtó priwatnu powěsć sćele." #. TRANS: Checkbox label in e-mail preferences form. #: actions/emailsettings.php:199 @@ -1594,12 +1593,12 @@ msgstr "" #: actions/featured.php:69 lib/featureduserssection.php:87 #: lib/publicgroupnav.php:89 msgid "Featured users" -msgstr "" +msgstr "Nazhonići wužiwarjo" #: actions/featured.php:71 #, php-format msgid "Featured users, page %d" -msgstr "" +msgstr "Nazhonići wužiwarjo, strona %d" #: actions/featured.php:99 #, php-format @@ -3053,7 +3052,7 @@ msgstr "Sy so identifikował. Zapodaj deleka nowe hesło. " #: actions/recoverpassword.php:188 msgid "Password recovery" -msgstr "" +msgstr "Wobnowjenje hesła" #: actions/recoverpassword.php:191 msgid "Nickname or email address" @@ -3066,7 +3065,7 @@ msgstr "" #: actions/recoverpassword.php:199 actions/recoverpassword.php:200 msgid "Recover" -msgstr "" +msgstr "Wobnowić" #: actions/recoverpassword.php:208 msgid "Reset password" @@ -3074,11 +3073,11 @@ msgstr "Hesło wróćo stajić" #: actions/recoverpassword.php:209 msgid "Recover password" -msgstr "" +msgstr "Hesło wobnowić" #: actions/recoverpassword.php:210 actions/recoverpassword.php:335 msgid "Password recovery requested" -msgstr "" +msgstr "Wobnowjenje hesła požadane" #: actions/recoverpassword.php:213 msgid "Unknown action" @@ -6439,16 +6438,14 @@ msgid "This server cannot handle theme uploads without ZIP support." msgstr "" #: lib/themeuploader.php:58 lib/themeuploader.php:61 -#, fuzzy msgid "Theme upload missing or failed." -msgstr "Systemowy zmylk při nahrawanju dataje." +msgstr "Nahraće šata faluje abo je so njeporadźiło." #: lib/themeuploader.php:91 lib/themeuploader.php:102 #: lib/themeuploader.php:253 lib/themeuploader.php:257 #: lib/themeuploader.php:265 lib/themeuploader.php:272 -#, fuzzy msgid "Failed saving theme." -msgstr "Aktualizowanje awatara je so njeporadźiło." +msgstr "Składowanje šata je so njeporadźiło." #: lib/themeuploader.php:139 msgid "Invalid theme: bad directory structure." @@ -6475,9 +6472,8 @@ msgid "Theme contains file of type '.%s', which is not allowed." msgstr "" #: lib/themeuploader.php:234 -#, fuzzy msgid "Error opening theme archive." -msgstr "Zmylk při aktualizaciji zdaleneho profila." +msgstr "Zmylk při wočinjenju šatoweho archiwa." #: lib/topposterssection.php:74 msgid "Top posters" diff --git a/locale/ia/LC_MESSAGES/statusnet.po b/locale/ia/LC_MESSAGES/statusnet.po index 46f4b37462..cc699cef48 100644 --- a/locale/ia/LC_MESSAGES/statusnet.po +++ b/locale/ia/LC_MESSAGES/statusnet.po @@ -9,11 +9,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:20:00+0000\n" +"PO-Revision-Date: 2010-06-21 18:04:03+0000\n" "Language-Team: Interlingua\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: ia\n" "X-Message-Group: out-statusnet\n" @@ -1129,13 +1129,14 @@ msgid "Theme for the site." msgstr "Le thema de apparentia pro le sito." #: actions/designadminpanel.php:467 -#, fuzzy msgid "Custom theme" -msgstr "Thema del sito" +msgstr "Apparentia personalisate" #: actions/designadminpanel.php:471 msgid "You can upload a custom StatusNet theme as a .ZIP archive." msgstr "" +"Es possibile incargar un apparentia personalisate de StatusNet in un " +"archivo .ZIP." #: actions/designadminpanel.php:486 lib/designsettings.php:101 msgid "Change background image" @@ -1195,11 +1196,11 @@ msgstr "Ligamines" #: actions/designadminpanel.php:651 msgid "Advanced" -msgstr "" +msgstr "Avantiate" #: actions/designadminpanel.php:655 msgid "Custom CSS" -msgstr "" +msgstr "CSS personalisate" #: actions/designadminpanel.php:676 lib/designsettings.php:247 msgid "Use defaults" @@ -4613,7 +4614,7 @@ msgstr "Acceptar" #: actions/userauthorization.php:218 lib/subscribeform.php:115 #: lib/subscribeform.php:139 msgid "Subscribe to this user" -msgstr "Subscriber me a iste usator" +msgstr "Subscriber a iste usator" #: actions/userauthorization.php:219 msgid "Reject" @@ -6848,47 +6849,51 @@ msgstr "Nulle" #: lib/themeuploader.php:50 msgid "This server cannot handle theme uploads without ZIP support." msgstr "" +"Iste servitor non pote manear le incargamento de apparentias sin supporto de " +"ZIP." #: lib/themeuploader.php:58 lib/themeuploader.php:61 -#, fuzzy msgid "Theme upload missing or failed." -msgstr "Error de systema durante le incargamento del file." +msgstr "Le file del apparentia manca o le incargamento ha fallite." #: lib/themeuploader.php:91 lib/themeuploader.php:102 #: lib/themeuploader.php:253 lib/themeuploader.php:257 #: lib/themeuploader.php:265 lib/themeuploader.php:272 -#, fuzzy msgid "Failed saving theme." -msgstr "Actualisation del avatar fallite." +msgstr "Salveguarda del apparentia fallite." #: lib/themeuploader.php:139 msgid "Invalid theme: bad directory structure." -msgstr "" +msgstr "Apparentia invalide: mal structura de directorios." #: lib/themeuploader.php:166 #, php-format msgid "Uploaded theme is too large; must be less than %d bytes uncompressed." msgstr "" +"Le apparentia incargate es troppo voluminose; debe occupar minus de %d bytes " +"in forma non comprimite." #: lib/themeuploader.php:178 msgid "Invalid theme archive: missing file css/display.css" -msgstr "" +msgstr "Archivo de apparentia invalide: manca le file css/display.css" #: lib/themeuploader.php:205 msgid "" "Theme contains invalid file or folder name. Stick with ASCII letters, " "digits, underscore, and minus sign." msgstr "" +"Le apparentia contine un nomine de file o dossier invalide. Limita te a " +"litteras ASCII, digitos, sublineamento, e signo minus." #: lib/themeuploader.php:216 #, php-format msgid "Theme contains file of type '.%s', which is not allowed." msgstr "" +"Le apparentia contine un file del typo '.%s', le qual non es permittite." #: lib/themeuploader.php:234 -#, fuzzy msgid "Error opening theme archive." -msgstr "Error durante le actualisation del profilo remote." +msgstr "Error durante le apertura del archivo del apparentia." #: lib/topposterssection.php:74 msgid "Top posters" diff --git a/locale/is/LC_MESSAGES/statusnet.po b/locale/is/LC_MESSAGES/statusnet.po index 511b706caa..c76c4e95f5 100644 --- a/locale/is/LC_MESSAGES/statusnet.po +++ b/locale/is/LC_MESSAGES/statusnet.po @@ -9,11 +9,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:20:07+0000\n" +"PO-Revision-Date: 2010-06-21 18:04:07+0000\n" "Language-Team: Icelandic\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: is\n" "X-Message-Group: out-statusnet\n" diff --git a/locale/it/LC_MESSAGES/statusnet.po b/locale/it/LC_MESSAGES/statusnet.po index 8013d4a577..1b6b39f032 100644 --- a/locale/it/LC_MESSAGES/statusnet.po +++ b/locale/it/LC_MESSAGES/statusnet.po @@ -1,5 +1,6 @@ # Translation of StatusNet to Italian # +# Author@translatewiki.net: HalphaZ # Author@translatewiki.net: Milocasagrande # Author@translatewiki.net: Nemo bis # -- @@ -10,11 +11,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:20:12+0000\n" +"PO-Revision-Date: 2010-06-21 18:04:12+0000\n" "Language-Team: Italian\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: it\n" "X-Message-Group: out-statusnet\n" @@ -1129,13 +1130,12 @@ msgid "Theme for the site." msgstr "Tema per questo sito." #: actions/designadminpanel.php:467 -#, fuzzy msgid "Custom theme" -msgstr "Tema del sito" +msgstr "Tema personalizzato" #: actions/designadminpanel.php:471 msgid "You can upload a custom StatusNet theme as a .ZIP archive." -msgstr "" +msgstr "Puoi caricare un tema per StatusNet personalizzato come un file ZIP." #: actions/designadminpanel.php:486 lib/designsettings.php:101 msgid "Change background image" @@ -1195,11 +1195,11 @@ msgstr "Collegamenti" #: actions/designadminpanel.php:651 msgid "Advanced" -msgstr "" +msgstr "Avanzate" #: actions/designadminpanel.php:655 msgid "Custom CSS" -msgstr "" +msgstr "CSS personalizzato" #: actions/designadminpanel.php:676 lib/designsettings.php:247 msgid "Use defaults" @@ -6854,47 +6854,48 @@ msgstr "Nessuno" #: lib/themeuploader.php:50 msgid "This server cannot handle theme uploads without ZIP support." msgstr "" +"Questo server non è in grado di gestire caricamenti senza il supporto ZIP." #: lib/themeuploader.php:58 lib/themeuploader.php:61 -#, fuzzy msgid "Theme upload missing or failed." -msgstr "Errore di sistema nel caricare il file." +msgstr "Tema caricato mancante o caricamento non riuscito." #: lib/themeuploader.php:91 lib/themeuploader.php:102 #: lib/themeuploader.php:253 lib/themeuploader.php:257 #: lib/themeuploader.php:265 lib/themeuploader.php:272 -#, fuzzy msgid "Failed saving theme." -msgstr "Aggiornamento dell'immagine non riuscito." +msgstr "Salvataggio del tema non riuscito." #: lib/themeuploader.php:139 msgid "Invalid theme: bad directory structure." -msgstr "" +msgstr "Tema non valido: struttura directory non corretta." #: lib/themeuploader.php:166 #, php-format msgid "Uploaded theme is too large; must be less than %d bytes uncompressed." msgstr "" +"Il tema caricato è troppo grande, deve essere meno di %d byte non compresso." #: lib/themeuploader.php:178 msgid "Invalid theme archive: missing file css/display.css" -msgstr "" +msgstr "File di tema non valido: manca il file css/display.css" #: lib/themeuploader.php:205 msgid "" "Theme contains invalid file or folder name. Stick with ASCII letters, " "digits, underscore, and minus sign." msgstr "" +"Il tema contiene file non o nomi di cartelle non validi. Utilizzare " +"solamente caratteri ASCII, numeri, il trattino basso e il segno meno." #: lib/themeuploader.php:216 #, php-format msgid "Theme contains file of type '.%s', which is not allowed." -msgstr "" +msgstr "Il tema contiene file di tipo \".%s\" che non sono supportati." #: lib/themeuploader.php:234 -#, fuzzy msgid "Error opening theme archive." -msgstr "Errore nell'aggiornare il profilo remoto." +msgstr "Errore nell'aprire il file del tema." #: lib/topposterssection.php:74 msgid "Top posters" diff --git a/locale/ja/LC_MESSAGES/statusnet.po b/locale/ja/LC_MESSAGES/statusnet.po index b6f83d8d9c..e0e1ef0210 100644 --- a/locale/ja/LC_MESSAGES/statusnet.po +++ b/locale/ja/LC_MESSAGES/statusnet.po @@ -1,5 +1,6 @@ # Translation of StatusNet to Japanese # +# Author@translatewiki.net: Brion # Author@translatewiki.net: Fryed-peach # Author@translatewiki.net: Sonoda # Author@translatewiki.net: Whym @@ -11,11 +12,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:20:17+0000\n" +"PO-Revision-Date: 2010-06-21 18:04:16+0000\n" "Language-Team: Japanese\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: ja\n" "X-Message-Group: out-statusnet\n" @@ -2578,7 +2579,7 @@ msgstr "つぶやきにはプロファイルはありません。" #: actions/oembed.php:87 actions/shownotice.php:175 #, php-format msgid "%1$s's status on %2$s" -msgstr "%2$s における %1$ のステータス" +msgstr "%2$s における %1$s のステータス" #. TRANS: Error message displaying attachments. %s is a raw MIME type (eg 'image/png') #: actions/oembed.php:159 diff --git a/locale/ko/LC_MESSAGES/statusnet.po b/locale/ko/LC_MESSAGES/statusnet.po index 0c9a7395c9..ce2db363a0 100644 --- a/locale/ko/LC_MESSAGES/statusnet.po +++ b/locale/ko/LC_MESSAGES/statusnet.po @@ -9,11 +9,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:20:22+0000\n" +"PO-Revision-Date: 2010-06-21 18:04:21+0000\n" "Language-Team: Korean\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: ko\n" "X-Message-Group: out-statusnet\n" diff --git a/locale/mk/LC_MESSAGES/statusnet.po b/locale/mk/LC_MESSAGES/statusnet.po index 7103c57867..09836ffa57 100644 --- a/locale/mk/LC_MESSAGES/statusnet.po +++ b/locale/mk/LC_MESSAGES/statusnet.po @@ -10,11 +10,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:20:27+0000\n" +"PO-Revision-Date: 2010-06-21 18:04:26+0000\n" "Language-Team: Macedonian\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: mk\n" "X-Message-Group: out-statusnet\n" @@ -29,7 +29,7 @@ msgstr "Пристап" #. TRANS: Page notice #: actions/accessadminpanel.php:67 msgid "Site access settings" -msgstr "Нагодувања за пристап на веб-страницата" +msgstr "Нагодувања за пристап на мрежното место" #. TRANS: Form legend for registration form. #: actions/accessadminpanel.php:161 @@ -40,8 +40,8 @@ msgstr "Регистрација" #: actions/accessadminpanel.php:165 msgid "Prohibit anonymous users (not logged in) from viewing site?" msgstr "" -"Да им забранам на анонимните (ненајавени) корисници да ја гледаат веб-" -"страницата?" +"Да им забранам на анонимните (ненајавени) корисници да го гледаат мрежното " +"место?" #. TRANS: Checkbox label for prohibiting anonymous users from viewing site. #: actions/accessadminpanel.php:167 @@ -1101,7 +1101,7 @@ msgstr "Изглед" #: actions/designadminpanel.php:74 msgid "Design settings for this StatusNet site." -msgstr "Нагодувања на изгледот на оваа StatusNet веб-страница." +msgstr "Нагодувања на изгледот на ова StatusNet-мрежно место." #: actions/designadminpanel.php:318 msgid "Invalid logo URL." @@ -1118,28 +1118,27 @@ msgstr "Промени лого" #: actions/designadminpanel.php:431 msgid "Site logo" -msgstr "Лого на веб-страницата" +msgstr "Лого на мрежното место" #: actions/designadminpanel.php:443 msgid "Change theme" -msgstr "Промени тема" +msgstr "Промени изглед" #: actions/designadminpanel.php:460 msgid "Site theme" -msgstr "Тема на веб-страницата" +msgstr "Изглед на мрежното место" #: actions/designadminpanel.php:461 msgid "Theme for the site." -msgstr "Тема за веб-страницата." +msgstr "Изглед за мрежното место." #: actions/designadminpanel.php:467 -#, fuzzy msgid "Custom theme" -msgstr "Тема на веб-страницата" +msgstr "Прилагоден мотив" #: actions/designadminpanel.php:471 msgid "You can upload a custom StatusNet theme as a .ZIP archive." -msgstr "" +msgstr "Можете да подигнете свој изглед за StatusNet како .ZIP архив." #: actions/designadminpanel.php:486 lib/designsettings.php:101 msgid "Change background image" @@ -1156,7 +1155,7 @@ msgid "" "You can upload a background image for the site. The maximum file size is %1" "$s." msgstr "" -"Може да подигнете позадинска слика за оваа веб-страница. Максималната " +"Може да подигнете позадинска слика за ова мрежно место. Максималната " "големина на податотеката е %1$s." #. TRANS: Used as radio button label to add a background image. @@ -1199,11 +1198,11 @@ msgstr "Врски" #: actions/designadminpanel.php:651 msgid "Advanced" -msgstr "" +msgstr "Напредно" #: actions/designadminpanel.php:655 msgid "Custom CSS" -msgstr "" +msgstr "Прилагодено CSS" #: actions/designadminpanel.php:676 lib/designsettings.php:247 msgid "Use defaults" @@ -1604,7 +1603,7 @@ msgstr "Популарни забелешки, стр. %d" #: actions/favorited.php:79 msgid "The most popular notices on the site right now." -msgstr "Моментално најпопуларни забелешки на веб-страницата." +msgstr "Моментално најпопуларни забелешки на мрежното место." #: actions/favorited.php:150 msgid "Favorite notices appear on this page but no one has favorited one yet." @@ -1721,7 +1720,7 @@ msgstr "Оваа улога е резервирана и не може да се #: actions/grantrole.php:75 msgid "You cannot grant user roles on this site." -msgstr "Не можете да им доделувате улоги на корисниците на оваа веб-страница." +msgstr "Не можете да им доделувате улоги на корисниците на ова мрежно место." #: actions/grantrole.php:82 msgid "User already has this role." @@ -2180,15 +2179,15 @@ msgid "" "on the site. Thanks for growing the community!" msgstr "" "Ќе добиете известување кога луѓето кои сте ги поканиле ќе ја прифатат " -"поканата и ќе се регистрираат на веб-страницата. Ви благодариме за Вашата " -"помош со проширувањето на заедницата!" +"поканата и ќе се регистрираат на мрежното место. Ви благодариме што ни " +"помагате да ја прошириме заедницата!" #: actions/invite.php:162 msgid "" "Use this form to invite your friends and colleagues to use this service." msgstr "" -"Со овој обраец можете да поканите пријатели и колеги да ја користат веб-" -"страницата." +"Со овој обраец можете да поканите пријатели и колеги да го користат мрежното " +"место." #: actions/invite.php:187 msgid "Email addresses" @@ -2251,7 +2250,7 @@ msgid "" msgstr "" "%1$s Ве кани да се придружите на %2$s (%3$s).\n" "\n" -"%2$s е веб-страница за микроблогирање што ви овозможува да бидете во тек " +"%2$s е мрежно место за микроблогирање што ви овозможува да бидете во тек " "луѓето што ги познавате и луѓето кои ве интересираат.\n" "\n" "Можете да објавувате и новости за Вас, Ваши размисли, и настани од Вашиот " @@ -2266,7 +2265,7 @@ msgstr "" "\n" "%5$s\n" "\n" -"Ако сакате да ја испробате оваа друштвена веб-страница, кликнете на врската " +"Ако сакате да ја испробате оваа друштвено мрежно место, кликнете на врската " "подолу за да ја прифатите поканата.\n" "\n" "%6$s\n" @@ -2489,8 +2488,8 @@ msgid "" "[post on this topic](%%%%action.newnotice%%%%?status_textarea=%s)!" msgstr "" "А зошто не [регистрирате сметка](%%%%action.register%%%%) и станете првиот " -"што ќе [објави нешто на оваа тема](%%%%action.newnotice%%%%?status_textarea=" -"%s)!" +"што ќе [објави нешто на оваа тема](%%%%action.newnotice%%%%?status_textarea=%" +"s)!" #: actions/noticesearchrss.php:96 #, php-format @@ -2759,7 +2758,7 @@ msgstr "Неважечки SSL-опслужувач. Дозволени се н #: actions/pathsadminpanel.php:234 actions/siteadminpanel.php:58 msgid "Site" -msgstr "Веб-страница" +msgstr "Мреж. место" #: actions/pathsadminpanel.php:238 msgid "Server" @@ -2775,7 +2774,7 @@ msgstr "Патека" #: actions/pathsadminpanel.php:242 msgid "Site path" -msgstr "Патека на веб-страницата" +msgstr "Патека на мрежното место" #: actions/pathsadminpanel.php:246 msgid "Path to locales" @@ -2795,7 +2794,7 @@ msgstr "Да користам интересни (почитливи и повп #: actions/pathsadminpanel.php:259 msgid "Theme" -msgstr "Тема" +msgstr "Изглед" #: actions/pathsadminpanel.php:264 msgid "Theme server" @@ -2909,8 +2908,8 @@ msgstr "Неважечка содржина на забелешката." #, php-format msgid "Notice license ‘%1$s’ is not compatible with site license ‘%2$s’." msgstr "" -"Лиценцата на забелешката „%1$s“ не е компатибилна со лиценцата на веб-" -"страницата „%2$s“." +"Лиценцата на забелешката „%1$s“ не е соодветна на лиценцата на мрежното " +"место „%2$s“." #: actions/profilesettings.php:60 msgid "Profile settings" @@ -2945,7 +2944,7 @@ msgstr "Домашна страница" #: actions/profilesettings.php:117 actions/register.php:462 msgid "URL of your homepage, blog, or profile on another site" -msgstr "URL на Вашата домашна страница, блог или профил на друга веб-страница." +msgstr "URL на Вашата домашна страница, блог или профил на друго мрежно место." #: actions/profilesettings.php:122 actions/register.php:468 #, php-format @@ -3108,10 +3107,10 @@ msgid "" "tool. [Join now](%%action.register%%) to share notices about yourself with " "friends, family, and colleagues! ([Read more](%%doc.help%%))" msgstr "" -"Ова е %%site.name%%, веб-страница за [микроблогирање](http://mk.wikipedia." -"org/wiki/Микроблогирање) базирана на слободната програмска алатка [StatusNet]" -"(http://status.net/). [Зачленете се](%%action.register%%) за да си " -"споделувате забелешки за себе со приајтелите, семејството и колегите! " +"Ова е %%site.name%%, мрежно место за [микроблогирање](http://mk.wikipedia." +"org/wiki/Микроблогирање) заснована на слободната програмска алатка " +"[StatusNet](http://status.net/). [Зачленете се](%%action.register%%) за да " +"си споделувате забелешки за себе со приајтелите, семејството и колегите! " "([Прочитајте повеќе](%%doc.help%%))" #: actions/public.php:247 @@ -3121,9 +3120,9 @@ msgid "" "blogging) service based on the Free Software [StatusNet](http://status.net/) " "tool." msgstr "" -"Ова е %%site.name%%, веб-страница за [микроблогирање](http://mk.wikipedia." -"org/wiki/Микроблогирање) базирана на слободната програмска алатка [StatusNet]" -"(http://status.net/)." +"Ова е %%site.name%%, мрежно место за [микроблогирање](http://mk.wikipedia." +"org/wiki/Микроблогирање) заснована на слободната програмска алатка " +"[StatusNet](http://status.net/)." #: actions/publictagcloud.php:57 msgid "Public tag cloud" @@ -3432,10 +3431,10 @@ msgid "" "register%%) a new account. If you already have an account on a [compatible " "microblogging site](%%doc.openmublog%%), enter your profile URL below." msgstr "" -"За да се претплатите, може да се [најавите](%%action.login%%) или да " +"За да се претплатите, можете да се [најавите](%%action.login%%) или да " "[регистрирате](%%action.register%%) нова сметка. Ако веќе имате сметка на " -"[компатибилна веб-страница за микроблогирање](%%doc.openmublog%%), внесете " -"го URL-то на Вашиот профил подолу." +"[усогласиво мреж. место за микроблогирање](%%doc.openmublog%%), внесете го " +"URL-то на Вашиот профил подолу." #: actions/remotesubscribe.php:112 msgid "Remote subscribe" @@ -3459,7 +3458,7 @@ msgstr "URL на профилот" #: actions/remotesubscribe.php:134 msgid "URL of your profile on another compatible microblogging service" -msgstr "URL на Вашиот профил на друга компатибилна служба за микроблогирање." +msgstr "URL на Вашиот профил на друга соодветна служба за микроблогирање." #: actions/remotesubscribe.php:137 lib/subscribeform.php:139 #: lib/userprofile.php:406 @@ -3568,7 +3567,7 @@ msgstr "Одговори на %1$s на %2$s!" #: actions/revokerole.php:75 msgid "You cannot revoke user roles on this site." -msgstr "На оваа веб-страница не можете да одземате кориснички улоги." +msgstr "На ова мрежно место не можете да одземате кориснички улоги." #: actions/revokerole.php:82 msgid "User doesn't have this role." @@ -3580,7 +3579,7 @@ msgstr "StatusNet" #: actions/sandbox.php:65 actions/unsandbox.php:65 msgid "You cannot sandbox users on this site." -msgstr "Не можете да ставате корисници во песочен режим на оваа веб-страница." +msgstr "Не можете да ставате корисници во песочен режим на ова мрежно место." #: actions/sandbox.php:72 msgid "User is already sandboxed." @@ -3594,7 +3593,7 @@ msgstr "Сесии" #: actions/sessionsadminpanel.php:65 msgid "Session settings for this StatusNet site." -msgstr "Нагодувања на сесиите за оваа StatusNet веб-страница." +msgstr "Нагодувања на сесиите за оваа StatusNet-мрежно место." #: actions/sessionsadminpanel.php:175 msgid "Handle sessions" @@ -3615,7 +3614,7 @@ msgstr "Вклучи извод од поправка на грешки за с #: actions/sessionsadminpanel.php:199 actions/siteadminpanel.php:292 #: actions/useradminpanel.php:294 msgid "Save site settings" -msgstr "Зачувај нагодувања на веб-страницата" +msgstr "Зачувај нагодувања на мреж. место" #: actions/showapplication.php:82 msgid "You must be logged in to view an application." @@ -3839,8 +3838,8 @@ msgid "" "their life and interests. [Join now](%%%%action.register%%%%) to become part " "of this group and many more! ([Read more](%%%%doc.help%%%%))" msgstr "" -"**%s** е корисничка група на %%%%site.name%%%%, веб-страница за " -"[микроблогирање](http://mk.wikipedia.org/wiki/Микроблогирање) базирана на " +"**%s** е корисничка група на %%%%site.name%%%%, мрежно место за " +"[микроблогирање](http://mk.wikipedia.org/wiki/Микроблогирање) заснована на " "слободната програмска алатка [StatusNet](http://status.net/). Нејзините " "членови си разменуваат кратки пораки за нивниот живот и интереси. [Зачленете " "се](%%%%action.register%%%%) за да станете дел од оваа група и многу повеќе! " @@ -3854,8 +3853,8 @@ msgid "" "[StatusNet](http://status.net/) tool. Its members share short messages about " "their life and interests. " msgstr "" -"**%s** е корисничка група на %%%%site.name%%%%, веб-страница за " -"[микроблогирање](http://mk.wikipedia.org/wiki/Микроблогирање) базирана на " +"**%s** е корисничка група на %%%%site.name%%%%, мрежно место за " +"[микроблогирање](http://mk.wikipedia.org/wiki/Микроблогирање) заснована на " "слободната програмска алатка [StatusNet](http://status.net/). Нејзините " "членови си разменуваат кратки пораки за нивниот живот и интереси. " @@ -3950,8 +3949,8 @@ msgid "" "[StatusNet](http://status.net/) tool. [Join now](%%%%action.register%%%%) to " "follow **%s**'s notices and many more! ([Read more](%%%%doc.help%%%%))" msgstr "" -"**%s** има сметка на %%%%site.name%%%%, веб-страница за [микроблогирање]" -"(http://mk.wikipedia.org/wiki/Микроблогирање) базирана на слободната " +"**%s** има сметка на %%%%site.name%%%%, мрежно место за [микроблогирање]" +"(http://mk.wikipedia.org/wiki/Микроблогирање) заснована на слободната " "програмска алатка [StatusNet](http://status.net/). [Зачленете се](%%%%action." "register%%%%) за да можете да ги следите забелешките на **%s** и многу " "повеќе! ([Прочитајте повеќе](%%%%doc.help%%%%))" @@ -3963,8 +3962,8 @@ msgid "" "wikipedia.org/wiki/Micro-blogging) service based on the Free Software " "[StatusNet](http://status.net/) tool. " msgstr "" -"**%s** има сметка на %%%%site.name%%%%, веб-страница за [микроблогирање]" -"(http://mk.wikipedia.org/wiki/Микроблогирање) базирана на слободната " +"**%s** има сметка на %%%%site.name%%%%, мрежно место за [микроблогирање]" +"(http://mk.wikipedia.org/wiki/Микроблогирање) заснована на слободната " "програмска алатка [StatusNet](http://status.net/). " #: actions/showstream.php:305 @@ -3974,7 +3973,7 @@ msgstr "Повторувања на %s" #: actions/silence.php:65 actions/unsilence.php:65 msgid "You cannot silence users on this site." -msgstr "Не можете да замолчувате корисници на оваа веб-страница." +msgstr "Не можете да замолчувате корисници на ова мрежно место." #: actions/silence.php:72 msgid "User is already silenced." @@ -3982,11 +3981,11 @@ msgstr "Корисникот е веќе замолчен." #: actions/siteadminpanel.php:69 msgid "Basic settings for this StatusNet site" -msgstr "Основни поставки за оваа StatusNet веб-страница." +msgstr "Основни поставки за оваа StatusNet-мрежно место." #: actions/siteadminpanel.php:133 msgid "Site name must have non-zero length." -msgstr "Должината на името на веб-страницата не може да изнесува нула." +msgstr "Должината на името на мрежното место не може да изнесува нула." #: actions/siteadminpanel.php:141 msgid "You must have a valid contact email address." @@ -4011,11 +4010,11 @@ msgstr "Општи" #: actions/siteadminpanel.php:224 msgid "Site name" -msgstr "Име на веб-страницата" +msgstr "Име на мрежното место" #: actions/siteadminpanel.php:225 msgid "The name of your site, like \"Yourcompany Microblog\"" -msgstr "Името на Вашата веб-страница, како на пр. „Микроблог на Вашафирма“" +msgstr "Името на Вашето мрежно место, како на пр. „Микроблог на Вашафирма“" #: actions/siteadminpanel.php:229 msgid "Brought by" @@ -4039,7 +4038,7 @@ msgstr "" #: actions/siteadminpanel.php:239 msgid "Contact email address for your site" -msgstr "Контактна е-пошта за Вашата веб-страница" +msgstr "Контактна е-пошта за Вашето мрежното место" #: actions/siteadminpanel.php:245 msgid "Local" @@ -4051,7 +4050,7 @@ msgstr "Основна часовна зона" #: actions/siteadminpanel.php:257 msgid "Default timezone for the site; usually UTC." -msgstr "Матична часовна зона за веб-страницата; обично UTC." +msgstr "Матична часовна зона за мрежното место; обично UTC." #: actions/siteadminpanel.php:262 msgid "Default language" @@ -4059,9 +4058,7 @@ msgstr "Основен јазик" #: actions/siteadminpanel.php:263 msgid "Site language when autodetection from browser settings is not available" -msgstr "" -"Јазик на мрежното место (веб-страницата) ако прелистувачот не може да го " -"препознае сам" +msgstr "Јазик на мрежното место ако прелистувачот не може да го препознае сам" #: actions/siteadminpanel.php:271 msgid "Limits" @@ -4091,24 +4088,24 @@ msgstr "Објава на страница" #: actions/sitenoticeadminpanel.php:67 msgid "Edit site-wide message" -msgstr "Уреди објава за цела веб-страница" +msgstr "Уреди објава за цело мрежно место" #: actions/sitenoticeadminpanel.php:103 msgid "Unable to save site notice." -msgstr "Не можам да ја зачувам објавата за веб-страницата." +msgstr "Не можам да ја зачувам објавата за мрежното место." #: actions/sitenoticeadminpanel.php:113 msgid "Max length for the site-wide notice is 255 chars." -msgstr "Објавата за цела веб-страница не треба да содржи повеќе од 255 знаци." +msgstr "Објавата за цело мрежно место не треба да содржи повеќе од 255 знаци." #: actions/sitenoticeadminpanel.php:176 msgid "Site notice text" -msgstr "Текст на објавата за веб-страницата" +msgstr "Текст на објавата за мрежното место" #: actions/sitenoticeadminpanel.php:178 msgid "Site-wide notice text (255 chars max; HTML okay)" msgstr "" -"Текст за главна објава по цела веб-страница (највеќе до 255 знаци; дозволено " +"Текст за главна објава по цело мрежно место (највеќе до 255 знаци; дозволено " "и HTML)" #: actions/sitenoticeadminpanel.php:198 @@ -4539,8 +4536,8 @@ msgstr "Претплатата е откажана" msgid "" "Listenee stream license ‘%1$s’ is not compatible with site license ‘%2$s’." msgstr "" -"Лиценцата на потокот на следачот „%1$s“ не е компатибилна со лиценцата на " -"веб-страницата „%2$s“." +"Лиценцата на каналот на следачот „%1$s“ не е соодветна на лиценцата на " +"мрежното место „%2$s“." #. TRANS: User admin panel title #: actions/useradminpanel.php:59 @@ -4550,7 +4547,7 @@ msgstr "Корисник" #: actions/useradminpanel.php:70 msgid "User settings for this StatusNet site." -msgstr "Кориснички нагодувања за оваа StatusNet веб-страница." +msgstr "Кориснички нагодувања за ова StatusNet-мрежно место." #: actions/useradminpanel.php:149 msgid "Invalid bio limit. Must be numeric." @@ -4661,7 +4658,7 @@ msgid "" "subscription. Your subscription token is:" msgstr "" "Претплатата е одобрена, но не е зададена обратна URL-адреса. Проверете ги " -"инструкциите на веб-страницата за да дознаете како се одобрува претплата. " +"инструкциите на мрежното место за да дознаете како се одобрува претплата. " "Жетонот на Вашата претплата е:" #: actions/userauthorization.php:266 @@ -4675,7 +4672,7 @@ msgid "" "subscription." msgstr "" "Претплатата е одбиена, но не е зададена обратна URL-адреса. Проверете ги " -"инструкциите на веб-страницата за да дознаете како се одбива претплата во " +"инструкциите на мрежното место за да дознаете како се одбива претплата во " "потполност." #: actions/userauthorization.php:303 @@ -4773,7 +4770,7 @@ msgid "" "This site is powered by %1$s version %2$s, Copyright 2008-2010 StatusNet, " "Inc. and contributors." msgstr "" -"Оваа веб-страница работи на %1$s верзија %2$s, Авторски права 2008-2010 " +"Ова мрежно место работи на %1$s верзија %2$s, Авторски права 2008-2010 " "StatusNet, Inc. и учесници." #: actions/version.php:163 @@ -4910,7 +4907,7 @@ msgstr "" #: classes/Notice.php:272 msgid "You are banned from posting notices on this site." -msgstr "Забрането Ви е да објавувате забелешки на оваа веб-страница." +msgstr "Забрането Ви е да објавувате забелешки на ова мрежно место." #: classes/Notice.php:338 classes/Notice.php:364 msgid "Problem saving notice." @@ -5061,7 +5058,7 @@ msgstr "Поврзи се" #: lib/action.php:458 msgctxt "TOOLTIP" msgid "Change site configuration" -msgstr "Промена на поставките на веб-страницата" +msgstr "Промена на поставките на мрежното место" #. TRANS: Main menu option when logged in and site admin for access to site configuration #: lib/action.php:461 @@ -5143,7 +5140,7 @@ msgstr "Барај" #. TRANS: Menu item for site administration #: lib/action.php:525 lib/adminpanelaction.php:400 msgid "Site notice" -msgstr "Напомена за веб-страницата" +msgstr "Напомена за мрежното место" #. TRANS: DT element for local views block. String is hidden in default CSS. #: lib/action.php:592 @@ -5235,7 +5232,7 @@ msgstr "" #. TRANS: DT element for StatusNet site content license. #: lib/action.php:850 msgid "Site content license" -msgstr "Лиценца на содржините на веб-страницата" +msgstr "Лиценца на содржините на мрежното место" #. TRANS: Content license displayed when license is set to 'private'. #. TRANS: %1$s is the site name. @@ -5303,7 +5300,7 @@ msgstr "Сè уште не е достапна обработката на вм #. TRANS: Client error message thrown when a user tries to change admin settings but has no access rights. #: lib/adminpanelaction.php:98 msgid "You cannot make changes to this site." -msgstr "Не можете да ја менувате оваа веб-страница." +msgstr "Не можете да врште измени на ова мрежно место." #. TRANS: Client error message throw when a certain panel's settings cannot be changed. #: lib/adminpanelaction.php:110 @@ -5329,13 +5326,13 @@ msgstr "Не можам да ги избришам нагодувањата за #. TRANS: Menu item title/tooltip #: lib/adminpanelaction.php:350 msgid "Basic site configuration" -msgstr "Основни нагодувања на веб-страницата" +msgstr "Основни нагодувања на мрежното место" #. TRANS: Menu item for site administration #: lib/adminpanelaction.php:352 msgctxt "MENU" msgid "Site" -msgstr "Веб-страница" +msgstr "Мреж. место" #. TRANS: Menu item title/tooltip #: lib/adminpanelaction.php:358 @@ -5376,7 +5373,7 @@ msgstr "Конфигурација на сесиите" #. TRANS: Menu item title/tooltip #: lib/adminpanelaction.php:398 msgid "Edit site notice" -msgstr "Уреди објава за веб-страницата" +msgstr "Уреди објава за мрежното место" #. TRANS: Menu item title/tooltip #: lib/adminpanelaction.php:406 @@ -6792,7 +6789,7 @@ msgstr "Стави го корисников во песочен режим" #: lib/searchaction.php:120 msgid "Search site" -msgstr "Пребарај по веб-страницата" +msgstr "Пребарај по мрежното место" #: lib/searchaction.php:126 msgid "Keyword(s)" @@ -6812,7 +6809,7 @@ msgstr "Луѓе" #: lib/searchgroupnav.php:81 msgid "Find people on this site" -msgstr "Пронајдете луѓе на оваа веб-страница" +msgstr "Пронајдете луѓе на ова мрежно место" #: lib/searchgroupnav.php:83 msgid "Find content of notices" @@ -6820,7 +6817,7 @@ msgstr "Пронајдете содржини на забелешките" #: lib/searchgroupnav.php:85 msgid "Find groups on this site" -msgstr "Пронајдете групи на оваа веб-страница" +msgstr "Пронајдете групи на ова мрежно место" #: lib/section.php:89 msgid "Untitled section" @@ -6879,47 +6876,48 @@ msgstr "Без ознаки" #: lib/themeuploader.php:50 msgid "This server cannot handle theme uploads without ZIP support." msgstr "" +"Опслужувачот не може да се справи со подигања на изгледи без ZIP-поддршка." #: lib/themeuploader.php:58 lib/themeuploader.php:61 -#, fuzzy msgid "Theme upload missing or failed." -msgstr "Системска грешка при подигањето на податотеката." +msgstr "Подигањето на мотивот недостасува или не успеа." #: lib/themeuploader.php:91 lib/themeuploader.php:102 #: lib/themeuploader.php:253 lib/themeuploader.php:257 #: lib/themeuploader.php:265 lib/themeuploader.php:272 -#, fuzzy msgid "Failed saving theme." -msgstr "Подновата на аватарот не успеа." +msgstr "Зачувувањето на мотивот не успеа." #: lib/themeuploader.php:139 msgid "Invalid theme: bad directory structure." -msgstr "" +msgstr "Неважечки изглед: лош состав на папката." #: lib/themeuploader.php:166 #, php-format msgid "Uploaded theme is too large; must be less than %d bytes uncompressed." msgstr "" +"Подигнатиот изглед е преголем; мора да биде помал од %d бајти (незбиен)." #: lib/themeuploader.php:178 msgid "Invalid theme archive: missing file css/display.css" -msgstr "" +msgstr "Неважечки архив за изглеедот: недостасува податотеката css/display.css" #: lib/themeuploader.php:205 msgid "" "Theme contains invalid file or folder name. Stick with ASCII letters, " "digits, underscore, and minus sign." msgstr "" +"Изгледот содржи неважечки назив на податотека или папка. Дозволени се само " +"ASCII-букви, бројки, долна црта и знак за минус." #: lib/themeuploader.php:216 #, php-format msgid "Theme contains file of type '.%s', which is not allowed." -msgstr "" +msgstr "Изгледот содржи податотека од типот „.%s“, која не е дозволена." #: lib/themeuploader.php:234 -#, fuzzy msgid "Error opening theme archive." -msgstr "Грешка во подновувањето на далечинскиот профил." +msgstr "Грешка при отворањето на архивот за мотив." #: lib/topposterssection.php:74 msgid "Top posters" diff --git a/locale/nb/LC_MESSAGES/statusnet.po b/locale/nb/LC_MESSAGES/statusnet.po index ffe7599e20..112ca76c8e 100644 --- a/locale/nb/LC_MESSAGES/statusnet.po +++ b/locale/nb/LC_MESSAGES/statusnet.po @@ -10,11 +10,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:20:35+0000\n" +"PO-Revision-Date: 2010-06-21 18:04:30+0000\n" "Language-Team: Norwegian (bokmål)‬\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: no\n" "X-Message-Group: out-statusnet\n" diff --git a/locale/nl/LC_MESSAGES/statusnet.po b/locale/nl/LC_MESSAGES/statusnet.po index bb16ff60a1..a69a7c7ea6 100644 --- a/locale/nl/LC_MESSAGES/statusnet.po +++ b/locale/nl/LC_MESSAGES/statusnet.po @@ -11,11 +11,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:20:48+0000\n" +"PO-Revision-Date: 2010-06-21 18:04:39+0000\n" "Language-Team: Dutch\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: nl\n" "X-Message-Group: out-statusnet\n" @@ -1143,13 +1143,12 @@ msgid "Theme for the site." msgstr "Mogelijke vormgevingen voor deze website." #: actions/designadminpanel.php:467 -#, fuzzy msgid "Custom theme" -msgstr "Vormgeving website" +msgstr "Aangepaste vormgeving" #: actions/designadminpanel.php:471 msgid "You can upload a custom StatusNet theme as a .ZIP archive." -msgstr "" +msgstr "U kunt een vormgeving voor StatusNet uploaden als ZIP-archief." #: actions/designadminpanel.php:486 lib/designsettings.php:101 msgid "Change background image" @@ -1209,11 +1208,11 @@ msgstr "Verwijzingen" #: actions/designadminpanel.php:651 msgid "Advanced" -msgstr "" +msgstr "Uitgebreid" #: actions/designadminpanel.php:655 msgid "Custom CSS" -msgstr "" +msgstr "Aangepaste CSS" #: actions/designadminpanel.php:676 lib/designsettings.php:247 msgid "Use defaults" @@ -6928,48 +6927,54 @@ msgstr "Geen" #: lib/themeuploader.php:50 msgid "This server cannot handle theme uploads without ZIP support." msgstr "" +"Deze server kan niet overweg met uploads van vormgevingsbestanden zonder ZIP-" +"ondersteuning." #: lib/themeuploader.php:58 lib/themeuploader.php:61 -#, fuzzy msgid "Theme upload missing or failed." -msgstr "Er is een systeemfout opgetreden tijdens het uploaden van het bestand." +msgstr "Het uploaden van het bestand met de vormgeving is mislukt." #: lib/themeuploader.php:91 lib/themeuploader.php:102 #: lib/themeuploader.php:253 lib/themeuploader.php:257 #: lib/themeuploader.php:265 lib/themeuploader.php:272 -#, fuzzy msgid "Failed saving theme." -msgstr "Het bijwerken van de avatar is mislukt." +msgstr "Het opslaan van de vormgeving is mislukt." #: lib/themeuploader.php:139 msgid "Invalid theme: bad directory structure." -msgstr "" +msgstr "Ongeldige vormgeving: de mappenstructuur is onjuist." #: lib/themeuploader.php:166 #, php-format msgid "Uploaded theme is too large; must be less than %d bytes uncompressed." msgstr "" +"De toegevoegde vormgeving is te groot. Deze moet uitgepakt kleiner zijn dan %" +"d bytes." #: lib/themeuploader.php:178 msgid "Invalid theme archive: missing file css/display.css" msgstr "" +"Ongeldig bestand met vormgeving: het bestand display.css is niet aanwezig" #: lib/themeuploader.php:205 msgid "" "Theme contains invalid file or folder name. Stick with ASCII letters, " "digits, underscore, and minus sign." msgstr "" +"De vormgeving bevat een ongeldige bestandsnaam of mapnaam. Gebruik alleen " +"maar ASCII-letters, getallen, liggende streepjes en het minteken." #: lib/themeuploader.php:216 #, php-format msgid "Theme contains file of type '.%s', which is not allowed." msgstr "" +"De vormgeving bevat een bestand van het type \".%s\". Dit is niet toegestaan." #: lib/themeuploader.php:234 -#, fuzzy msgid "Error opening theme archive." msgstr "" -"Er is een fout opgetreden tijdens het bijwerken van het profiel op afstand." +"Er is een fout opgetreden tijdens het openen van het archiefbestand met de " +"vormgeving." #: lib/topposterssection.php:74 msgid "Top posters" diff --git a/locale/nn/LC_MESSAGES/statusnet.po b/locale/nn/LC_MESSAGES/statusnet.po index 6de6133b6a..dc166d820d 100644 --- a/locale/nn/LC_MESSAGES/statusnet.po +++ b/locale/nn/LC_MESSAGES/statusnet.po @@ -9,11 +9,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:20:43+0000\n" +"PO-Revision-Date: 2010-06-21 18:04:35+0000\n" "Language-Team: Norwegian Nynorsk\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: nn\n" "X-Message-Group: out-statusnet\n" diff --git a/locale/pl/LC_MESSAGES/statusnet.po b/locale/pl/LC_MESSAGES/statusnet.po index cdeecc4340..95146156b2 100644 --- a/locale/pl/LC_MESSAGES/statusnet.po +++ b/locale/pl/LC_MESSAGES/statusnet.po @@ -12,7 +12,7 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:20:52+0000\n" +"PO-Revision-Date: 2010-06-21 18:04:44+0000\n" "Last-Translator: Piotr Drąg \n" "Language-Team: Polish \n" "MIME-Version: 1.0\n" @@ -20,7 +20,7 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " "|| n%100>=20) ? 1 : 2);\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: pl\n" "X-Message-Group: out-statusnet\n" @@ -1128,13 +1128,12 @@ msgid "Theme for the site." msgstr "Motyw witryny." #: actions/designadminpanel.php:467 -#, fuzzy msgid "Custom theme" -msgstr "Motyw witryny" +msgstr "Własny motyw" #: actions/designadminpanel.php:471 msgid "You can upload a custom StatusNet theme as a .ZIP archive." -msgstr "" +msgstr "Można wysłać własny motyw witryny StatusNet jako archiwum zip." #: actions/designadminpanel.php:486 lib/designsettings.php:101 msgid "Change background image" @@ -1192,11 +1191,11 @@ msgstr "Odnośniki" #: actions/designadminpanel.php:651 msgid "Advanced" -msgstr "" +msgstr "Zaawansowane" #: actions/designadminpanel.php:655 msgid "Custom CSS" -msgstr "" +msgstr "Własny plik CSS" #: actions/designadminpanel.php:676 lib/designsettings.php:247 msgid "Use defaults" @@ -6848,47 +6847,49 @@ msgstr "Brak" #: lib/themeuploader.php:50 msgid "This server cannot handle theme uploads without ZIP support." msgstr "" +"Ten serwer nie może obsługiwać wysyłania motywu bez obsługi archiwów zip." #: lib/themeuploader.php:58 lib/themeuploader.php:61 -#, fuzzy msgid "Theme upload missing or failed." -msgstr "Błąd systemu podczas wysyłania pliku." +msgstr "Brak wysłania motywu lub nie powiodło się." #: lib/themeuploader.php:91 lib/themeuploader.php:102 #: lib/themeuploader.php:253 lib/themeuploader.php:257 #: lib/themeuploader.php:265 lib/themeuploader.php:272 -#, fuzzy msgid "Failed saving theme." -msgstr "Zaktualizowanie awatara nie powiodło się." +msgstr "Zapisanie motywu nie powiodło się." #: lib/themeuploader.php:139 msgid "Invalid theme: bad directory structure." -msgstr "" +msgstr "Nieprawidłowy motyw: błędna struktura katalogów." #: lib/themeuploader.php:166 #, php-format msgid "Uploaded theme is too large; must be less than %d bytes uncompressed." msgstr "" +"Wysłany motyw jest za duży, musi być mniejszy niż %d bajtów po " +"zdekompresowaniu." #: lib/themeuploader.php:178 msgid "Invalid theme archive: missing file css/display.css" -msgstr "" +msgstr "Nieprawidłowe archiwum motywu: brak pliku css/display.css" #: lib/themeuploader.php:205 msgid "" "Theme contains invalid file or folder name. Stick with ASCII letters, " "digits, underscore, and minus sign." msgstr "" +"Motyw zawiera nieprawidłowy plik lub nazwę katalogu. Należy używać tylko " +"liter, cyfr, podkreślników i znaku minus z zestawu ASCII." #: lib/themeuploader.php:216 #, php-format msgid "Theme contains file of type '.%s', which is not allowed." -msgstr "" +msgstr "Motyw zawiera plik typu \\\".%s\\\", który nie jest dozwolony." #: lib/themeuploader.php:234 -#, fuzzy msgid "Error opening theme archive." -msgstr "Błąd podczas aktualizowania zdalnego profilu." +msgstr "Błąd podczas otwierania archiwum motywu." #: lib/topposterssection.php:74 msgid "Top posters" diff --git a/locale/pt/LC_MESSAGES/statusnet.po b/locale/pt/LC_MESSAGES/statusnet.po index 36abe62cab..d2b2720bbd 100644 --- a/locale/pt/LC_MESSAGES/statusnet.po +++ b/locale/pt/LC_MESSAGES/statusnet.po @@ -1,6 +1,7 @@ # Translation of StatusNet to Portuguese # # Author@translatewiki.net: Gallaecio +# Author@translatewiki.net: Giro720 # Author@translatewiki.net: Hamilton Abreu # Author@translatewiki.net: Ipublicis # -- @@ -11,11 +12,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:20:57+0000\n" +"PO-Revision-Date: 2010-06-21 18:04:48+0000\n" "Language-Team: Portuguese\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: pt\n" "X-Message-Group: out-statusnet\n" @@ -1183,7 +1184,7 @@ msgstr "Texto" #: actions/designadminpanel.php:626 lib/designsettings.php:230 msgid "Links" -msgstr "Ligações" +msgstr "Links" #: actions/designadminpanel.php:651 msgid "Advanced" @@ -6683,7 +6684,7 @@ msgstr "Todos os subscritores" #: lib/profileaction.php:191 msgid "User ID" -msgstr "ID do utilizador" +msgstr "Número de identificação" #: lib/profileaction.php:196 msgid "Member since" diff --git a/locale/pt_BR/LC_MESSAGES/statusnet.po b/locale/pt_BR/LC_MESSAGES/statusnet.po index 1f5fc708e8..a12a309f34 100644 --- a/locale/pt_BR/LC_MESSAGES/statusnet.po +++ b/locale/pt_BR/LC_MESSAGES/statusnet.po @@ -13,11 +13,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:21:01+0000\n" +"PO-Revision-Date: 2010-06-21 18:04:52+0000\n" "Language-Team: Brazilian Portuguese\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: pt-br\n" "X-Message-Group: out-statusnet\n" @@ -1136,13 +1136,14 @@ msgid "Theme for the site." msgstr "Tema para o site." #: actions/designadminpanel.php:467 -#, fuzzy msgid "Custom theme" -msgstr "Tema do site" +msgstr "Tema personalizado" #: actions/designadminpanel.php:471 msgid "You can upload a custom StatusNet theme as a .ZIP archive." msgstr "" +"Você pode enviar um tema personalizado para o StatusNet, na forma de um " +"arquivo .zip." #: actions/designadminpanel.php:486 lib/designsettings.php:101 msgid "Change background image" @@ -1202,11 +1203,11 @@ msgstr "Links" #: actions/designadminpanel.php:651 msgid "Advanced" -msgstr "" +msgstr "Avançado" #: actions/designadminpanel.php:655 msgid "Custom CSS" -msgstr "" +msgstr "CSS personalizado" #: actions/designadminpanel.php:676 lib/designsettings.php:247 msgid "Use defaults" diff --git a/locale/ru/LC_MESSAGES/statusnet.po b/locale/ru/LC_MESSAGES/statusnet.po index b431ddd62b..d276b197a7 100644 --- a/locale/ru/LC_MESSAGES/statusnet.po +++ b/locale/ru/LC_MESSAGES/statusnet.po @@ -13,11 +13,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:21:06+0000\n" +"PO-Revision-Date: 2010-06-21 18:04:57+0000\n" "Language-Team: Russian\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: ru\n" "X-Message-Group: out-statusnet\n" @@ -1134,13 +1134,12 @@ msgid "Theme for the site." msgstr "Тема для сайта." #: actions/designadminpanel.php:467 -#, fuzzy msgid "Custom theme" -msgstr "Тема сайта" +msgstr "Особая тема" #: actions/designadminpanel.php:471 msgid "You can upload a custom StatusNet theme as a .ZIP archive." -msgstr "" +msgstr "Вы можете загрузить особую тему StatusNet в виде ZIP-архива." #: actions/designadminpanel.php:486 lib/designsettings.php:101 msgid "Change background image" @@ -1200,11 +1199,11 @@ msgstr "Ссылки" #: actions/designadminpanel.php:651 msgid "Advanced" -msgstr "" +msgstr "Расширенный" #: actions/designadminpanel.php:655 msgid "Custom CSS" -msgstr "" +msgstr "Особый CSS" #: actions/designadminpanel.php:676 lib/designsettings.php:247 msgid "Use defaults" @@ -4628,7 +4627,7 @@ msgstr "Принять" #: actions/userauthorization.php:218 lib/subscribeform.php:115 #: lib/subscribeform.php:139 msgid "Subscribe to this user" -msgstr "Подписаться на %s" +msgstr "Подписаться на этого пользователя" #: actions/userauthorization.php:219 msgid "Reject" @@ -6862,48 +6861,49 @@ msgstr "Нет тегов" #: lib/themeuploader.php:50 msgid "This server cannot handle theme uploads without ZIP support." -msgstr "" +msgstr "Этот сервер не может обработать загруженные темы без поддержки ZIP." #: lib/themeuploader.php:58 lib/themeuploader.php:61 -#, fuzzy msgid "Theme upload missing or failed." -msgstr "Системная ошибка при загрузке файла." +msgstr "Ошибка при загрузке файла темы." #: lib/themeuploader.php:91 lib/themeuploader.php:102 #: lib/themeuploader.php:253 lib/themeuploader.php:257 #: lib/themeuploader.php:265 lib/themeuploader.php:272 -#, fuzzy msgid "Failed saving theme." -msgstr "Неудача при обновлении аватары." +msgstr "Ошибка при сохранении темы." #: lib/themeuploader.php:139 msgid "Invalid theme: bad directory structure." -msgstr "" +msgstr "Ошибочная тема. Плохая структура директорий." #: lib/themeuploader.php:166 #, php-format msgid "Uploaded theme is too large; must be less than %d bytes uncompressed." msgstr "" +"Размер загруженной темы слишком велик, в распакованном виде она должна " +"занимать не более %d байт." #: lib/themeuploader.php:178 msgid "Invalid theme archive: missing file css/display.css" -msgstr "" +msgstr "Недопустимый архив: темы. Отсутствует файл css/display.css" #: lib/themeuploader.php:205 msgid "" "Theme contains invalid file or folder name. Stick with ASCII letters, " "digits, underscore, and minus sign." msgstr "" +"Тема содержит недопустимое имя файла или папки. Допустимы буквы ASCII, " +"цифры, подчеркивание и знак минуса." #: lib/themeuploader.php:216 #, php-format msgid "Theme contains file of type '.%s', which is not allowed." -msgstr "" +msgstr "Тема содержит файл недопустимого типа «.%s»." #: lib/themeuploader.php:234 -#, fuzzy msgid "Error opening theme archive." -msgstr "Ошибка обновления удалённого профиля." +msgstr "Ошибка открытия архива темы." #: lib/topposterssection.php:74 msgid "Top posters" diff --git a/locale/statusnet.pot b/locale/statusnet.pot index b95f5f42f9..6661aba7b8 100644 --- a/locale/statusnet.pot +++ b/locale/statusnet.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-06-16 22:18+0000\n" +"POT-Creation-Date: 2010-06-21 18:02+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/locale/sv/LC_MESSAGES/statusnet.po b/locale/sv/LC_MESSAGES/statusnet.po index 40c357d00e..5d8461ca00 100644 --- a/locale/sv/LC_MESSAGES/statusnet.po +++ b/locale/sv/LC_MESSAGES/statusnet.po @@ -10,11 +10,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:21:15+0000\n" +"PO-Revision-Date: 2010-06-21 18:05:03+0000\n" "Language-Team: Swedish\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: sv\n" "X-Message-Group: out-statusnet\n" diff --git a/locale/te/LC_MESSAGES/statusnet.po b/locale/te/LC_MESSAGES/statusnet.po index 96a7bb818f..c5d30c58a5 100644 --- a/locale/te/LC_MESSAGES/statusnet.po +++ b/locale/te/LC_MESSAGES/statusnet.po @@ -10,11 +10,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:21:20+0000\n" +"PO-Revision-Date: 2010-06-21 18:05:08+0000\n" "Language-Team: Telugu\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: te\n" "X-Message-Group: out-statusnet\n" diff --git a/locale/tr/LC_MESSAGES/statusnet.po b/locale/tr/LC_MESSAGES/statusnet.po index 08f281cd38..8f59d84765 100644 --- a/locale/tr/LC_MESSAGES/statusnet.po +++ b/locale/tr/LC_MESSAGES/statusnet.po @@ -10,11 +10,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:21:25+0000\n" +"PO-Revision-Date: 2010-06-21 18:05:12+0000\n" "Language-Team: Turkish\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: tr\n" "X-Message-Group: out-statusnet\n" diff --git a/locale/uk/LC_MESSAGES/statusnet.po b/locale/uk/LC_MESSAGES/statusnet.po index 4db4c94a06..93ef6b48a1 100644 --- a/locale/uk/LC_MESSAGES/statusnet.po +++ b/locale/uk/LC_MESSAGES/statusnet.po @@ -12,11 +12,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:21:32+0000\n" +"PO-Revision-Date: 2010-06-21 18:05:17+0000\n" "Language-Team: Ukrainian\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: uk\n" "X-Message-Group: out-statusnet\n" @@ -940,7 +940,7 @@ msgstr "Невизначений тип адреси %s." #. TRANS: Client error for an already confirmed email/jabbel/sms address. #: actions/confirmaddress.php:96 msgid "That address has already been confirmed." -msgstr "Цю адресу вже було підтверджено." +msgstr "Цю адресу вже підтверджено." #. TRANS: Server error thrown on database error updating e-mail preferences. #. TRANS: Server error thrown on database error removing a registered e-mail address. @@ -970,7 +970,7 @@ msgstr "Підтвердити адресу" #: actions/confirmaddress.php:161 #, php-format msgid "The address \"%s\" has been confirmed for your account." -msgstr "Адресу «%s» було підтверджено для Вашого акаунту." +msgstr "Адресу «%s» підтверджено для Вашого акаунту." #: actions/conversation.php:99 msgid "Conversation" @@ -1129,13 +1129,12 @@ msgid "Theme for the site." msgstr "Тема для цього сайту." #: actions/designadminpanel.php:467 -#, fuzzy msgid "Custom theme" -msgstr "Тема сайту" +msgstr "Своя тема" #: actions/designadminpanel.php:471 msgid "You can upload a custom StatusNet theme as a .ZIP archive." -msgstr "" +msgstr "Ви можете завантажити свою тему для сайту StatusNet як .ZIP архів." #: actions/designadminpanel.php:486 lib/designsettings.php:101 msgid "Change background image" @@ -1195,11 +1194,11 @@ msgstr "Посилання" #: actions/designadminpanel.php:651 msgid "Advanced" -msgstr "" +msgstr "Додатково" #: actions/designadminpanel.php:655 msgid "Custom CSS" -msgstr "" +msgstr "Свій CSS" #: actions/designadminpanel.php:676 lib/designsettings.php:247 msgid "Use defaults" @@ -6844,48 +6843,49 @@ msgstr "Пусто" #: lib/themeuploader.php:50 msgid "This server cannot handle theme uploads without ZIP support." -msgstr "" +msgstr "Цей сервер не може опрацювати завантаження теми без підтримки ZIP." #: lib/themeuploader.php:58 lib/themeuploader.php:61 -#, fuzzy msgid "Theme upload missing or failed." -msgstr "Система відповіла помилкою при завантаженні цього файла." +msgstr "Завантажити тему не вдалося або процес завантаження перервано." #: lib/themeuploader.php:91 lib/themeuploader.php:102 #: lib/themeuploader.php:253 lib/themeuploader.php:257 #: lib/themeuploader.php:265 lib/themeuploader.php:272 -#, fuzzy msgid "Failed saving theme." -msgstr "Оновлення аватари невдале." +msgstr "Помилка при збереженні теми." #: lib/themeuploader.php:139 msgid "Invalid theme: bad directory structure." -msgstr "" +msgstr "Невірна тема: хибна структура каталогів." #: lib/themeuploader.php:166 #, php-format msgid "Uploaded theme is too large; must be less than %d bytes uncompressed." msgstr "" +"Тема, що її було завантажено, надто велика; без компресії розмір має " +"становити менше ніж %d байтів." #: lib/themeuploader.php:178 msgid "Invalid theme archive: missing file css/display.css" -msgstr "" +msgstr "В архіві з темою є помилка: відсутній файл css/display.css" #: lib/themeuploader.php:205 msgid "" "Theme contains invalid file or folder name. Stick with ASCII letters, " "digits, underscore, and minus sign." msgstr "" +"Тема містить неприпустиме ім’я файлу або теки. Використовуйте літери " +"стандарту ASCII, цифри, знаки підкреслення та мінусу." #: lib/themeuploader.php:216 #, php-format msgid "Theme contains file of type '.%s', which is not allowed." -msgstr "" +msgstr "Тема містить файл типу «.%s», який є неприпустимим." #: lib/themeuploader.php:234 -#, fuzzy msgid "Error opening theme archive." -msgstr "Помилка при оновленні віддаленого профілю." +msgstr "Помилка при відкритті архіву з темою." #: lib/topposterssection.php:74 msgid "Top posters" diff --git a/locale/vi/LC_MESSAGES/statusnet.po b/locale/vi/LC_MESSAGES/statusnet.po index 5f2df5bb8b..cc5899b9ed 100644 --- a/locale/vi/LC_MESSAGES/statusnet.po +++ b/locale/vi/LC_MESSAGES/statusnet.po @@ -8,11 +8,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:21:37+0000\n" +"PO-Revision-Date: 2010-06-21 18:05:22+0000\n" "Language-Team: Vietnamese\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: vi\n" "X-Message-Group: out-statusnet\n" diff --git a/locale/zh_CN/LC_MESSAGES/statusnet.po b/locale/zh_CN/LC_MESSAGES/statusnet.po index bd27f2a186..d9afdf9e97 100644 --- a/locale/zh_CN/LC_MESSAGES/statusnet.po +++ b/locale/zh_CN/LC_MESSAGES/statusnet.po @@ -11,11 +11,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:21:41+0000\n" +"PO-Revision-Date: 2010-06-21 18:05:26+0000\n" "Language-Team: Simplified Chinese\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: zh-hans\n" "X-Message-Group: out-statusnet\n" diff --git a/locale/zh_TW/LC_MESSAGES/statusnet.po b/locale/zh_TW/LC_MESSAGES/statusnet.po index a5613b3ac3..e002fd55d5 100644 --- a/locale/zh_TW/LC_MESSAGES/statusnet.po +++ b/locale/zh_TW/LC_MESSAGES/statusnet.po @@ -8,11 +8,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-06-16 22:18+0000\n" -"PO-Revision-Date: 2010-06-16 22:21:46+0000\n" +"PO-Revision-Date: 2010-06-21 18:05:30+0000\n" "Language-Team: Traditional Chinese\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.17alpha (r68131); Translate extension (2010-06-12)\n" +"X-Generator: MediaWiki 1.17alpha (r68367); Translate extension (2010-06-12)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: zh-hant\n" "X-Message-Group: out-statusnet\n" From 87125a1395ed4bf8660e2ba47645835b9d1f4acf Mon Sep 17 00:00:00 2001 From: Siebrand Mazeland Date: Mon, 21 Jun 2010 20:15:26 +0200 Subject: [PATCH 09/25] Improve error message per discussion on http://translatewiki.net/wiki/Thread:Support/Unclear_message. Spotted by Peter17 and changed per suggestion of McDutchie with approval of Brion. --- lib/themeuploader.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/themeuploader.php b/lib/themeuploader.php index 18ef8c4d1a..370965db08 100644 --- a/lib/themeuploader.php +++ b/lib/themeuploader.php @@ -55,10 +55,10 @@ class ThemeUploader public static function fromUpload($name) { if (!isset($_FILES[$name]['error'])) { - throw new ServerException(_("Theme upload missing or failed.")); + throw new ServerException(_("The theme file is missing or the upload failed.")); } if ($_FILES[$name]['error'] != UPLOAD_ERR_OK) { - throw new ServerException(_("Theme upload missing or failed.")); + throw new ServerException(_("The theme file is missing or the upload failed.")); } return new ThemeUploader($_FILES[$name]['tmp_name']); } From b59aba9543b46c4d9e31dbff2c490a9b03539abe Mon Sep 17 00:00:00 2001 From: Siebrand Mazeland Date: Mon, 21 Jun 2010 20:17:32 +0200 Subject: [PATCH 10/25] Update pot file. --- locale/statusnet.pot | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/locale/statusnet.pot b/locale/statusnet.pot index 6661aba7b8..c811492881 100644 --- a/locale/statusnet.pot +++ b/locale/statusnet.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-06-21 18:02+0000\n" +"POT-Creation-Date: 2010-06-21 18:15+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -6396,7 +6396,7 @@ msgid "This server cannot handle theme uploads without ZIP support." msgstr "" #: lib/themeuploader.php:58 lib/themeuploader.php:61 -msgid "Theme upload missing or failed." +msgid "The theme file is missing or the upload failed." msgstr "" #: lib/themeuploader.php:91 lib/themeuploader.php:102 From 1eec7f779fc85b530907ea31deceadb2a30d7614 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 22 Jun 2010 16:28:06 -0700 Subject: [PATCH 11/25] - Add profile_info tag to Atom author - Normalize xmlns:statusnet links in the API --- classes/Notice.php | 4 ++-- classes/Profile.php | 10 +++++++++- lib/apiaction.php | 2 ++ lib/atomnoticefeed.php | 2 +- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/classes/Notice.php b/classes/Notice.php index f8eda5777d..c752e35a72 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -1190,7 +1190,7 @@ class Notice extends Memcached_DataObject 'xmlns:media' => 'http://purl.org/syndication/atommedia', 'xmlns:poco' => 'http://portablecontacts.net/spec/1.0', 'xmlns:ostatus' => 'http://ostatus.org/schema/1.0', - 'xmlns:statusnet' => 'http://status.net/ont/'); + 'xmlns:statusnet' => 'http://status.net/schema/api/1/'); } else { $attrs = array(); } @@ -1225,7 +1225,7 @@ class Notice extends Memcached_DataObject $xs->element('title', null, common_xml_safe_str($this->content)); if ($author) { - $xs->raw($profile->asAtomAuthor()); + $xs->raw($profile->asAtomAuthor($cur)); $xs->raw($profile->asActivityActor()); } diff --git a/classes/Profile.php b/classes/Profile.php index 54f557ea7c..a303469e96 100644 --- a/classes/Profile.php +++ b/classes/Profile.php @@ -849,15 +849,23 @@ class Profile extends Memcached_DataObject * * Assumes that Atom has been previously set up as the base namespace. * + * @param Profile $cur the current authenticated user + * * @return string */ - function asAtomAuthor() + function asAtomAuthor($cur = null) { $xs = new XMLStringer(true); $xs->elementStart('author'); $xs->element('name', null, $this->nickname); $xs->element('uri', null, $this->getUri()); + if ($cur != null) { + $attrs = Array(); + $attrs['following'] = $cur->isSubscribed($this) ? 'true' : 'false'; + $attrs['blocking'] = $cur->hasBlocked($this) ? 'true' : 'false'; + $xs->element('statusnet:profile_info', $attrs, null); + } $xs->elementEnd('author'); return $xs->getString(); diff --git a/lib/apiaction.php b/lib/apiaction.php index 7cc473d512..226481778e 100644 --- a/lib/apiaction.php +++ b/lib/apiaction.php @@ -208,11 +208,13 @@ class ApiAction extends Action // Is the requesting user following this user? $twitter_user['following'] = false; + $twitter_user['statusnet:blocking'] = false; $twitter_user['notifications'] = false; if (isset($this->auth_user)) { $twitter_user['following'] = $this->auth_user->isSubscribed($profile); + $twitter_user['statusnet:blocking'] = $this->auth_user->hasBlocked($profile); // Notifications on? $sub = Subscription::pkeyGet(array('subscriber' => diff --git a/lib/atomnoticefeed.php b/lib/atomnoticefeed.php index ef44de4b6c..6ed803ce4e 100644 --- a/lib/atomnoticefeed.php +++ b/lib/atomnoticefeed.php @@ -95,7 +95,7 @@ class AtomNoticeFeed extends Atom10Feed $this->addNamespace( 'statusnet', - 'http://status.net/ont/' + 'http://status.net/schema/api/1/' ); } From 72e486a3226c9101f33bd86f953dbb9650c19fd1 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 23 Jun 2010 11:29:13 -0700 Subject: [PATCH 12/25] Fix for ticket http://status.net/open-source/issues/2380 "Autofocus shouldn't override scroll" -- Thanks @michaeltwofish! --- js/util.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/util.js b/js/util.js index 1320d11b4b..29b33097b1 100644 --- a/js/util.js +++ b/js/util.js @@ -84,7 +84,7 @@ var SN = { // StatusNet form.find('#'+SN.C.S.NoticeTextCount).text(jQuery.data(form[0], 'ElementData').MaxLength); } - if ($('body')[0].id != 'conversation' && window.location.hash.length === 0) { + if ($('body')[0].id != 'conversation' && window.location.hash.length === 0 && $(window).scrollTop() == 0) { form.find('textarea').focus(); } }, From a6408be566dc9877eb67c86d4283dd57b2255d8b Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Thu, 24 Jun 2010 15:21:04 +0000 Subject: [PATCH 13/25] Regression fix for Recaptcha on SSL registration page; their API is served on a different hostname for SSL. --- plugins/Recaptcha/RecaptchaPlugin.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/Recaptcha/RecaptchaPlugin.php b/plugins/Recaptcha/RecaptchaPlugin.php index f09d81ec00..7cc34c5686 100644 --- a/plugins/Recaptcha/RecaptchaPlugin.php +++ b/plugins/Recaptcha/RecaptchaPlugin.php @@ -77,8 +77,11 @@ class RecaptchaPlugin extends Plugin { if (isset($action->recaptchaPluginNeedsOutput) && $action->recaptchaPluginNeedsOutput) { // Load the AJAX API - $proto = $this->checkssl() ? 'https' : 'http'; - $url = "$proto://api.recaptcha.net/js/recaptcha_ajax.js"; + if ($this->checkssl()) { + $url = "https://api-secure.recaptcha.net/js/recaptcha_ajax.js"; + } else { + $url = "http://api.recaptcha.net/js/recaptcha_ajax.js"; + } $action->script($url); // And when we're ready, fill out the captcha! From 9eb5a976b03fae6bd1e1fce6abfe4a6c7964d1ae Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 24 Jun 2010 18:11:50 -0700 Subject: [PATCH 14/25] Have API methods for search subclass ApiPrivateAuthAction --- actions/{twitapisearchatom.php => apisearchatom.php} | 12 +++++++++--- actions/{twitapisearchjson.php => apisearchjson.php} | 7 +++++-- actions/{twitapitrends.php => apitrends.php} | 8 +++++--- lib/router.php | 6 +++--- 4 files changed, 22 insertions(+), 11 deletions(-) rename actions/{twitapisearchatom.php => apisearchatom.php} (97%) rename actions/{twitapisearchjson.php => apisearchjson.php} (94%) rename actions/{twitapitrends.php => apitrends.php} (93%) diff --git a/actions/twitapisearchatom.php b/actions/apisearchatom.php similarity index 97% rename from actions/twitapisearchatom.php rename to actions/apisearchatom.php index 51e8a8881b..60bb8b0408 100644 --- a/actions/twitapisearchatom.php +++ b/actions/apisearchatom.php @@ -22,7 +22,7 @@ * @category Search * @package StatusNet * @author Zach Copley - * @copyright 2008-2009 StatusNet, Inc. + * @copyright 2008-2010 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ */ @@ -31,6 +31,8 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } +require_once INSTALLDIR.'/lib/apiprivateauth.php'; + /** * Action for outputting search results in Twitter compatible Atom * format. @@ -44,10 +46,10 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ * - * @see ApiAction + * @see ApiPrivateAuthAction */ -class TwitapisearchatomAction extends ApiAction +class ApiSearchAtomAction extends ApiPrivateAuthAction { var $cnt; @@ -96,8 +98,11 @@ class TwitapisearchatomAction extends ApiAction function prepare($args) { + common_debug("in apisearchatom prepare()"); + parent::prepare($args); + $this->query = $this->trimmed('q'); $this->lang = $this->trimmed('lang'); $this->rpp = $this->trimmed('rpp'); @@ -138,6 +143,7 @@ class TwitapisearchatomAction extends ApiAction function handle($args) { parent::handle($args); + common_debug("In apisearchatom handle()"); $this->showAtom(); } diff --git a/actions/twitapisearchjson.php b/actions/apisearchjson.php similarity index 94% rename from actions/twitapisearchjson.php rename to actions/apisearchjson.php index b5c006aa7b..e44634684d 100644 --- a/actions/twitapisearchjson.php +++ b/actions/apisearchjson.php @@ -22,7 +22,7 @@ * @category Search * @package StatusNet * @author Zach Copley - * @copyright 2008-2009 StatusNet, Inc. + * @copyright 2008-2010 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ */ @@ -31,6 +31,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } +require_once INSTALLDIR.'/lib/apiprivateauth.php'; require_once INSTALLDIR.'/lib/jsonsearchresultslist.php'; /** @@ -44,7 +45,7 @@ require_once INSTALLDIR.'/lib/jsonsearchresultslist.php'; * @see ApiAction */ -class TwitapisearchjsonAction extends ApiAction +class ApiSearchJSONAction extends ApiPrivateAuthAction { var $query; var $lang; @@ -64,6 +65,8 @@ class TwitapisearchjsonAction extends ApiAction function prepare($args) { + common_debug("apisearchjson prepare()"); + parent::prepare($args); $this->query = $this->trimmed('q'); diff --git a/actions/twitapitrends.php b/actions/apitrends.php similarity index 93% rename from actions/twitapitrends.php rename to actions/apitrends.php index 5a04569a22..5b74636c69 100644 --- a/actions/twitapitrends.php +++ b/actions/apitrends.php @@ -22,7 +22,7 @@ * @category Search * @package StatusNet * @author Zach Copley - * @copyright 2008-2009 StatusNet, Inc. + * @copyright 2008-2010 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ */ @@ -31,6 +31,8 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } +require_once INSTALLDIR.'/lib/apiprivateauth.php'; + /** * Returns the top ten queries that are currently trending * @@ -43,7 +45,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { * @see ApiAction */ -class TwitapitrendsAction extends ApiAction +class ApiTrendsAction extends ApiPrivateAuthAction { var $callback; @@ -82,7 +84,7 @@ class TwitapitrendsAction extends ApiAction */ function showTrends() { - $this->serverError(_('API method under construction.'), $code = 501); + $this->serverError(_('API method under construction.'), 501); } } \ No newline at end of file diff --git a/lib/router.php b/lib/router.php index fec229c9b6..7e1e6a2a47 100644 --- a/lib/router.php +++ b/lib/router.php @@ -667,9 +667,9 @@ class Router ); // search - $m->connect('api/search.atom', array('action' => 'twitapisearchatom')); - $m->connect('api/search.json', array('action' => 'twitapisearchjson')); - $m->connect('api/trends.json', array('action' => 'twitapitrends')); + $m->connect('api/search.atom', array('action' => 'ApiSearchAtom')); + $m->connect('api/search.json', array('action' => 'ApiSearchJSON')); + $m->connect('api/trends.json', array('action' => 'ApiTrends')); $m->connect('api/oauth/request_token', array('action' => 'apioauthrequesttoken')); From f0c5e7eca3842411d4e3ee6efb3fd6ac0ad85f4a Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Sat, 26 Jun 2010 15:07:32 -0400 Subject: [PATCH 15/25] Fix for bug #2382: releasing claim on failed queue item works again with DB-based queues. Warning: DB-based queue doesn't currently implement discarding of items after a retry limit. Failed items will be retried until they succeed. --- classes/Queue_item.php | 13 +++++++++++++ lib/dbqueuemanager.php | 4 +--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/classes/Queue_item.php b/classes/Queue_item.php index f83c2cef18..c7e17be6e8 100644 --- a/classes/Queue_item.php +++ b/classes/Queue_item.php @@ -64,4 +64,17 @@ class Queue_item extends Memcached_DataObject $qi = null; return null; } + + /** + * Release a claimed item. + */ + function releaseCLaim() + { + // DB_DataObject doesn't let us save nulls right now + $sql = sprintf("UPDATE queue_item SET claimed=NULL WHERE id=%d", $this->id); + $this->query($sql); + + $this->claimed = null; + $this->encache(); + } } diff --git a/lib/dbqueuemanager.php b/lib/dbqueuemanager.php index 3032e4ec7a..3dda9fd1ac 100644 --- a/lib/dbqueuemanager.php +++ b/lib/dbqueuemanager.php @@ -135,9 +135,7 @@ class DBQueueManager extends QueueManager if (empty($qi->claimed)) { $this->_log(LOG_WARNING, "[$queue:item $qi->id] Ignoring failure for unclaimed queue item"); } else { - $orig = clone($qi); - $qi->claimed = null; - $qi->update($orig); + $qi->releaseClaim(); } $this->stats('error', $queue); From 41d81b996fdd8276cc04e750297a12f852a97bf4 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Mon, 10 May 2010 15:32:02 -0700 Subject: [PATCH 16/25] Test cases for MediaFile::getUploadedFileType() with OpenOffice, MS Office, and PDF sample files (as saved from OpenOffice 3.2) Only 3 of 16 cases pass on my dev box with default config. Ouch! --- tests/MediaFileTest.php | 77 +++++++++++++++++++++++++ tests/sample-uploads/office.pdf | Bin 0 -> 1162 bytes tests/sample-uploads/presentation.odp | Bin 0 -> 9330 bytes tests/sample-uploads/presentation.otp | Bin 0 -> 9359 bytes tests/sample-uploads/presentation.pot | Bin 0 -> 71168 bytes tests/sample-uploads/presentation.potm | Bin 0 -> 5789 bytes tests/sample-uploads/presentation.ppt | Bin 0 -> 71168 bytes tests/sample-uploads/presentation.pptx | Bin 0 -> 5790 bytes tests/sample-uploads/spreadsheet.ods | Bin 0 -> 6560 bytes tests/sample-uploads/spreadsheet.ots | Bin 0 -> 6575 bytes tests/sample-uploads/spreadsheet.xls | Bin 0 -> 6656 bytes tests/sample-uploads/spreadsheet.xlsx | Bin 0 -> 6010 bytes tests/sample-uploads/spreadsheet.xlt | Bin 0 -> 6144 bytes tests/sample-uploads/wordproc.doc | Bin 0 -> 9216 bytes tests/sample-uploads/wordproc.docx | Bin 0 -> 3350 bytes tests/sample-uploads/wordproc.odt | Bin 0 -> 7641 bytes tests/sample-uploads/wordproc.ott | Bin 0 -> 7656 bytes tests/sample-uploads/wordproc.rtf | 16 +++++ 18 files changed, 93 insertions(+) create mode 100644 tests/MediaFileTest.php create mode 100644 tests/sample-uploads/office.pdf create mode 100644 tests/sample-uploads/presentation.odp create mode 100644 tests/sample-uploads/presentation.otp create mode 100644 tests/sample-uploads/presentation.pot create mode 100644 tests/sample-uploads/presentation.potm create mode 100644 tests/sample-uploads/presentation.ppt create mode 100644 tests/sample-uploads/presentation.pptx create mode 100644 tests/sample-uploads/spreadsheet.ods create mode 100644 tests/sample-uploads/spreadsheet.ots create mode 100644 tests/sample-uploads/spreadsheet.xls create mode 100644 tests/sample-uploads/spreadsheet.xlsx create mode 100644 tests/sample-uploads/spreadsheet.xlt create mode 100644 tests/sample-uploads/wordproc.doc create mode 100644 tests/sample-uploads/wordproc.docx create mode 100644 tests/sample-uploads/wordproc.odt create mode 100644 tests/sample-uploads/wordproc.ott create mode 100644 tests/sample-uploads/wordproc.rtf diff --git a/tests/MediaFileTest.php b/tests/MediaFileTest.php new file mode 100644 index 0000000000..6fe9956210 --- /dev/null +++ b/tests/MediaFileTest.php @@ -0,0 +1,77 @@ +old_attachments_supported = common_config('attachments', 'supported'); + $GLOBALS['config']['attachments']['supported'] = true; + } + + public function tearDown() + { + $GLOBALS['config']['attachments']['supported'] = $this->old_attachments_supported; + } + + /** + * @dataProvider fileTypeCases + * + */ + public function testFileType($filename, $expectedType) + { + if (!file_exists($filename)) { + throw new Exception("WTF? $filename test file missing"); + } + $this->assertEquals($expectedType, MediaFile::getUploadedFileType($filename)); + } + + static public function fileTypeCases() + { + $base = dirname(__FILE__); + $dir = "$base/sample-uploads"; + return array( + array("$dir/office.pdf", "application/pdf"), + + array("$dir/wordproc.odt", "application/vnd.oasis.opendocument.text"), + array("$dir/wordproc.ott", "application/vnd.oasis.opendocument.text-template"), + array("$dir/wordproc.doc", "application/msword"), + array("$dir/wordproc.docx", + "application/vnd.openxmlformats-officedocument.wordprocessingml.document"), + array("$dir/wordproc.rtf", "text/rtf"), + + array("$dir/spreadsheet.ods", + "application/vnd.oasis.opendocument.spreadsheet"), + array("$dir/spreadsheet.ots", + "application/vnd.oasis.opendocument.spreadsheet-template"), + array("$dir/spreadsheet.xls", "application/vnd.ms-excel"), + array("$dir/spreadsheet.xlt", "application/vnd.ms-excel"), + array("$dir/spreadsheet.xlsx", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"), + + array("$dir/presentation.odp", + "application/vnd.oasis-opendocument.presentation"), + array("$dir/presentation.otp", + "application/vnd.oasis-opendocument.presentation-template"), + array("$dir/presentation.ppt", + "application/vnd.ms-powerpoint"), + array("$dir/presentation.pot", + "application/vnd.ms-powerpoint"), + array("$dir/presentation.pptx", + "application/vnd.openxmlformats-officedocument.presentationml.presentation"), + ); + } + +} + diff --git a/tests/sample-uploads/office.pdf b/tests/sample-uploads/office.pdf new file mode 100644 index 0000000000000000000000000000000000000000..670bc2343e9cbfee1eb0a6eb6ff4733fc1b8dae7 GIT binary patch literal 1162 zcmah}!EVz)5bX`L;v@DFwMCTO_1fzgMUfIat_nqsoKym$9*nb14XHP>*Hy}iBbWXG z5|3LvA)UHO{%osWLzyacdQom4qtO z*q|ary17bvQV$4JLi%#5Pu7FjDyV-sk)#`s%qy2bU>gDw$wHNRA`5H;BJx}g)3~js z0}4mMEbMyL3E9t8If0J!NI#FWVqzGQOXBxPATQEHM*D4YfOTF%Q-}}gfk1&xE2Fg% zjN-DjRW=3MOaZNO0DP4MK0)MJIxGg*6cw4HuS%$cttq%03Vy8Pu^P?mE*2Fdax{@y zE77US1`8_k;^ixxmE-Z^MS=P-&PF>j+dJ;XO)dI?~aXexV;S=7cgZTHfH}L)`gqdz}e!it|QhobRMT;nVT=Sm%fwOBau=X zo0)(QKu$>eQO uo@2s2zs)?+Vtx?XF8nyOZM7M%+rk&VPt7zHI?naH)ovaBdTO1c5d8)1-7zu% literal 0 HcmV?d00001 diff --git a/tests/sample-uploads/presentation.odp b/tests/sample-uploads/presentation.odp new file mode 100644 index 0000000000000000000000000000000000000000..8dd3a428bc3c42586770a37f6894803d479319d5 GIT binary patch literal 9330 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 YKLk=eO#;G0HVW+L3-%#D5_EXm&i?&E<7GD*w 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 F_J3^OcBB9R literal 0 HcmV?d00001 diff --git a/tests/sample-uploads/presentation.pot b/tests/sample-uploads/presentation.pot new file mode 100644 index 0000000000000000000000000000000000000000..f5124ffa2b25669b2b442452771f23de0a46e7a5 GIT binary patch literal 71168 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 literal 0 HcmV?d00001 diff --git a/tests/sample-uploads/presentation.potm b/tests/sample-uploads/presentation.potm new file mode 100644 index 0000000000000000000000000000000000000000..ade1bcb10fda6e20ea38931b7aaf31e26fc5c7c1 GIT binary patch literal 5789 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 WqpL-L9V7q%g#8F&w_nCT-}*nWOLxiu literal 0 HcmV?d00001 diff --git a/tests/sample-uploads/presentation.ppt b/tests/sample-uploads/presentation.ppt new file mode 100644 index 0000000000000000000000000000000000000000..f5124ffa2b25669b2b442452771f23de0a46e7a5 GIT binary patch literal 71168 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 literal 0 HcmV?d00001 diff --git a/tests/sample-uploads/presentation.pptx b/tests/sample-uploads/presentation.pptx new file mode 100644 index 0000000000000000000000000000000000000000..21ea61a1590f3895992071d93ce52573f2e247ec GIT binary patch literal 5790 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 Vig__eC@Ax4ky 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 literal 0 HcmV?d00001 diff --git a/tests/sample-uploads/spreadsheet.ots b/tests/sample-uploads/spreadsheet.ots new file mode 100644 index 0000000000000000000000000000000000000000..5f830e6def09a7379b7760b82064d8c232f25b8c GIT binary patch literal 6575 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 D_kSmS literal 0 HcmV?d00001 diff --git a/tests/sample-uploads/spreadsheet.xls b/tests/sample-uploads/spreadsheet.xls new file mode 100644 index 0000000000000000000000000000000000000000..2d470e68713923544ad8d36556928c0142e225df GIT binary patch literal 6656 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 literal 0 HcmV?d00001 diff --git a/tests/sample-uploads/spreadsheet.xlt b/tests/sample-uploads/spreadsheet.xlt new file mode 100644 index 0000000000000000000000000000000000000000..980423b20f315ee3ca980928ac7c7528d4a896f4 GIT binary patch literal 6144 zcmeHLU1(fI6h3$VdN)avO`23~ZM;Ui`P+upJXq11P10x!)`qsC4~4qf?xtzC-4a)* zpt!9T6dF)k=u1Hgc`1TF2>PI40zQZ+iqZ#tN_{K(uoXoLHtYADd#}B&yL7iMO3R+* zo0&a#=AM~z&YUxIzxld->HPa^E=dVJEPh!oh9%_T8)%2!{}B-%+T<-4i$#}>W`k}a z4P0~PN*e}X#2`SMuK-Md{3fTqg_hNrYLyz;C0YD(V#$OYK|L!kz}nT*YIuxSR5c^L z@uHgkH|o=ne_aDN(iNY3_0RatIPM3^?SIC5?*C?>1y~8R0&M_NfV2Z0z$%~<=mJ&) zcK~++cL8gFwZPrLI-nc42e5#9fga#K;C^5|!1?t$HQNJd4+1fVH{{gUSKVmctOmj+ ztQZQ)$1A^N$k*6^2_ErYU{U?zNAUK_QToPsB9pZKD;m=|Bn<_#Z$=~{&4J^mOWawqBP_q9rJ^7Ho-SPN3Y_`Z#WwvXpABT z&PYNsQt}l2>h-ic&?589v5!wYIk9W>i6z}T^YUBKf)tk)Eb=)q<^Nh8pQ|p{zY?Es zE!Y3{<7MJIctLH&m4~0^Ge+7Q50)LWD0Y^h@*^4_Z8*_ z(=$Z-J-j;YC! zeag@4F;(9q>#0sD%5gkd3=HUqK`l>c-%e~f^oWi}N4t>CFyrX>WMVpHMJHd;Zm((? z#Vd!EE|2tj+I?uJl?o&Mp7wd^!36gM{GE`P5i{KJZf(d@cz3hBq*+vqGtJDPARn`- zmwuK>F1fG`Of0uRg;DREd7JnP8_{f&fNd)Y7pUn{@=249;~1XkAN6&}hw2}3PuF#P zpZ#A2pg9d=O?ylP%`>yG(`{uWUmcBPd5r|!)odh;`O8RZjyTFk;83K7k({0Q?{?Bg zuaOXxYBmza)YC|6TNDOPyMAmf?y`u<7>o0cmhu?S%sXb1v)Sje>6|rjESbt!4?VbH zPhu*S$)xnCHa3$^+eaRIOwA=WzAd!ok@kRP#0H+rN{Inw>Ev6#T-|vf^7fmi4EBET zJtNl{fN6=(;{XDbYy)`Dcm`mUq2u$uaTI{syKT1XDfKY65d|$cu%4} z2u5>`0a!981JH#QISwqT~2XHded-e)Rp!d1X+xLPApK fkkT(uwasVqO{{+dWak|D^{8sqzxVsg|1JMd3gb%2 literal 0 HcmV?d00001 diff --git a/tests/sample-uploads/wordproc.doc b/tests/sample-uploads/wordproc.doc new file mode 100644 index 0000000000000000000000000000000000000000..81c5e34c6caab43a0d52e3cec241d72e423a8eac GIT binary patch literal 9216 zcmeI1PfT1z7{I@`ER;o{TR?0nl`X|mX$$2~E7;b;mQqSZ+EPpXpDlj`gjh7zE`uk?za~BHiTSA&vb~e8^ z^JeDF_suuo%)Xg-_16tIE`3$@yDSL%B}?XFKFLYSw@9yd?)@Sj(wa9Hi^ZI5l9})T zS>TSXtB#?ULCgjn^L3C5KFEWIARh{#5VSrnVB!a;yBSp%Sm2aI_)SVcj!2j|DsM5W z?n5aaliZ}6CzIC;H}zB1$;eMwAeF7OJlX!v`kn6l*Z%>X{~MqPilGD^hEjM0Ho_(- zgUz5awh%uG754pB;!4;CRqz;WhicdXk3$XYgk7*3YM~DHKs_`-BQ(KY*auHQGqk{y zupbVmKQkMkXRdlYzcSbYORTZ{iwj+@(lTX5cwHWEAusS|;xzOkuK9P&BgFiV zwacIkNl2z-l=UtCuU20rHC0xl1Z$+HD@#to;jWD`*6H(3!0}E?PIP%C-097InK(q* zE1fOgNmxXeptQB#id`~(vj2j%*9qyDVNxULq$N?KQ=-uh znX9nGW2q0W!vhDYGeGUIyh=_1y)3?bQ%WwMmz*k#8P?O4jr!TBUv5;6t6R<-3Hr4i zohv>(b5PDBDS&Pf+S4^Yk5MbW%&es?k#ec?TUL=(PTGs7kD#eq%VTEv0i#u=r88(9 zb0s9>l#b9=n4AJufMQzFmh#c6&=_-HuBCQ+Dc7nrPd5)w3HSoC z&Fh8nN0XWEg_jl&=zEO5z-T(hZbRGG;L(LkgJv*^sS>Yrv~H5$?i#ndlip_BCxkn*Od)BSI8{ic@u3`d z?dW8Bjb5H%It9>Q`#XVf)qOgZ5|k(F9%Qhs+>5L-KVqz5WBKoU|Jd#{V=|l@Ggj&z z@67y{MPh!P>MWGfu-Gg$1(}N*3l!~fQ!BkX3+6+>S>*z`=qm=d!+%;{n9w(!v)ZN(|e$j{=5@^ z2hw(e(UC|v5Wm+lmC*`LXmt|Anx3Be@qqbZpZzb^#+F42XHcRAO(z8vZ^{qM+{+||5 zKT$ut*TEy#@3qK`yo?1h7Pzl0pzkG_u!b#Qzvr!C3#{d?Th18?TarvzTNcngj#ViY zvsdc^vo{WIoeg^{VcSgDTLq0LIDv1F!bLWINp@Ol|EwDr&$VB!eOkNO|KZ2%pLgB< zvYou_1$lZ#%L$O#2dYAT&}Vgzyi`8LnXpP0Sk3Q$I(`ekAuOgQ8(g`fABhMSr^$M7 zI?flBa~v(E8;bB2^%p(B&~F%SpLZl#$Q|WSbEP2<=_*(Izq{7b2cBM=PT8r z(3Y>VHMr@A>bk`~6wl@mcMALK(Y1d2)zkSQMkH!-5@-BNwYvlPde*MZxs|Wq7=ExD z>@%_k_(~Ju%ZO?+hz65(Y3itK1^o}utaEOaeV63)?9sde`OhKWeGgOHzzn>7NnLyX H_uqd3i08!l literal 0 HcmV?d00001 diff --git a/tests/sample-uploads/wordproc.docx b/tests/sample-uploads/wordproc.docx new file mode 100644 index 0000000000000000000000000000000000000000..04ea3c3ec18be5009329677c9327d3dacfe8e91e GIT binary patch literal 3350 zcmaJ@c|4T+8yzMY+YKWIg_&?MVXPrbi0lR>%h;KWWrjiaU0H@}FkK2INm7=`lr=l$ z+6p%mm9@pbWo&n*d+&$({cg|u&-A&kqAZQ(LIExfSC#rK+^CJ*Jv-0?;h*ara-f{lpHWBGxv5S0ahQcCtVdNSh z(vT69utRcwO6`wG2LK@dlYt}uGT`SQ?B(W1>-_Hd1>6XNeW&3WY&nqc47Ecfw6Iw3 zXtrg|Lgu7aoice!j%~H<*2)9;iG)UVQj?pfdLaIB$8A@vUI76G#23 znO=8MZl7`zuqMiYL}VO8g)eJt`DdCwpJzy)nK!&KO=nm#Xfb|Itc`V67ekWD6w8PX zc!r*sdC@vj1WH708hvevh@8CCD3YzfP)|X%)4?@R+M5IORiU=A(J6Gfzxyy*M@KMl zl$T{ST3StKGQAlVHOmy6pwx>0meV2OAcjfdWHS=czw(IPJiI37OhW%5Bb84&{5EEd z?K`$ZZ@^ikR7xc7rKRTtr00pH+I&D#I^Saj+lT!D(uFE85fTRZPRg>o&lb!dfrYV9 zPN4;kWx|-bdcjFKNqT_yDU)l3m@{n)T{m(W|$u_H;1WYbf|f{GwbCGJio?8@3d`9=8cdC z#r8J|Z|e@gU@h^n~&Ac;LZ@86YXYW^u4Pv__oXc zctC%E-R#lgpuO=IH^G(0FIZkD*Omu=a5V*E_|(y|yN#0+?qBU}P*G&;f<1I&5;-3- zqw1UZz?-`!U<^}87?+c?lje=U?<_LdDJDI!BU!(I1YVrQk7{OC7AiW(Z+#o8cW@~t z2t5EG$oR9N;`n!{4hky8yc^q$U~O0sFMb1+bO9H;SLeM|gf8D|=pBZB}6_6dG0)Nkklzz}$!l6I4gT)0JEcotcxxI(3vP#2tpT z?ddcyPKYJu_9-MWL!o-2r0CYu7_y7b22^R;b_8?!G2 zegp4)E;y1YwQB8oQcvXRfKke%)l+;j&&VTPqdHS`20{tuzK~Tf6K_vy1Tl|`S^vYlOTt@Metkvjl&`E)LW zCM5dFk-|y|QVldsXF5bJsA`B}&ER83eiE85&!N?J40VRP%&L{2;VGZjk;J7ByiNS~ ztIn?o9GbbeCEvYn4MCB2!qv6#KC3}#14q}{DC$>EZ0ZbAo>^~sSnEnQw6)3XajwOl zJQdlyZ0WPbK;s8kIRSk~?cRbq&HrtWEYv6d-VJ~6gLGpi|DUGcm$2A zNeeo@lCHU^P8=|}j*=)Ii_3T7)K5)lGx~C0UdFd58;UkH?@)DyRo+YUeM{cRij>W} zB{MkW(P>*tU$v#TeM&KeyFxfl6m4IKDyvkII%*Q^+V6NL_`dI^hx|3xAUpS+(A!F^ zJ&P9d=Xy0ugO{w8tjJHUiQTo;4cx=X(-*nWHga zYvU#MLH6+R_>K2Wi$h(x^Ocfc^B!W@B|$G5LGWuI`BusHQ-NYEY5dPaJ@Yg}LGHt2 z1I;o{YIQ-M8_zL74PoFcAGVR!SxCF4*O?WhaC5<8S4g)DUwHg+p7A;$iW5&zI4c!A z8N@Y>Rm{I*o@D(oB20s+ps_FZFc?_K&=&d7(s$wAr$mb&-E)g7s4MqeMFTav2N0}n zNMlruMw?)-Y1u0aKezTW&ZrSe5xNBM3GWnbV4MzN1rE{jHP2v*H-$X7H>L<~#b zG#$D=y%aIXvTh6hvJTy3qVW=KY4&D>+BN#8ynv}s*lJVViJHqC&IkLr`PtE^sn1X| zZ9%YK-Pld)gc}@#uxsh72+3&0BTl$Da1y?1t6Pjj_EtxOqDjm}5SQ`#UO%!$Ng(#m&qQ;%-(pQ}5DbiGIMwA|- z-mb;G+4jtJQ#fJ)a(m7!^|#KFAinpjFu&FG)>Zo5i6MP|aL&1q-1j`MA{Na9P5eSY zX3`F;Mg_APg3@1#ETSnr_7}DnD;04xe#67|Z7 zYd_)-Iv&mG_X~RXJKz5icu>;cf43Yp82yhu{s=!f`83_{7Xfqt{*Md%h(36(Gt8{0ODO;V literal 0 HcmV?d00001 diff --git a/tests/sample-uploads/wordproc.odt b/tests/sample-uploads/wordproc.odt new file mode 100644 index 0000000000000000000000000000000000000000..fa6fe5e9ff0f2485b7bdb8390735c89954baec0b GIT binary patch literal 7641 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 GeD)tte=w2& literal 0 HcmV?d00001 diff --git a/tests/sample-uploads/wordproc.rtf b/tests/sample-uploads/wordproc.rtf new file mode 100644 index 0000000000..aad2c4605e --- /dev/null +++ b/tests/sample-uploads/wordproc.rtf @@ -0,0 +1,16 @@ +{\rtf1\ansi\deff0\adeflang1025 +{\fonttbl{\f0\froman\fprq2\fcharset128 Times New Roman;}{\f1\froman\fprq2\fcharset128 Times New Roman;}{\f2\fswiss\fprq2\fcharset128 Arial;}{\f3\fnil\fprq2\fcharset128 DejaVu Sans;}} +{\colortbl;\red0\green0\blue0;\red128\green128\blue128;} +{\stylesheet{\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af3\afs24\lang1081\ltrch\dbch\af3\langfe2052\hich\f0\fs24\lang1033\loch\f0\fs24\lang1033\snext1 Normal;} +{\s2\sb240\sa120\keepn\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\afs28\lang1081\ltrch\dbch\langfe2052\hich\f2\fs28\lang1033\loch\f2\fs28\lang1033\sbasedon1\snext3 Heading;} +{\s3\sa120\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af3\afs24\lang1081\ltrch\dbch\af3\langfe2052\hich\f0\fs24\lang1033\loch\f0\fs24\lang1033\sbasedon1\snext3 Body Text;} +{\s4\sa120\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af3\afs24\lang1081\ltrch\dbch\af3\langfe2052\hich\f0\fs24\lang1033\loch\f0\fs24\lang1033\sbasedon3\snext4 List;} +{\s5\sb120\sa120\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af3\afs24\lang1081\ai\ltrch\dbch\af3\langfe2052\hich\f0\fs24\lang1033\i\loch\f0\fs24\lang1033\i\sbasedon1\snext5 caption;} +{\s6\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af3\afs24\lang1081\ltrch\dbch\af3\langfe2052\hich\f0\fs24\lang1033\loch\f0\fs24\lang1033\sbasedon1\snext6 Index;} +} +{\info{\author Brion }{\creatim\yr2010\mo5\dy10\hr15\min2}{\revtim\yr0\mo0\dy0\hr0\min0}{\printim\yr0\mo0\dy0\hr0\min0}{\comment StarWriter}{\vern3200}}\deftab709 +{\*\pgdsctbl +{\pgdsc0\pgdscuse195\pgwsxn12240\pghsxn15840\marglsxn1134\margrsxn1134\margtsxn1134\margbsxn1134\pgdscnxt0 Standard;}} +\paperh15840\paperw12240\margl1134\margr1134\margt1134\margb1134\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn1134\margrsxn1134\margtsxn1134\margbsxn1134\ftnbj\ftnstart1\ftnrstcont\ftnnar\aenddoc\aftnrstcont\aftnstart1\aftnnrlc +\pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af3\afs24\lang1081\ltrch\dbch\af3\langfe2052\hich\f0\fs24\lang1033\loch\f0\fs24\lang1033 +\par } \ No newline at end of file From 9c7b66984c46668f314f93337d28c62854b6d134 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Mon, 10 May 2010 16:18:29 -0700 Subject: [PATCH 17/25] Enhanced upload file type detection. If given an original filename, we'll attempt to detect type from the extension if we were unable to make a definitive match from content. Generic octet-stream, zip, and MS Office type are explicitly singled out for re-checks, which fixes OpenOffice and MS Office documents to come up with the proper types when misdetected. File extensions can also be added to the upload type whitelist; they'll be normalized to types for the actual comparison, so only known extensions will work. --- lib/mediafile.php | 54 +++++++++++++++++++++-- tests/MediaFileTest.php | 73 ++++++++++++++++++++------------ tests/sample-uploads/image.gif | Bin 0 -> 35 bytes tests/sample-uploads/image.jpeg | Bin 0 -> 306 bytes tests/sample-uploads/image.jpg | Bin 0 -> 306 bytes tests/sample-uploads/image.png | Bin 0 -> 159 bytes 6 files changed, 97 insertions(+), 30 deletions(-) create mode 100644 tests/sample-uploads/image.gif create mode 100644 tests/sample-uploads/image.jpeg create mode 100644 tests/sample-uploads/image.jpg create mode 100644 tests/sample-uploads/image.png diff --git a/lib/mediafile.php b/lib/mediafile.php index 10d90d0081..85d673d92a 100644 --- a/lib/mediafile.php +++ b/lib/mediafile.php @@ -180,7 +180,8 @@ class MediaFile return; } - $mimetype = MediaFile::getUploadedFileType($_FILES[$param]['tmp_name']); + $mimetype = MediaFile::getUploadedFileType($_FILES[$param]['tmp_name'], + $_FILES[$param]['name']); $filename = null; @@ -241,19 +242,41 @@ class MediaFile return new MediaFile($user, $filename, $mimetype); } - static function getUploadedFileType($f) { + /** + * Attempt to identify the content type of a given file. + * + * @param mixed $f file handle resource, or filesystem path as string + * @param string $originalFilename (optional) for extension-based detection + * @return string + * + * @fixme is this an internal or public method? It's called from GetFileAction + * @fixme this seems to tie a front-end error message in, kinda confusing + * @fixme this looks like it could return a PEAR_Error in some cases, if + * type can't be identified and $config['attachments']['supported'] is true + * + * @throws ClientException if type is known, but not supported for local uploads + */ + static function getUploadedFileType($f, $originalFilename=false) { require_once 'MIME/Type.php'; + require_once 'MIME/Type/Extension.php'; + $mte = new MIME_Type_Extension(); $cmd = &PEAR::getStaticProperty('MIME_Type', 'fileCmd'); $cmd = common_config('attachments', 'filecommand'); $filetype = null; + // If we couldn't get a clear type from the file extension, + // we'll go ahead and try checking the content. Content checks + // are unambiguous for most image files, but nearly useless + // for office document formats. + if (is_string($f)) { // assuming a filename $filetype = MIME_Type::autoDetect($f); + } else { // assuming a filehandle @@ -262,7 +285,32 @@ class MediaFile $filetype = MIME_Type::autoDetect($stream['uri']); } - if (common_config('attachments', 'supported') === true || in_array($filetype, common_config('attachments', 'supported'))) { + // The content-based sources for MIME_Type::autoDetect() + // are wildly unreliable for office-type documents. If we've + // gotten an unclear reponse back or just couldn't identify it, + // we'll try detecting a type from its extension... + $unclearTypes = array('application/octet-stream', + 'application/vnd.ms-office', + 'application/zip'); + + if ($originalFilename && (!$filetype || in_array($filetype, $unclearTypes))) { + $type = $mte->getMIMEType($originalFilename); + if (is_string($type)) { + $filetype = $type; + } + } + + $supported = common_config('attachments', 'supported'); + if (is_array($supported)) { + // Normalize extensions to mime types + foreach ($supported as $i => $entry) { + if (strpos($entry, '/') === false) { + common_log(LOG_INFO, "sample.$entry"); + $supported[$i] = $mte->getMIMEType("sample.$entry"); + } + } + } + if ($supported === true || in_array($filetype, $supported)) { return $filetype; } $media = MIME_Type::getMedia($filetype); diff --git a/tests/MediaFileTest.php b/tests/MediaFileTest.php index 6fe9956210..a76a4f45e6 100644 --- a/tests/MediaFileTest.php +++ b/tests/MediaFileTest.php @@ -34,43 +34,62 @@ class MediaFileTest extends PHPUnit_Framework_TestCase if (!file_exists($filename)) { throw new Exception("WTF? $filename test file missing"); } - $this->assertEquals($expectedType, MediaFile::getUploadedFileType($filename)); + + $type = MediaFile::getUploadedFileType($filename, basename($filename)); + $this->assertEquals($expectedType, $type); + } + + /** + * @dataProvider fileTypeCases + * + */ + public function testUploadedFileType($filename, $expectedType) + { + if (!file_exists($filename)) { + throw new Exception("WTF? $filename test file missing"); + } + $tmp = tmpfile(); + fwrite($tmp, file_get_contents($filename)); + + $type = MediaFile::getUploadedFileType($tmp, basename($filename)); + $this->assertEquals($expectedType, $type); } static public function fileTypeCases() { $base = dirname(__FILE__); $dir = "$base/sample-uploads"; - return array( - array("$dir/office.pdf", "application/pdf"), + $files = array( + "image.png" => "image/png", + "image.gif" => "image/gif", + "image.jpg" => "image/jpeg", + "image.jpeg" => "image/jpeg", + + "office.pdf" => "application/pdf", - array("$dir/wordproc.odt", "application/vnd.oasis.opendocument.text"), - array("$dir/wordproc.ott", "application/vnd.oasis.opendocument.text-template"), - array("$dir/wordproc.doc", "application/msword"), - array("$dir/wordproc.docx", - "application/vnd.openxmlformats-officedocument.wordprocessingml.document"), - array("$dir/wordproc.rtf", "text/rtf"), + "wordproc.odt" => "application/vnd.oasis.opendocument.text", + "wordproc.ott" => "application/vnd.oasis.opendocument.text-template", + "wordproc.doc" => "application/msword", + "wordproc.docx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + "wordproc.rtf" => "text/rtf", - array("$dir/spreadsheet.ods", - "application/vnd.oasis.opendocument.spreadsheet"), - array("$dir/spreadsheet.ots", - "application/vnd.oasis.opendocument.spreadsheet-template"), - array("$dir/spreadsheet.xls", "application/vnd.ms-excel"), - array("$dir/spreadsheet.xlt", "application/vnd.ms-excel"), - array("$dir/spreadsheet.xlsx", - "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"), + "spreadsheet.ods" => "application/vnd.oasis.opendocument.spreadsheet", + "spreadsheet.ots" => "application/vnd.oasis.opendocument.spreadsheet-template", + "spreadsheet.xls" => "application/vnd.ms-excel", + "spreadsheet.xlt" => "application/vnd.ms-excel", + "spreadsheet.xlsx" => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", - array("$dir/presentation.odp", - "application/vnd.oasis-opendocument.presentation"), - array("$dir/presentation.otp", - "application/vnd.oasis-opendocument.presentation-template"), - array("$dir/presentation.ppt", - "application/vnd.ms-powerpoint"), - array("$dir/presentation.pot", - "application/vnd.ms-powerpoint"), - array("$dir/presentation.pptx", - "application/vnd.openxmlformats-officedocument.presentationml.presentation"), + "presentation.odp" => "application/vnd.oasis.opendocument.presentation", + "presentation.otp" => "application/vnd.oasis.opendocument.presentation-template", + "presentation.ppt" => "application/vnd.ms-powerpoint", + "presentation.pptx" => "application/vnd.openxmlformats-officedocument.presentationml.presentation", ); + + $dataset = array(); + foreach ($files as $file => $type) { + $dataset[] = array("$dir/$file", $type); + } + return $dataset; } } diff --git a/tests/sample-uploads/image.gif b/tests/sample-uploads/image.gif new file mode 100644 index 0000000000000000000000000000000000000000..b636f4b8df536b0a85e7cea1a6cf3f0bd3179b96 GIT binary patch literal 35 jcmZ?wbh9u|WMp7uXkcLY4+c66KmZb9U}AD%WUvMRyAlZ1 literal 0 HcmV?d00001 diff --git a/tests/sample-uploads/image.jpeg b/tests/sample-uploads/image.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..21fcb5aef4f885ba2de26b136bec29a3056fcc86 GIT binary patch literal 306 zcmb7;NeaS15Ji94X}cvMu}st;rlY}oxDcE`@Ct&0Zbk53p1_5NaM*Yf+t!`B@)gwL z@oTVWdq;IToD4xk7`uXfARcU2i`{D3*>861&S)~5+ZzUu!t*>KU6WFlRiKq4^8HG{ zQLV-ibKGb*5FmVdKX1cKZZ!RX^~RQB=&=X)#B literal 0 HcmV?d00001 diff --git a/tests/sample-uploads/image.jpg b/tests/sample-uploads/image.jpg new file mode 100644 index 0000000000000000000000000000000000000000..21fcb5aef4f885ba2de26b136bec29a3056fcc86 GIT binary patch literal 306 zcmb7;NeaS15Ji94X}cvMu}st;rlY}oxDcE`@Ct&0Zbk53p1_5NaM*Yf+t!`B@)gwL z@oTVWdq;IToD4xk7`uXfARcU2i`{D3*>861&S)~5+ZzUu!t*>KU6WFlRiKq4^8HG{ zQLV-ibKGb*5FmVdKX1cKZZ!RX^~RQB=&=X)#B literal 0 HcmV?d00001 diff --git a/tests/sample-uploads/image.png b/tests/sample-uploads/image.png new file mode 100644 index 0000000000000000000000000000000000000000..60cbcfd17f345e65baf596c61f53985977f5a89e GIT binary patch literal 159 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1SBVv2j2s6ii6yp7}lMWc?slj7I;J!Gca%q zgD@k*tT_@uLG}_)Usv{9tlZ*U3Ogzu=mUi$OI#yLobz*YQ}ap~oQqNuOHxx5$}>wc x6x=<11Hv2m#DR) Date: Mon, 28 Jun 2010 14:41:33 -0400 Subject: [PATCH 18/25] Fix for PHP notice when given an integer degrees in decimalDegreesToDMS(); using math instead of string manipulation to split integer portion from decimal remainder. --- lib/noticelist.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/noticelist.php b/lib/noticelist.php index 432ea78d5b..e23cf3b6d5 100644 --- a/lib/noticelist.php +++ b/lib/noticelist.php @@ -463,12 +463,14 @@ class NoticeListItem extends Widget $this->out->elementEnd('span'); } + /** + * @param number $dec decimal degrees + * @return array split into 'deg', 'min', and 'sec' + */ function decimalDegreesToDMS($dec) { - - $vars = explode(".",$dec); - $deg = $vars[0]; - $tempma = "0.".$vars[1]; + $deg = intval($dec); + $tempma = abs($dec) - abs($deg); $tempma = $tempma * 3600; $min = floor($tempma / 60); From d87b3f3d2e4b15de14987f431981445c1c9db1be Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 28 Jun 2010 12:02:08 -0700 Subject: [PATCH 19/25] Add notice source for StatusNet Desktop --- db/notice_source.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/db/notice_source.sql b/db/notice_source.sql index f5db37f04e..6bfd5c5f15 100644 --- a/db/notice_source.sql +++ b/db/notice_source.sql @@ -51,6 +51,7 @@ VALUES ('smob','SMOB','http://smob.sioc-project.org/', now()), ('socialoomphBfD4pMqz31', 'SocialOomph', 'http://www.socialoomph.com/', now()), ('spaz','Spaz','http://funkatron.com/spaz', now()), + ('StatusNet Desktop', 'StatusNet Desktop', 'http://status.net/desktop', now()), ('tarpipe','tarpipe','http://tarpipe.com/', now()), ('tjunar','Tjunar','http://nederflash.nl/boek/titels/tjunar-air', now()), ('tr.im','tr.im','http://tr.im/', now()), From c9863bb864d67e5a88f5f9647ba9727d740692a2 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Mon, 28 Jun 2010 15:08:01 -0400 Subject: [PATCH 20/25] Update version and code name: 0.9.3 Half a World Away --- README | 4 ++-- lib/common.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README b/README index c47d3499fa..452123db49 100644 --- a/README +++ b/README @@ -2,8 +2,8 @@ README ------ -StatusNet 0.9.2 ("King of Birds") -3 May 2010 +StatusNet 0.9.3 ("Half a World Away") +29 June 2010 This is the README file for StatusNet, the Open Source microblogging platform. It includes installation instructions, descriptions of diff --git a/lib/common.php b/lib/common.php index 064f6f73a6..817434b976 100644 --- a/lib/common.php +++ b/lib/common.php @@ -22,10 +22,10 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } //exit with 200 response, if this is checking fancy from the installer if (isset($_REQUEST['p']) && $_REQUEST['p'] == 'check-fancy') { exit; } -define('STATUSNET_VERSION', '0.9.2'); +define('STATUSNET_VERSION', '0.9.3'); define('LACONICA_VERSION', STATUSNET_VERSION); // compatibility -define('STATUSNET_CODENAME', 'King of Birds'); +define('STATUSNET_CODENAME', 'Half a World Away'); define('AVATAR_PROFILE_SIZE', 96); define('AVATAR_STREAM_SIZE', 48); From dcfe5b24f6047aa830f107628aa3c10b9d292951 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Mon, 28 Jun 2010 15:20:50 -0400 Subject: [PATCH 21/25] Fix regression in 92ded7c6cb56056a89bc8b3caabd08049104898e: spewed PHP notices when checking for enclosures due to uninitialized variables. --- classes/File.php | 1 + 1 file changed, 1 insertion(+) diff --git a/classes/File.php b/classes/File.php index 0cd31075d2..0f230a6ee5 100644 --- a/classes/File.php +++ b/classes/File.php @@ -302,6 +302,7 @@ class File extends Memcached_DataObject if(! isset($this->filename)){ $notEnclosureMimeTypes = array(null,'text/html','application/xhtml+xml'); + $mimetype = $this->mimetype; if($mimetype != null){ $mimetype = strtolower($this->mimetype); } From 923d9ef71ce49bfa55460bf42acb8a35bf3e84be Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 28 Jun 2010 16:53:05 -0700 Subject: [PATCH 22/25] - Fix bugs with block and friendship API methods - Friendship API methods now use a Profile instead of User for target --- actions/apiblockcreate.php | 4 ++-- actions/apiblockdestroy.php | 4 ++-- actions/apifriendshipscreate.php | 6 +++--- actions/apifriendshipsdestroy.php | 7 +++---- actions/apifriendshipsexists.php | 19 ++++++++----------- lib/apiaction.php | 28 ++++++++++++++++++++++++++++ 6 files changed, 46 insertions(+), 22 deletions(-) diff --git a/actions/apiblockcreate.php b/actions/apiblockcreate.php index c26485f591..b355cd1c7e 100644 --- a/actions/apiblockcreate.php +++ b/actions/apiblockcreate.php @@ -23,7 +23,7 @@ * @package StatusNet * @author Evan Prodromou * @author Zach Copley - * @copyright 2009 StatusNet, Inc. + * @copyright 2009-2010 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ */ @@ -65,7 +65,7 @@ class ApiBlockCreateAction extends ApiAuthAction parent::prepare($args); $this->user = $this->auth_user; - $this->other = $this->getTargetUser($this->arg('id')); + $this->other = $this->getTargetProfile($this->arg('id')); return true; } diff --git a/actions/apiblockdestroy.php b/actions/apiblockdestroy.php index 666f308f4c..7ea201677e 100644 --- a/actions/apiblockdestroy.php +++ b/actions/apiblockdestroy.php @@ -23,7 +23,7 @@ * @package StatusNet * @author Evan Prodromou * @author Zach Copley - * @copyright 2009 StatusNet, Inc. + * @copyright 2009-2010 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ */ @@ -64,7 +64,7 @@ class ApiBlockDestroyAction extends ApiAuthAction parent::prepare($args); $this->user = $this->auth_user; - $this->other = $this->getTargetUser($this->arg('id')); + $this->other = $this->getTargetProfile($this->arg('id')); return true; } diff --git a/actions/apifriendshipscreate.php b/actions/apifriendshipscreate.php index 1de2cc32e0..a7ec5b28a4 100644 --- a/actions/apifriendshipscreate.php +++ b/actions/apifriendshipscreate.php @@ -24,7 +24,7 @@ * @author Dan Moore * @author Evan Prodromou * @author Zach Copley - * @copyright 2009 StatusNet, Inc. + * @copyright 2009-2010 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ */ @@ -67,7 +67,7 @@ class ApiFriendshipsCreateAction extends ApiAuthAction parent::prepare($args); $this->user = $this->auth_user; - $this->other = $this->getTargetUser($id); + $this->other = $this->getTargetProfile($this->arg('id')); return true; } @@ -106,7 +106,7 @@ class ApiFriendshipsCreateAction extends ApiAuthAction if (empty($this->other)) { $this->clientError( - _('Could not follow user: User not found.'), + _('Could not follow user: profile not found.'), 403, $this->format ); diff --git a/actions/apifriendshipsdestroy.php b/actions/apifriendshipsdestroy.php index d48a577562..551d016823 100644 --- a/actions/apifriendshipsdestroy.php +++ b/actions/apifriendshipsdestroy.php @@ -24,7 +24,7 @@ * @author Dan Moore * @author Evan Prodromou * @author Zach Copley - * @copyright 2009 StatusNet, Inc. + * @copyright 2009-2010 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ */ @@ -67,7 +67,7 @@ class ApiFriendshipsDestroyAction extends ApiAuthAction parent::prepare($args); $this->user = $this->auth_user; - $this->other = $this->getTargetUser($id); + $this->other = $this->getTargetProfile($this->arg('id')); return true; } @@ -125,8 +125,7 @@ class ApiFriendshipsDestroyAction extends ApiAuthAction } // throws an exception on error - Subscription::cancel($this->user->getProfile(), - $this->other->getProfile()); + Subscription::cancel($this->user->getProfile(), $this->other); $this->initDocument($this->format); $this->showProfile($this->other, $this->format); diff --git a/actions/apifriendshipsexists.php b/actions/apifriendshipsexists.php index ca62b5f514..725178fd42 100644 --- a/actions/apifriendshipsexists.php +++ b/actions/apifriendshipsexists.php @@ -24,7 +24,7 @@ * @author Dan Moore * @author Evan Prodromou * @author Zach Copley - * @copyright 2009 StatusNet, Inc. + * @copyright 2009-2010 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ */ @@ -50,8 +50,8 @@ require_once INSTALLDIR . '/lib/apiprivateauth.php'; class ApiFriendshipsExistsAction extends ApiPrivateAuthAction { - var $user_a = null; - var $user_b = null; + var $profile_a = null; + var $profile_b = null; /** * Take arguments for running @@ -66,11 +66,8 @@ class ApiFriendshipsExistsAction extends ApiPrivateAuthAction { parent::prepare($args); - $user_a_id = $this->trimmed('user_a'); - $user_b_id = $this->trimmed('user_b'); - - $this->user_a = $this->getTargetUser($user_a_id); - $this->user_b = $this->getTargetUser($user_b_id); + $this->profile_a = $this->getTargetProfile($this->trimmed('user_a')); + $this->profile_b = $this->getTargetProfile($this->trimmed('user_b')); return true; } @@ -89,16 +86,16 @@ class ApiFriendshipsExistsAction extends ApiPrivateAuthAction { parent::handle($args); - if (empty($this->user_a) || empty($this->user_b)) { + if (empty($this->profile_a) || empty($this->profile_b)) { $this->clientError( - _('Two user ids or screen_names must be supplied.'), + _('Two valid IDs or screen_names must be supplied.'), 400, $this->format ); return; } - $result = $this->user_a->isSubscribed($this->user_b); + $result = Subscription::exists($this->profile_a, $this->profile_b); switch ($this->format) { case 'xml': diff --git a/lib/apiaction.php b/lib/apiaction.php index 89a4871029..8de13a62da 100644 --- a/lib/apiaction.php +++ b/lib/apiaction.php @@ -1374,6 +1374,34 @@ class ApiAction extends Action } } + function getTargetProfile($id) + { + if (empty($id)) { + + // Twitter supports these other ways of passing the user ID + if (is_numeric($this->arg('id'))) { + return Profile::staticGet($this->arg('id')); + } else if ($this->arg('id')) { + $nickname = common_canonical_nickname($this->arg('id')); + return Profile::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 + if (is_numeric($this->arg('user_id'))) { + return Profile::staticGet('id', $this->arg('user_id')); + } + } else if ($this->arg('screen_name')) { + $nickname = common_canonical_nickname($this->arg('screen_name')); + return Profile::staticGet('nickname', $nickname); + } + } else if (is_numeric($id)) { + return Profile::staticGet($id); + } else { + $nickname = common_canonical_nickname($id); + return Profile::staticGet('nickname', $nickname); + } + } + function getTargetGroup($id) { if (empty($id)) { From 2d920e05d563c9c327cf235b31ce18dfc4a83870 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 29 Jun 2010 10:24:48 -0400 Subject: [PATCH 23/25] Update the (formerly) Janrain OpenID library to 2.2.2 -- bug fixes including PHP 5.3 compatibility fix. Upstream release was tagged at: http://github.com/openid/php-openid/commit/a287b2d85e753c84b3b883ed8ee3ffe8692c8477 --- extlib/Auth/OpenID.php | 63 ++++++++------- extlib/Auth/OpenID/AX.php | 23 +++--- extlib/Auth/OpenID/Association.php | 23 +++--- extlib/Auth/OpenID/BigMath.php | 31 ++------ extlib/Auth/OpenID/Consumer.php | 66 ++++++++-------- extlib/Auth/OpenID/CryptUtil.php | 5 +- extlib/Auth/OpenID/DatabaseConnection.php | 1 - extlib/Auth/OpenID/DiffieHellman.php | 6 +- extlib/Auth/OpenID/Discover.php | 94 +++++++++++++++++----- extlib/Auth/OpenID/DumbStore.php | 1 - extlib/Auth/OpenID/Extension.php | 3 +- extlib/Auth/OpenID/FileStore.php | 6 +- extlib/Auth/OpenID/HMAC.php | 1 - extlib/Auth/OpenID/Interface.php | 1 - extlib/Auth/OpenID/KVForm.php | 5 +- extlib/Auth/OpenID/MemcachedStore.php | 1 - extlib/Auth/OpenID/Message.php | 10 +-- extlib/Auth/OpenID/MySQLStore.php | 1 - extlib/Auth/OpenID/Nonce.php | 1 - extlib/Auth/OpenID/PAPE.php | 11 ++- extlib/Auth/OpenID/Parse.php | 37 +++++++-- extlib/Auth/OpenID/PostgreSQLStore.php | 1 - extlib/Auth/OpenID/SQLStore.php | 18 +---- extlib/Auth/OpenID/SQLiteStore.php | 1 - extlib/Auth/OpenID/SReg.php | 14 ++-- extlib/Auth/OpenID/Server.php | 95 ++++++++++++----------- extlib/Auth/OpenID/ServerRequest.php | 1 - extlib/Auth/OpenID/TrustRoot.php | 21 +++-- extlib/Auth/OpenID/URINorm.php | 2 +- extlib/Auth/Yadis/HTTPFetcher.php | 33 +++++++- extlib/Auth/Yadis/Manager.php | 20 ++--- extlib/Auth/Yadis/Misc.php | 1 - extlib/Auth/Yadis/ParanoidHTTPFetcher.php | 29 +++++-- extlib/Auth/Yadis/ParseHTML.php | 1 - extlib/Auth/Yadis/PlainHTTPFetcher.php | 3 +- extlib/Auth/Yadis/XML.php | 56 ++++--------- extlib/Auth/Yadis/XRDS.php | 16 ++-- extlib/Auth/Yadis/XRI.php | 4 +- extlib/Auth/Yadis/XRIRes.php | 6 +- extlib/Auth/Yadis/Yadis.php | 20 ++--- 40 files changed, 397 insertions(+), 335 deletions(-) diff --git a/extlib/Auth/OpenID.php b/extlib/Auth/OpenID.php index db6164256f..c9d9779624 100644 --- a/extlib/Auth/OpenID.php +++ b/extlib/Auth/OpenID.php @@ -20,7 +20,7 @@ /** * The library version string */ -define('Auth_OpenID_VERSION', '2.1.3'); +define('Auth_OpenID_VERSION', '2.2.2'); /** * Require the fetcher code. @@ -102,9 +102,7 @@ define('Auth_OpenID_digits', define('Auth_OpenID_punct', "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"); -if (Auth_OpenID_getMathLib() === null) { - Auth_OpenID_setNoMathSupport(); -} +Auth_OpenID_include_init(); /** * The OpenID utility function class. @@ -120,7 +118,7 @@ class Auth_OpenID { * * @access private */ - function isFailure($thing) + static function isFailure($thing) { return is_a($thing, 'Auth_OpenID_FailureResponse'); } @@ -139,9 +137,12 @@ class Auth_OpenID { * Returns an empty array if neither GET nor POST was used, or if * POST was used but php://input cannot be opened. * + * See background: + * http://lists.openidenabled.com/pipermail/dev/2007-March/000395.html + * * @access private */ - function getQuery($query_str=null) + static function getQuery($query_str=null) { $data = array(); @@ -177,7 +178,7 @@ class Auth_OpenID { return $data; } - function params_from_string($str) + static function params_from_string($str) { $chunks = explode("&", $str); @@ -190,7 +191,7 @@ class Auth_OpenID { } list($k, $v) = $parts; - $data[$k] = urldecode($v); + $data[urldecode($k)] = urldecode($v); } return $data; @@ -203,7 +204,7 @@ class Auth_OpenID { * * @access private */ - function ensureDir($dir_name) + static function ensureDir($dir_name) { if (is_dir($dir_name) || @mkdir($dir_name)) { return true; @@ -225,7 +226,7 @@ class Auth_OpenID { * * @access private */ - function addPrefix($values, $prefix) + static function addPrefix($values, $prefix) { $new_values = array(); foreach ($values as $s) { @@ -241,7 +242,7 @@ class Auth_OpenID { * * @access private */ - function arrayGet($arr, $key, $fallback = null) + static function arrayGet($arr, $key, $fallback = null) { if (is_array($arr)) { if (array_key_exists($key, $arr)) { @@ -261,7 +262,7 @@ class Auth_OpenID { /** * Replacement for PHP's broken parse_str. */ - function parse_str($query) + static function parse_str($query) { if ($query === null) { return null; @@ -278,7 +279,7 @@ class Auth_OpenID { } list($key, $value) = $pair; - $new_parts[$key] = urldecode($value); + $new_parts[urldecode($key)] = urldecode($value); } return $new_parts; @@ -295,7 +296,7 @@ class Auth_OpenID { * pairs from $data into a URL query string * (e.g. "username=bob&id=56"). */ - function httpBuildQuery($data) + static function httpBuildQuery($data) { $pairs = array(); foreach ($data as $key => $value) { @@ -323,7 +324,7 @@ class Auth_OpenID { * @return string $url The original URL with the new parameters added. * */ - function appendArgs($url, $args) + static function appendArgs($url, $args) { if (count($args) == 0) { return $url; @@ -367,7 +368,7 @@ class Auth_OpenID { * @return string $url The URL resulting from assembling the * specified components. */ - function urlunparse($scheme, $host, $port = null, $path = '/', + static function urlunparse($scheme, $host, $port = null, $path = '/', $query = '', $fragment = '') { @@ -412,7 +413,7 @@ class Auth_OpenID { * @return mixed $new_url The URL after normalization, or null if * $url was malformed. */ - function normalizeUrl($url) + static function normalizeUrl($url) { @$parsed = parse_url($url); @@ -443,7 +444,7 @@ class Auth_OpenID { * * @access private */ - function intval($value) + static function intval($value) { $re = "/^\\d+$/"; @@ -461,7 +462,7 @@ class Auth_OpenID { * @param string $str The string of bytes to count. * @return int The number of bytes in $str. */ - function bytes($str) + static function bytes($str) { return strlen(bin2hex($str)) / 2; } @@ -470,7 +471,7 @@ class Auth_OpenID { * Get the bytes in a string independently of multibyte support * conditions. */ - function toBytes($str) + static function toBytes($str) { $hex = bin2hex($str); @@ -486,7 +487,7 @@ class Auth_OpenID { return $b; } - function urldefrag($url) + static function urldefrag($url) { $parts = explode("#", $url, 2); @@ -497,7 +498,7 @@ class Auth_OpenID { } } - function filter($callback, &$sequence) + static function filter($callback, &$sequence) { $result = array(); @@ -510,7 +511,7 @@ class Auth_OpenID { return $result; } - function update(&$dest, &$src) + static function update(&$dest, &$src) { foreach ($src as $k => $v) { $dest[$k] = $v; @@ -524,14 +525,14 @@ class Auth_OpenID { * * @param string $format_string The sprintf format for the message */ - function log($format_string) + static function log($format_string) { $args = func_get_args(); $message = call_user_func_array('sprintf', $args); error_log($message); } - function autoSubmitHTML($form, $title="OpenId transaction in progress") + static function autoSubmitHTML($form, $title="OpenId transaction in progress") { return("". "". @@ -549,4 +550,14 @@ class Auth_OpenID { "</html>"); } } -?> + +/* + * Function to run when this file is included. + * Abstracted to a function to make life easier + * for some PHP optimizers. + */ +function Auth_OpenID_include_init() { + if (Auth_OpenID_getMathLib() === null) { + Auth_OpenID_setNoMathSupport(); + } +} diff --git a/extlib/Auth/OpenID/AX.php b/extlib/Auth/OpenID/AX.php index 4a617ae30c..7370715e3a 100644 --- a/extlib/Auth/OpenID/AX.php +++ b/extlib/Auth/OpenID/AX.php @@ -38,7 +38,7 @@ class Auth_OpenID_AX { * @return bool true if $thing is an Auth_OpenID_AX_Error; false * if not. */ - function isError($thing) + static function isError($thing) { return is_a($thing, 'Auth_OpenID_AX_Error'); } @@ -191,7 +191,7 @@ class Auth_OpenID_AX_AttrInfo { * Construct an attribute information object. For parameter * details, see the constructor. */ - function make($type_uri, $count=1, $required=false, + static function make($type_uri, $count=1, $required=false, $alias=null) { if ($alias !== null) { @@ -235,7 +235,7 @@ class Auth_OpenID_AX_AttrInfo { * return null If an alias is present in the list of aliases but * is not present in the namespace map. */ -function Auth_OpenID_AX_toTypeURIs(&$namespace_map, $alias_list_s) +function Auth_OpenID_AX_toTypeURIs($namespace_map, $alias_list_s) { $uris = array(); @@ -386,7 +386,7 @@ class Auth_OpenID_AX_FetchRequest extends Auth_OpenID_AX_Message { * Auth_OpenID_AX_FetchRequest extracted from the request message if * successful */ - function &fromOpenIDRequest($request) + static function fromOpenIDRequest($request) { $m = $request->message; $obj = new Auth_OpenID_AX_FetchRequest(); @@ -484,7 +484,7 @@ class Auth_OpenID_AX_FetchRequest extends Auth_OpenID_AX_Message { Auth_OpenID::arrayGet($ax_args, 'required')); foreach ($required as $type_uri) { - $attrib =& $this->requested_attributes[$type_uri]; + $attrib = $this->requested_attributes[$type_uri]; $attrib->required = true; } @@ -587,7 +587,7 @@ class Auth_OpenID_AX_KeyValueMessage extends Auth_OpenID_AX_Message { * * @access private */ - function _getExtensionKVArgs(&$aliases) + function _getExtensionKVArgs($aliases) { if ($aliases === null) { $aliases = new Auth_OpenID_NamespaceMap(); @@ -652,7 +652,7 @@ class Auth_OpenID_AX_KeyValueMessage extends Auth_OpenID_AX_Message { foreach ($aliases->iteritems() as $pair) { list($type_uri, $alias) = $pair; - if (array_key_exists('count.' . $alias, $ax_args)) { + if (array_key_exists('count.' . $alias, $ax_args) && ($ax_args['count.' . $alias] !== Auth_OpenID_AX_UNLIMITED_VALUES)) { $count_key = 'count.' . $alias; $count_s = $ax_args[$count_key]; @@ -888,7 +888,7 @@ class Auth_OpenID_AX_FetchResponse extends Auth_OpenID_AX_KeyValueMessage { $ax_args['update_url'] = $update_url; } - Auth_OpenID::update(&$ax_args, $kv_args); + Auth_OpenID::update($ax_args, $kv_args); return $ax_args; } @@ -922,7 +922,7 @@ class Auth_OpenID_AX_FetchResponse extends Auth_OpenID_AX_KeyValueMessage { * @return $response A FetchResponse containing the data from the * OpenID message */ - function fromSuccessResponse($success_response, $signed=true) + static function fromSuccessResponse($success_response, $signed=true) { $obj = new Auth_OpenID_AX_FetchResponse(); if ($signed) { @@ -960,7 +960,7 @@ class Auth_OpenID_AX_StoreRequest extends Auth_OpenID_AX_KeyValueMessage { { $ax_args = $this->_newArgs(); $kv_args = $this->_getExtensionKVArgs($aliases); - Auth_OpenID::update(&$ax_args, $kv_args); + Auth_OpenID::update($ax_args, $kv_args); return $ax_args; } } @@ -980,7 +980,7 @@ class Auth_OpenID_AX_StoreResponse extends Auth_OpenID_AX_Message { * Returns Auth_OpenID_AX_Error on error or an * Auth_OpenID_AX_StoreResponse object on success. */ - function &make($succeeded=true, $error_message=null) + function make($succeeded=true, $error_message=null) { if (($succeeded) && ($error_message !== null)) { return new Auth_OpenID_AX_Error('An error message may only be '. @@ -1020,4 +1020,3 @@ class Auth_OpenID_AX_StoreResponse extends Auth_OpenID_AX_Message { } } -?> \ No newline at end of file diff --git a/extlib/Auth/OpenID/Association.php b/extlib/Auth/OpenID/Association.php index 37ce0cbf45..d1ac1ed9b9 100644 --- a/extlib/Auth/OpenID/Association.php +++ b/extlib/Auth/OpenID/Association.php @@ -94,7 +94,7 @@ class Auth_OpenID_Association { * @return association An {@link Auth_OpenID_Association} * instance. */ - function fromExpiresIn($expires_in, $handle, $secret, $assoc_type) + static function fromExpiresIn($expires_in, $handle, $secret, $assoc_type) { $issued = time(); $lifetime = $expires_in; @@ -132,7 +132,7 @@ class Auth_OpenID_Association { $handle, $secret, $issued, $lifetime, $assoc_type) { if (!in_array($assoc_type, - Auth_OpenID_getSupportedAssociationTypes())) { + Auth_OpenID_getSupportedAssociationTypes(), true)) { $fmt = 'Unsupported association type (%s)'; trigger_error(sprintf($fmt, $assoc_type), E_USER_ERROR); } @@ -206,7 +206,7 @@ class Auth_OpenID_Association { * @param string $assoc_s Association as serialized by serialize() * @return Auth_OpenID_Association $result instance of this class */ - function deserialize($class_name, $assoc_s) + static function deserialize($class_name, $assoc_s) { $pairs = Auth_OpenID_KVForm::toArray($assoc_s, $strict = true); $keys = array(); @@ -327,7 +327,7 @@ class Auth_OpenID_Association { * * @access private */ - function _makePairs(&$message) + function _makePairs($message) { $signed = $message->getArg(Auth_OpenID_OPENID_NS, 'signed'); if (!$signed || Auth_OpenID::isFailure($signed)) { @@ -352,7 +352,7 @@ class Auth_OpenID_Association { * * @access private */ - function getMessageSignature(&$message) + function getMessageSignature($message) { $pairs = $this->_makePairs($message); return base64_encode($this->sign($pairs)); @@ -364,7 +364,7 @@ class Auth_OpenID_Association { * * @access private */ - function checkMessageSignature(&$message) + function checkMessageSignature($message) { $sig = $message->getArg(Auth_OpenID_OPENID_NS, 'sig'); @@ -469,18 +469,16 @@ function Auth_OpenID_getOnlyEncryptedOrder() return $result; } -function &Auth_OpenID_getDefaultNegotiator() +function Auth_OpenID_getDefaultNegotiator() { - $x = new Auth_OpenID_SessionNegotiator( + return new Auth_OpenID_SessionNegotiator( Auth_OpenID_getDefaultAssociationOrder()); - return $x; } -function &Auth_OpenID_getEncryptedNegotiator() +function Auth_OpenID_getEncryptedNegotiator() { - $x = new Auth_OpenID_SessionNegotiator( + return new Auth_OpenID_SessionNegotiator( Auth_OpenID_getOnlyEncryptedOrder()); - return $x; } /** @@ -610,4 +608,3 @@ class Auth_OpenID_SessionNegotiator { } } -?> \ No newline at end of file diff --git a/extlib/Auth/OpenID/BigMath.php b/extlib/Auth/OpenID/BigMath.php index 45104947d6..7fca2dc43e 100644 --- a/extlib/Auth/OpenID/BigMath.php +++ b/extlib/Auth/OpenID/BigMath.php @@ -351,8 +351,7 @@ function Auth_OpenID_math_extensions() 'class' => 'Auth_OpenID_GmpMathWrapper'); } - $result[] = array( - 'modules' => array('bcmath', 'php_bcmath'), + $result[] = array('modules' => array('bcmath', 'php_bcmath'), 'extension' => 'bcmath', 'class' => 'Auth_OpenID_BcMathWrapper'); @@ -366,27 +365,9 @@ function Auth_OpenID_detectMathLibrary($exts) { $loaded = false; + $hasDl = function_exists('dl'); foreach ($exts as $extension) { - // See if the extension specified is already loaded. - if ($extension['extension'] && - extension_loaded($extension['extension'])) { - $loaded = true; - } - - // Try to load dynamic modules. - if (!$loaded) { - foreach ($extension['modules'] as $module) { - if (@dl($module . "." . PHP_SHLIB_SUFFIX)) { - $loaded = true; - break; - } - } - } - - // If the load succeeded, supply an instance of - // Auth_OpenID_MathWrapper which wraps the specified - // module's functionality. - if ($loaded) { + if (extension_loaded($extension['extension'])) { return $extension; } } @@ -405,7 +386,7 @@ function Auth_OpenID_detectMathLibrary($exts) * instance of a wrapper for that extension module. If no extension * module is found, an instance of {@link Auth_OpenID_MathWrapper} is * returned, which wraps the native PHP integer implementation. The - * proper calling convention for this method is $lib =& + * proper calling convention for this method is $lib = * Auth_OpenID_getMathLib(). * * This function checks for the existence of specific long number @@ -416,7 +397,7 @@ function Auth_OpenID_detectMathLibrary($exts) * * @package OpenID */ -function &Auth_OpenID_getMathLib() +function Auth_OpenID_getMathLib() { // The instance of Auth_OpenID_MathWrapper that we choose to // supply will be stored here, so that subseqent calls to this @@ -468,4 +449,4 @@ function Auth_OpenID_noMathSupport() return defined('Auth_OpenID_NO_MATH_SUPPORT'); } -?> + diff --git a/extlib/Auth/OpenID/Consumer.php b/extlib/Auth/OpenID/Consumer.php index 500890b656..021c038988 100644 --- a/extlib/Auth/OpenID/Consumer.php +++ b/extlib/Auth/OpenID/Consumer.php @@ -258,19 +258,19 @@ class Auth_OpenID_Consumer { * when creating the internal consumer object. This is used for * testing. */ - function Auth_OpenID_Consumer(&$store, $session = null, + function Auth_OpenID_Consumer($store, $session = null, $consumer_cls = null) { if ($session === null) { $session = new Auth_Yadis_PHPSession(); } - $this->session =& $session; + $this->session = $session; if ($consumer_cls !== null) { - $this->consumer =& new $consumer_cls($store); + $this->consumer = new $consumer_cls($store); } else { - $this->consumer =& new Auth_OpenID_GenericConsumer($store); + $this->consumer = new Auth_OpenID_GenericConsumer($store); } $this->_token_key = $this->session_key_prefix . $this->_token_suffix; @@ -281,7 +281,7 @@ class Auth_OpenID_Consumer { * * @access private */ - function getDiscoveryObject(&$session, $openid_url, + function getDiscoveryObject($session, $openid_url, $session_key_prefix) { return new Auth_Yadis_Discovery($session, $openid_url, @@ -339,7 +339,7 @@ class Auth_OpenID_Consumer { $this->consumer->fetcher); // Reset the 'stale' attribute of the manager. - $m =& $disco->getManager(); + $m = $disco->getManager(); if ($m) { $m->stale = false; $disco->session->set($disco->session_key, @@ -370,7 +370,7 @@ class Auth_OpenID_Consumer { * @return Auth_OpenID_AuthRequest $auth_request An OpenID * authentication request object. */ - function &beginWithoutDiscovery($endpoint, $anonymous=false) + function beginWithoutDiscovery($endpoint, $anonymous=false) { $loader = new Auth_OpenID_ServiceEndpointLoader(); $auth_req = $this->consumer->begin($endpoint); @@ -467,7 +467,7 @@ class Auth_OpenID_DiffieHellmanSHA1ConsumerSession { function getRequest() { - $math =& Auth_OpenID_getMathLib(); + $math = Auth_OpenID_getMathLib(); $cpub = $math->longToBase64($this->dh->public); @@ -496,7 +496,7 @@ class Auth_OpenID_DiffieHellmanSHA1ConsumerSession { return null; } - $math =& Auth_OpenID_getMathLib(); + $math = Auth_OpenID_getMathLib(); $spub = $math->base64ToLong($response->getArg(Auth_OpenID_OPENID_NS, 'dh_server_public')); @@ -611,11 +611,11 @@ class Auth_OpenID_GenericConsumer { * in the module description. The default value is False, which * disables immediate mode. */ - function Auth_OpenID_GenericConsumer(&$store) + function Auth_OpenID_GenericConsumer($store) { - $this->store =& $store; - $this->negotiator =& Auth_OpenID_getDefaultNegotiator(); - $this->_use_assocs = ($this->store ? true : false); + $this->store = $store; + $this->negotiator = Auth_OpenID_getDefaultNegotiator(); + $this->_use_assocs = (is_null($this->store) ? false : true); $this->fetcher = Auth_Yadis_Yadis::getHTTPFetcher(); @@ -665,14 +665,14 @@ class Auth_OpenID_GenericConsumer { $method = Auth_OpenID::arrayGet($mode_methods, $mode, '_completeInvalid'); - return call_user_func_array(array(&$this, $method), - array($message, $endpoint, $return_to)); + return call_user_func_array(array($this, $method), + array($message, &$endpoint, $return_to)); } /** * @access private */ - function _completeInvalid($message, &$endpoint, $unused) + function _completeInvalid($message, $endpoint, $unused) { $mode = $message->getArg(Auth_OpenID_OPENID_NS, 'mode', '<No mode set>'); @@ -684,7 +684,7 @@ class Auth_OpenID_GenericConsumer { /** * @access private */ - function _complete_cancel($message, &$endpoint, $unused) + function _complete_cancel($message, $endpoint, $unused) { return new Auth_OpenID_CancelResponse($endpoint); } @@ -692,7 +692,7 @@ class Auth_OpenID_GenericConsumer { /** * @access private */ - function _complete_error($message, &$endpoint, $unused) + function _complete_error($message, $endpoint, $unused) { $error = $message->getArg(Auth_OpenID_OPENID_NS, 'error'); $contact = $message->getArg(Auth_OpenID_OPENID_NS, 'contact'); @@ -705,7 +705,7 @@ class Auth_OpenID_GenericConsumer { /** * @access private */ - function _complete_setup_needed($message, &$endpoint, $unused) + function _complete_setup_needed($message, $endpoint, $unused) { if (!$message->isOpenID2()) { return $this->_completeInvalid($message, $endpoint); @@ -719,7 +719,7 @@ class Auth_OpenID_GenericConsumer { /** * @access private */ - function _complete_id_res($message, &$endpoint, $return_to) + function _complete_id_res($message, $endpoint, $return_to) { $user_setup_url = $message->getArg(Auth_OpenID_OPENID1_NS, 'user_setup_url'); @@ -1181,7 +1181,7 @@ class Auth_OpenID_GenericConsumer { // oidutil.log('Performing discovery on %s' % (claimed_id,)) list($unused, $services) = call_user_func($this->discoverMethod, $claimed_id, - $this->fetcher); + &$this->fetcher); if (!$services) { return new Auth_OpenID_FailureResponse(null, @@ -1197,7 +1197,7 @@ class Auth_OpenID_GenericConsumer { * @access private */ function _verifyDiscoveryServices($claimed_id, - &$services, &$to_match_endpoints) + $services, $to_match_endpoints) { // Search the services resulting from discovery to find one // that matches the information from the assertion @@ -1216,8 +1216,8 @@ class Auth_OpenID_GenericConsumer { } return new Auth_OpenID_FailureResponse(null, - sprintf('No matching endpoint found after discovering %s', - $claimed_id)); + sprintf('No matching endpoint found after discovering %s: %s', + $claimed_id, $result->message)); } /** @@ -1397,7 +1397,7 @@ class Auth_OpenID_GenericConsumer { * * @access private */ - function _httpResponseToMessage($response, $server_url) + static function _httpResponseToMessage($response, $server_url) { // Should this function be named Message.fromHTTPResponse instead? $response_message = Auth_OpenID_Message::fromKVForm($response->body); @@ -1461,7 +1461,7 @@ class Auth_OpenID_GenericConsumer { * * @access private */ - function _extractSupportedAssociationType(&$server_error, &$endpoint, + function _extractSupportedAssociationType($server_error, $endpoint, $assoc_type) { // Any error message whose code is not 'unsupported-type' @@ -1566,7 +1566,7 @@ class Auth_OpenID_GenericConsumer { /** * @access private */ - function _extractAssociation(&$assoc_response, &$assoc_session) + function _extractAssociation($assoc_response, $assoc_session) { // Extract the common fields from the response, raising an // exception if they are not found @@ -1748,10 +1748,10 @@ class Auth_OpenID_AuthRequest { * class. Instances of this class are created by the library when * needed. */ - function Auth_OpenID_AuthRequest(&$endpoint, $assoc) + function Auth_OpenID_AuthRequest($endpoint, $assoc) { $this->assoc = $assoc; - $this->endpoint =& $endpoint; + $this->endpoint = $endpoint; $this->return_to_args = array(); $this->message = new Auth_OpenID_Message( $endpoint->preferredNamespace()); @@ -1764,7 +1764,7 @@ class Auth_OpenID_AuthRequest { * $extension_request: An object that implements the extension * request interface for adding arguments to an OpenID message. */ - function addExtension(&$extension_request) + function addExtension($extension_request) { $extension_request->toMessage($this->message); } @@ -2089,7 +2089,7 @@ class Auth_OpenID_SuccessResponse extends Auth_OpenID_ConsumerResponse { foreach ($msg_args as $key => $value) { if (!$this->isSigned($ns_uri, $key)) { - return null; + unset($msg_args[$key]); } } @@ -2167,7 +2167,7 @@ class Auth_OpenID_ServerErrorContainer { /** * @access private */ - function fromMessage($message) + static function fromMessage($message) { $error_text = $message->getArg( Auth_OpenID_OPENID_NS, 'error', '<no error message supplied>'); @@ -2227,4 +2227,4 @@ class Auth_OpenID_SetupNeededResponse extends Auth_OpenID_ConsumerResponse { } } -?> + diff --git a/extlib/Auth/OpenID/CryptUtil.php b/extlib/Auth/OpenID/CryptUtil.php index aacc3cd397..a926267779 100644 --- a/extlib/Auth/OpenID/CryptUtil.php +++ b/extlib/Auth/OpenID/CryptUtil.php @@ -37,7 +37,7 @@ class Auth_OpenID_CryptUtil { * @param int $num_bytes The length of the return value * @return string $bytes random bytes */ - function getBytes($num_bytes) + static function getBytes($num_bytes) { static $f = null; $bytes = ''; @@ -77,7 +77,7 @@ class Auth_OpenID_CryptUtil { * @return string $result A string of randomly-chosen characters * from $chrs */ - function randomString($length, $population = null) + static function randomString($length, $population = null) { if ($population === null) { return Auth_OpenID_CryptUtil::getBytes($length); @@ -106,4 +106,3 @@ class Auth_OpenID_CryptUtil { } } -?> \ No newline at end of file diff --git a/extlib/Auth/OpenID/DatabaseConnection.php b/extlib/Auth/OpenID/DatabaseConnection.php index 9db6e0eb3f..0c7d08f916 100644 --- a/extlib/Auth/OpenID/DatabaseConnection.php +++ b/extlib/Auth/OpenID/DatabaseConnection.php @@ -128,4 +128,3 @@ class Auth_OpenID_DatabaseConnection { } } -?> \ No newline at end of file diff --git a/extlib/Auth/OpenID/DiffieHellman.php b/extlib/Auth/OpenID/DiffieHellman.php index f4ded7eba5..3e25b7dbbb 100644 --- a/extlib/Auth/OpenID/DiffieHellman.php +++ b/extlib/Auth/OpenID/DiffieHellman.php @@ -51,9 +51,9 @@ class Auth_OpenID_DiffieHellman { $private = null, $lib = null) { if ($lib === null) { - $this->lib =& Auth_OpenID_getMathLib(); + $this->lib = Auth_OpenID_getMathLib(); } else { - $this->lib =& $lib; + $this->lib = $lib; } if ($mod === null) { @@ -110,4 +110,4 @@ class Auth_OpenID_DiffieHellman { } } -?> + diff --git a/extlib/Auth/OpenID/Discover.php b/extlib/Auth/OpenID/Discover.php index 62aeb1d2bc..7b0c640c58 100644 --- a/extlib/Auth/OpenID/Discover.php +++ b/extlib/Auth/OpenID/Discover.php @@ -28,8 +28,34 @@ function Auth_OpenID_getOpenIDTypeURIs() Auth_OpenID_TYPE_2_0, Auth_OpenID_TYPE_1_2, Auth_OpenID_TYPE_1_1, - Auth_OpenID_TYPE_1_0, - Auth_OpenID_RP_RETURN_TO_URL_TYPE); + Auth_OpenID_TYPE_1_0); +} + +function Auth_OpenID_getOpenIDConsumerTypeURIs() +{ + return array(Auth_OpenID_RP_RETURN_TO_URL_TYPE); +} + + +/* + * Provides a user-readable interpretation of a type uri. + * Useful for error messages. + */ +function Auth_OpenID_getOpenIDTypeName($type_uri) { + switch ($type_uri) { + case Auth_OpenID_TYPE_2_0_IDP: + return 'OpenID 2.0 IDP'; + case Auth_OpenID_TYPE_2_0: + return 'OpenID 2.0'; + case Auth_OpenID_TYPE_1_2: + return 'OpenID 1.2'; + case Auth_OpenID_TYPE_1_1: + return 'OpenID 1.1'; + case Auth_OpenID_TYPE_1_0: + return 'OpenID 1.0'; + case Auth_OpenID_RP_RETURN_TO_URL_TYPE: + return 'OpenID relying party'; + } } /** @@ -124,7 +150,7 @@ class Auth_OpenID_ServiceEndpoint { return in_array(Auth_OpenID_TYPE_2_0_IDP, $this->type_uris); } - function fromOPEndpointURL($op_endpoint_url) + static function fromOPEndpointURL($op_endpoint_url) { // Construct an OP-Identifier OpenIDServiceEndpoint object for // a given OP Endpoint URL @@ -171,15 +197,34 @@ class Auth_OpenID_ServiceEndpoint { } } + /* + * Parse the given document as XRDS looking for OpenID consumer services. + * + * @return array of Auth_OpenID_ServiceEndpoint or null if the + * document cannot be parsed. + */ + function consumerFromXRDS($uri, $xrds_text) + { + $xrds =& Auth_Yadis_XRDS::parseXRDS($xrds_text); + + if ($xrds) { + $yadis_services = + $xrds->services(array('filter_MatchesAnyOpenIDConsumerType')); + return Auth_OpenID_makeOpenIDEndpoints($uri, $yadis_services); + } + + return null; + } + /* * Parse the given document as XRDS looking for OpenID services. * * @return array of Auth_OpenID_ServiceEndpoint or null if the * document cannot be parsed. */ - function fromXRDS($uri, $xrds_text) + static function fromXRDS($uri, $xrds_text) { - $xrds =& Auth_Yadis_XRDS::parseXRDS($xrds_text); + $xrds = Auth_Yadis_XRDS::parseXRDS($xrds_text); if ($xrds) { $yadis_services = @@ -197,7 +242,7 @@ class Auth_OpenID_ServiceEndpoint { * @return array of Auth_OpenID_ServiceEndpoint or null if * endpoints cannot be created. */ - function fromDiscoveryResult($discoveryResult) + static function fromDiscoveryResult($discoveryResult) { if ($discoveryResult->isXRDS()) { return Auth_OpenID_ServiceEndpoint::fromXRDS( @@ -210,7 +255,7 @@ class Auth_OpenID_ServiceEndpoint { } } - function fromHTML($uri, $html) + static function fromHTML($uri, $html) { $discovery_types = array( array(Auth_OpenID_TYPE_2_0, @@ -273,7 +318,7 @@ function Auth_OpenID_findOPLocalIdentifier($service, $type_uris) $service->parser->registerNamespace('xrd', Auth_Yadis_XMLNS_XRD_2_0); - $parser =& $service->parser; + $parser = $service->parser; $permitted_tags = array(); @@ -305,7 +350,7 @@ function Auth_OpenID_findOPLocalIdentifier($service, $type_uris) return $local_id; } -function filter_MatchesAnyOpenIDType(&$service) +function filter_MatchesAnyOpenIDType($service) { $uris = $service->getTypes(); @@ -318,6 +363,19 @@ function filter_MatchesAnyOpenIDType(&$service) return false; } +function filter_MatchesAnyOpenIDConsumerType(&$service) +{ + $uris = $service->getTypes(); + + foreach ($uris as $uri) { + if (in_array($uri, Auth_OpenID_getOpenIDConsumerTypeURIs())) { + return true; + } + } + + return false; +} + function Auth_OpenID_bestMatchingService($service, $preferred_types) { // Return the index of the first matching type, or something @@ -415,7 +473,7 @@ function Auth_OpenID_makeOpenIDEndpoints($uri, $yadis_services) return $s; } -function Auth_OpenID_discoverWithYadis($uri, &$fetcher, +function Auth_OpenID_discoverWithYadis($uri, $fetcher, $endpoint_filter='Auth_OpenID_getOPOrUserServices', $discover_function=null) { @@ -433,12 +491,12 @@ function Auth_OpenID_discoverWithYadis($uri, &$fetcher, $openid_services = array(); $response = call_user_func_array($discover_function, - array($uri, &$fetcher)); + array($uri, $fetcher)); $yadis_url = $response->normalized_uri; $yadis_services = array(); - if ($response->isFailure()) { + if ($response->isFailure() && !$response->isXRDS()) { return array($uri, array()); } @@ -460,18 +518,18 @@ function Auth_OpenID_discoverWithYadis($uri, &$fetcher, } $openid_services = call_user_func_array($endpoint_filter, - array(&$openid_services)); + array($openid_services)); return array($yadis_url, $openid_services); } -function Auth_OpenID_discoverURI($uri, &$fetcher) +function Auth_OpenID_discoverURI($uri, $fetcher) { $uri = Auth_OpenID::normalizeUrl($uri); return Auth_OpenID_discoverWithYadis($uri, $fetcher); } -function Auth_OpenID_discoverWithoutYadis($uri, &$fetcher) +function Auth_OpenID_discoverWithoutYadis($uri, $fetcher) { $http_resp = @$fetcher->get($uri); @@ -490,7 +548,7 @@ function Auth_OpenID_discoverWithoutYadis($uri, &$fetcher) return array($identity_url, $openid_services); } -function Auth_OpenID_discoverXRI($iname, &$fetcher) +function Auth_OpenID_discoverXRI($iname, $fetcher) { $resolver = new Auth_Yadis_ProxyResolver($fetcher); list($canonicalID, $yadis_services) = @@ -513,7 +571,7 @@ function Auth_OpenID_discoverXRI($iname, &$fetcher) return array($iname, $openid_services); } -function Auth_OpenID_discover($uri, &$fetcher) +function Auth_OpenID_discover($uri, $fetcher) { // If the fetcher (i.e., PHP) doesn't support SSL, we can't do // discovery on an HTTPS URL. @@ -545,4 +603,4 @@ function Auth_OpenID_discover($uri, &$fetcher) return $result; } -?> + diff --git a/extlib/Auth/OpenID/DumbStore.php b/extlib/Auth/OpenID/DumbStore.php index 22fd2d3661..e8f29ace55 100644 --- a/extlib/Auth/OpenID/DumbStore.php +++ b/extlib/Auth/OpenID/DumbStore.php @@ -97,4 +97,3 @@ class Auth_OpenID_DumbStore extends Auth_OpenID_OpenIDStore { } } -?> \ No newline at end of file diff --git a/extlib/Auth/OpenID/Extension.php b/extlib/Auth/OpenID/Extension.php index f362a4b389..c4e38c0380 100644 --- a/extlib/Auth/OpenID/Extension.php +++ b/extlib/Auth/OpenID/Extension.php @@ -39,7 +39,7 @@ class Auth_OpenID_Extension { * * Returns the message with the extension arguments added. */ - function toMessage(&$message) + function toMessage($message) { $implicit = $message->isOpenID1(); $added = $message->namespaces->addAlias($this->ns_uri, @@ -59,4 +59,3 @@ class Auth_OpenID_Extension { } } -?> \ No newline at end of file diff --git a/extlib/Auth/OpenID/FileStore.php b/extlib/Auth/OpenID/FileStore.php index 29d8d20e76..074421a0bb 100644 --- a/extlib/Auth/OpenID/FileStore.php +++ b/extlib/Auth/OpenID/FileStore.php @@ -367,7 +367,7 @@ class Auth_OpenID_FileStore extends Auth_OpenID_OpenIDStore { } if ( abs($timestamp - time()) > $Auth_OpenID_SKEW ) { - return False; + return false; } if ($server_url) { @@ -519,7 +519,7 @@ class Auth_OpenID_FileStore extends Auth_OpenID_OpenIDStore { /** * @access private */ - function _mkdtemp($dir) + static function _mkdtemp($dir) { foreach (range(0, 4) as $i) { $name = $dir . strval(DIRECTORY_SEPARATOR) . strval(getmypid()) . @@ -615,4 +615,4 @@ class Auth_OpenID_FileStore extends Auth_OpenID_OpenIDStore { } } -?> + diff --git a/extlib/Auth/OpenID/HMAC.php b/extlib/Auth/OpenID/HMAC.php index ec42db8dfc..e9779bd4e0 100644 --- a/extlib/Auth/OpenID/HMAC.php +++ b/extlib/Auth/OpenID/HMAC.php @@ -96,4 +96,3 @@ if (function_exists('hash_hmac') && define('Auth_OpenID_HMACSHA256_SUPPORTED', false); } -?> \ No newline at end of file diff --git a/extlib/Auth/OpenID/Interface.php b/extlib/Auth/OpenID/Interface.php index f4c6062f8c..eca6b9c50f 100644 --- a/extlib/Auth/OpenID/Interface.php +++ b/extlib/Auth/OpenID/Interface.php @@ -194,4 +194,3 @@ class Auth_OpenID_OpenIDStore { } } -?> \ No newline at end of file diff --git a/extlib/Auth/OpenID/KVForm.php b/extlib/Auth/OpenID/KVForm.php index fb342a0013..dd02661d88 100644 --- a/extlib/Auth/OpenID/KVForm.php +++ b/extlib/Auth/OpenID/KVForm.php @@ -26,7 +26,7 @@ class Auth_OpenID_KVForm { * @static * @access private */ - function toArray($kvs, $strict=false) + static function toArray($kvs, $strict=false) { $lines = explode("\n", $kvs); @@ -78,7 +78,7 @@ class Auth_OpenID_KVForm { * @static * @access private */ - function fromArray($values) + static function fromArray($values) { if ($values === null) { return null; @@ -109,4 +109,3 @@ class Auth_OpenID_KVForm { } } -?> \ No newline at end of file diff --git a/extlib/Auth/OpenID/MemcachedStore.php b/extlib/Auth/OpenID/MemcachedStore.php index d357c6b11d..fc10800b1c 100644 --- a/extlib/Auth/OpenID/MemcachedStore.php +++ b/extlib/Auth/OpenID/MemcachedStore.php @@ -205,4 +205,3 @@ class Auth_OpenID_MemcachedStore extends Auth_OpenID_OpenIDStore { } } -?> \ No newline at end of file diff --git a/extlib/Auth/OpenID/Message.php b/extlib/Auth/OpenID/Message.php index 5ab115a86e..9aa1fa4684 100644 --- a/extlib/Auth/OpenID/Message.php +++ b/extlib/Auth/OpenID/Message.php @@ -143,7 +143,7 @@ class Auth_OpenID_Mapping { * Returns true if $thing is an Auth_OpenID_Mapping object; false * if not. */ - function isA($thing) + static function isA($thing) { return (is_object($thing) && strtolower(get_class($thing)) == 'auth_openid_mapping'); @@ -442,7 +442,7 @@ class Auth_OpenID_Message { return $this->getOpenIDNamespace() == Auth_OpenID_OPENID2_NS; } - function fromPostArgs($args) + static function fromPostArgs($args) { // Construct a Message containing a set of POST arguments $obj = new Auth_OpenID_Message(); @@ -477,7 +477,7 @@ class Auth_OpenID_Message { } } - function fromOpenIDArgs($openid_args) + static function fromOpenIDArgs($openid_args) { // Takes an array. @@ -594,7 +594,7 @@ class Auth_OpenID_Message { return $this->_openid_ns_uri; } - function fromKVForm($kvform_string) + static function fromKVForm($kvform_string) { // Create a Message from a KVForm string return Auth_OpenID_Message::fromOpenIDArgs( @@ -917,4 +917,4 @@ class Auth_OpenID_Message { } } -?> + diff --git a/extlib/Auth/OpenID/MySQLStore.php b/extlib/Auth/OpenID/MySQLStore.php index eb08af0162..810f059f1d 100644 --- a/extlib/Auth/OpenID/MySQLStore.php +++ b/extlib/Auth/OpenID/MySQLStore.php @@ -75,4 +75,3 @@ class Auth_OpenID_MySQLStore extends Auth_OpenID_SQLStore { } } -?> \ No newline at end of file diff --git a/extlib/Auth/OpenID/Nonce.php b/extlib/Auth/OpenID/Nonce.php index effecac385..b83c5911f8 100644 --- a/extlib/Auth/OpenID/Nonce.php +++ b/extlib/Auth/OpenID/Nonce.php @@ -106,4 +106,3 @@ function Auth_OpenID_mkNonce($when = null) return $time_str . $salt; } -?> \ No newline at end of file diff --git a/extlib/Auth/OpenID/PAPE.php b/extlib/Auth/OpenID/PAPE.php index 62cba8a912..f08ca8bd0b 100644 --- a/extlib/Auth/OpenID/PAPE.php +++ b/extlib/Auth/OpenID/PAPE.php @@ -21,7 +21,7 @@ define('PAPE_AUTH_PHISHING_RESISTANT', 'http://schemas.openid.net/pape/policies/2007/06/phishing-resistant'); define('PAPE_TIME_VALIDATOR', - '^[0-9]{4,4}-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9]Z$'); + '/^[0-9]{4,4}-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9]Z$/'); /** * A Provider Authentication Policy request, sent from a relying party * to a provider @@ -82,7 +82,7 @@ class Auth_OpenID_PAPE_Request extends Auth_OpenID_Extension { * Instantiate a Request object from the arguments in a checkid_* * OpenID message */ - function fromOpenIDRequest($request) + static function fromOpenIDRequest($request) { $obj = new Auth_OpenID_PAPE_Request(); $args = $request->message->getArgs(Auth_OpenID_PAPE_NS_URI); @@ -201,7 +201,7 @@ class Auth_OpenID_PAPE_Response extends Auth_OpenID_Extension { * @returns: A provider authentication policy response from the * data that was supplied with the id_res response. */ - function fromSuccessResponse($success_response) + static function fromSuccessResponse($success_response) { $obj = new Auth_OpenID_PAPE_Response(); @@ -262,7 +262,7 @@ class Auth_OpenID_PAPE_Response extends Auth_OpenID_Extension { $auth_time = Auth_OpenID::arrayGet($args, 'auth_time'); if ($auth_time !== null) { - if (ereg(PAPE_TIME_VALIDATOR, $auth_time)) { + if (preg_match(PAPE_TIME_VALIDATOR, $auth_time)) { $this->auth_time = $auth_time; } else if ($strict) { return false; @@ -287,7 +287,7 @@ class Auth_OpenID_PAPE_Response extends Auth_OpenID_Extension { } if ($this->auth_time !== null) { - if (!ereg(PAPE_TIME_VALIDATOR, $this->auth_time)) { + if (!preg_match(PAPE_TIME_VALIDATOR, $this->auth_time)) { return false; } @@ -298,4 +298,3 @@ class Auth_OpenID_PAPE_Response extends Auth_OpenID_Extension { } } -?> \ No newline at end of file diff --git a/extlib/Auth/OpenID/Parse.php b/extlib/Auth/OpenID/Parse.php index 546f34f6be..6c2e721691 100644 --- a/extlib/Auth/OpenID/Parse.php +++ b/extlib/Auth/OpenID/Parse.php @@ -101,7 +101,7 @@ class Auth_OpenID_Parse { * Starts with the tag name at a word boundary, where the tag name * is not a namespace */ - var $_tag_expr = "<%s\b(?!:)([^>]*?)(?:\/>|>(.*?)(?:<\/?%s\s*>|\Z))"; + var $_tag_expr = "<%s\b(?!:)([^>]*?)(?:\/>|>(.*)(?:<\/?%s\s*>|\Z))"; var $_attr_find = '\b(\w+)=("[^"]*"|\'[^\']*\'|[^\'"\s\/<>]+)'; @@ -215,11 +215,31 @@ class Auth_OpenID_Parse { return $str; } } + + function match($regexp, $text, &$match) + { + if (!is_callable('mb_ereg_search_init')) { + return preg_match($regexp, $text, $match); + } + + $regexp = substr($regexp, 1, strlen($regexp) - 2 - strlen($this->_re_flags)); + mb_ereg_search_init($text); + if (!mb_ereg_search($regexp)) { + return false; + } + list($match) = mb_ereg_search_getregs(); + return true; + } /** * Find all link tags in a string representing a HTML document and * return a list of their attributes. * + * @todo This is quite ineffective and may fail with the default + * pcre.backtrack_limit of 100000 in PHP 5.2, if $html is big. + * It should rather use stripos (in PHP5) or strpos()+strtoupper() + * in PHP4 to manage this. + * * @param string $html The text to parse * @return array $list An array of arrays of attributes, one for each * link tag @@ -244,18 +264,23 @@ class Auth_OpenID_Parse { $stripped = substr($stripped, $html_begin, $html_end - $html_begin); + // Workaround to prevent PREG_BACKTRACK_LIMIT_ERROR: + $old_btlimit = ini_set( 'pcre.backtrack_limit', -1 ); + // Try to find the <HEAD> tag. $head_re = $this->headFind(); - $head_matches = array(); - if (!preg_match($head_re, $stripped, $head_matches)) { - return array(); + $head_match = ''; + if (!$this->match($head_re, $stripped, $head_match)) { + ini_set( 'pcre.backtrack_limit', $old_btlimit ); + return array(); } $link_data = array(); $link_matches = array(); - if (!preg_match_all($this->_link_find, $head_matches[0], + if (!preg_match_all($this->_link_find, $head_match, $link_matches)) { + ini_set( 'pcre.backtrack_limit', $old_btlimit ); return array(); } @@ -273,6 +298,7 @@ class Auth_OpenID_Parse { $link_data[] = $link_attrs; } + ini_set( 'pcre.backtrack_limit', $old_btlimit ); return $link_data; } @@ -349,4 +375,3 @@ function Auth_OpenID_legacy_discover($html_text, $server_rel, } } -?> \ No newline at end of file diff --git a/extlib/Auth/OpenID/PostgreSQLStore.php b/extlib/Auth/OpenID/PostgreSQLStore.php index 69d95e7b8d..d90e43e00d 100644 --- a/extlib/Auth/OpenID/PostgreSQLStore.php +++ b/extlib/Auth/OpenID/PostgreSQLStore.php @@ -110,4 +110,3 @@ class Auth_OpenID_PostgreSQLStore extends Auth_OpenID_SQLStore { } } -?> \ No newline at end of file diff --git a/extlib/Auth/OpenID/SQLStore.php b/extlib/Auth/OpenID/SQLStore.php index da93c6aa25..c04059732c 100644 --- a/extlib/Auth/OpenID/SQLStore.php +++ b/extlib/Auth/OpenID/SQLStore.php @@ -13,16 +13,6 @@ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache */ -/** - * Require the PEAR DB module because we'll need it for the SQL-based - * stores implemented here. We silence any errors from the inclusion - * because it might not be present, and a user of the SQL stores may - * supply an Auth_OpenID_DatabaseConnection instance that implements - * its own storage. - */ -global $__Auth_OpenID_PEAR_AVAILABLE; -$__Auth_OpenID_PEAR_AVAILABLE = @include_once 'DB.php'; - /** * @access private */ @@ -89,8 +79,6 @@ class Auth_OpenID_SQLStore extends Auth_OpenID_OpenIDStore { $associations_table = null, $nonces_table = null) { - global $__Auth_OpenID_PEAR_AVAILABLE; - $this->associations_table_name = "oid_associations"; $this->nonces_table_name = "oid_nonces"; @@ -113,7 +101,7 @@ class Auth_OpenID_SQLStore extends Auth_OpenID_OpenIDStore { // constant, so only try to use it if PEAR is present. Note // that Auth_Openid_Databaseconnection instances need not // implement ::setFetchMode for this reason. - if ($__Auth_OpenID_PEAR_AVAILABLE) { + if (is_subclass_of($this->connection, 'db_common')) { $this->connection->setFetchMode(DB_FETCHMODE_ASSOC); } @@ -482,7 +470,7 @@ class Auth_OpenID_SQLStore extends Auth_OpenID_OpenIDStore { global $Auth_OpenID_SKEW; if ( abs($timestamp - time()) > $Auth_OpenID_SKEW ) { - return False; + return false; } return $this->_add_nonce($server_url, $timestamp, $salt); @@ -566,4 +554,4 @@ class Auth_OpenID_SQLStore extends Auth_OpenID_OpenIDStore { } } -?> + diff --git a/extlib/Auth/OpenID/SQLiteStore.php b/extlib/Auth/OpenID/SQLiteStore.php index ec2bf58e46..4558fa1c33 100644 --- a/extlib/Auth/OpenID/SQLiteStore.php +++ b/extlib/Auth/OpenID/SQLiteStore.php @@ -68,4 +68,3 @@ class Auth_OpenID_SQLiteStore extends Auth_OpenID_SQLStore { } } -?> \ No newline at end of file diff --git a/extlib/Auth/OpenID/SReg.php b/extlib/Auth/OpenID/SReg.php index 63280769fd..5ece707243 100644 --- a/extlib/Auth/OpenID/SReg.php +++ b/extlib/Auth/OpenID/SReg.php @@ -94,7 +94,7 @@ Auth_OpenID_registerNamespaceAlias(Auth_OpenID_SREG_NS_URI_1_1, 'sreg'); * $endpoint: The endpoint object as returned by OpenID discovery. * returns whether an sreg type was advertised by the endpoint */ -function Auth_OpenID_supportsSReg(&$endpoint) +function Auth_OpenID_supportsSReg($endpoint) { return ($endpoint->usesExtension(Auth_OpenID_SREG_NS_URI_1_1) || $endpoint->usesExtension(Auth_OpenID_SREG_NS_URI_1_0)); @@ -122,7 +122,7 @@ class Auth_OpenID_SRegBase extends Auth_OpenID_Extension { * * @access private */ - function _getSRegNS(&$message) + static function _getSRegNS($message) { $alias = null; $found_ns_uri = null; @@ -173,7 +173,7 @@ class Auth_OpenID_SRegRequest extends Auth_OpenID_SRegBase { /** * Initialize an empty simple registration request. */ - function build($required=null, $optional=null, + static function build($required=null, $optional=null, $policy_url=null, $sreg_ns_uri=Auth_OpenID_SREG_NS_URI, $cls='Auth_OpenID_SRegRequest') @@ -213,7 +213,7 @@ class Auth_OpenID_SRegRequest extends Auth_OpenID_SRegBase { * * Returns the newly created simple registration request */ - function fromOpenIDRequest($request, $cls='Auth_OpenID_SRegRequest') + static function fromOpenIDRequest($request, $cls='Auth_OpenID_SRegRequest') { $obj = call_user_func_array(array($cls, 'build'), @@ -442,7 +442,7 @@ class Auth_OpenID_SRegResponse extends Auth_OpenID_SRegBase { * string (unicode) value. For instance, the nickname should be * stored under the key 'nickname'. */ - function extractResponse($request, $data) + static function extractResponse($request, $data) { $obj = new Auth_OpenID_SRegResponse(); $obj->ns_uri = $request->ns_uri; @@ -471,7 +471,7 @@ class Auth_OpenID_SRegResponse extends Auth_OpenID_SRegBase { * Returns a simple registration response containing the data that * was supplied with the C{id_res} response. */ - function fromSuccessResponse(&$success_response, $signed_only=true) + static function fromSuccessResponse($success_response, $signed_only=true) { global $Auth_OpenID_sreg_data_fields; @@ -518,4 +518,4 @@ class Auth_OpenID_SRegResponse extends Auth_OpenID_SRegBase { } } -?> + diff --git a/extlib/Auth/OpenID/Server.php b/extlib/Auth/OpenID/Server.php index f1db4d8725..cc8ba961c2 100644 --- a/extlib/Auth/OpenID/Server.php +++ b/extlib/Auth/OpenID/Server.php @@ -43,7 +43,7 @@ * consumers to add extensions to their requests. For example, with * sites using the Simple Registration * Extension - * (http://www.openidenabled.com/openid/simple-registration-extension/), + * (http://openid.net/specs/openid-simple-registration-extension-1_0.html), * a user can agree to have their nickname and e-mail address sent to * a site when they sign up. * @@ -365,7 +365,7 @@ class Auth_OpenID_CheckAuthRequest extends Auth_OpenID_Request { $this->message = null; } - function fromMessage($message, $server=null) + static function fromMessage($message, $server=null) { $required_keys = array('assoc_handle', 'sig', 'signed'); @@ -396,7 +396,7 @@ class Auth_OpenID_CheckAuthRequest extends Auth_OpenID_Request { return $result; } - function answer(&$signatory) + function answer($signatory) { $is_valid = $signatory->verify($this->assoc_handle, $this->signed); @@ -436,7 +436,7 @@ class Auth_OpenID_PlainTextServerSession { var $needs_math = false; var $allowed_assoc_types = array('HMAC-SHA1', 'HMAC-SHA256'); - function fromMessage($unused_request) + static function fromMessage($unused_request) { return new Auth_OpenID_PlainTextServerSession(); } @@ -469,7 +469,7 @@ class Auth_OpenID_DiffieHellmanSHA1ServerSession { $this->consumer_pubkey = $consumer_pubkey; } - function getDH($message) + static function getDH($message) { $dh_modulus = $message->getArg(Auth_OpenID_OPENID_NS, 'dh_modulus'); $dh_gen = $message->getArg(Auth_OpenID_OPENID_NS, 'dh_gen'); @@ -489,7 +489,7 @@ class Auth_OpenID_DiffieHellmanSHA1ServerSession { $missing); } - $lib =& Auth_OpenID_getMathLib(); + $lib = Auth_OpenID_getMathLib(); if ($dh_modulus || $dh_gen) { $dh_modulus = $lib->base64ToLong($dh_modulus); @@ -523,7 +523,7 @@ class Auth_OpenID_DiffieHellmanSHA1ServerSession { return array($dh, $consumer_pubkey); } - function fromMessage($message) + static function fromMessage($message) { $result = Auth_OpenID_DiffieHellmanSHA1ServerSession::getDH($message); @@ -538,7 +538,7 @@ class Auth_OpenID_DiffieHellmanSHA1ServerSession { function answer($secret) { - $lib =& Auth_OpenID_getMathLib(); + $lib = Auth_OpenID_getMathLib(); $mac_key = $this->dh->xorSecret($this->consumer_pubkey, $secret, $this->hash_func); return array( @@ -560,7 +560,7 @@ class Auth_OpenID_DiffieHellmanSHA256ServerSession var $hash_func = 'Auth_OpenID_SHA256'; var $allowed_assoc_types = array('HMAC-SHA256'); - function fromMessage($message) + static function fromMessage($message) { $result = Auth_OpenID_DiffieHellmanSHA1ServerSession::getDH($message); @@ -582,7 +582,7 @@ class Auth_OpenID_DiffieHellmanSHA256ServerSession class Auth_OpenID_AssociateRequest extends Auth_OpenID_Request { var $mode = "associate"; - function getSessionClasses() + static function getSessionClasses() { return array( 'no-encryption' => 'Auth_OpenID_PlainTextServerSession', @@ -590,14 +590,14 @@ class Auth_OpenID_AssociateRequest extends Auth_OpenID_Request { 'DH-SHA256' => 'Auth_OpenID_DiffieHellmanSHA256ServerSession'); } - function Auth_OpenID_AssociateRequest(&$session, $assoc_type) + function Auth_OpenID_AssociateRequest($session, $assoc_type) { - $this->session =& $session; + $this->session = $session; $this->namespace = Auth_OpenID_OPENID2_NS; $this->assoc_type = $assoc_type; } - function fromMessage($message, $server=null) + static function fromMessage($message, $server=null) { if ($message->isOpenID1()) { $session_type = $message->getArg(Auth_OpenID_OPENID_NS, @@ -696,7 +696,7 @@ class Auth_OpenID_AssociateRequest extends Auth_OpenID_Request { 'session_type', $preferred_session_type); } - + $response->code = AUTH_OPENID_HTTP_ERROR; return $response; } } @@ -734,7 +734,7 @@ class Auth_OpenID_CheckIDRequest extends Auth_OpenID_Request { */ var $namespace; - function make(&$message, $identity, $return_to, $trust_root = null, + static function make($message, $identity, $return_to, $trust_root = null, $immediate = false, $assoc_handle = null, $server = null) { if ($server === null) { @@ -752,7 +752,7 @@ class Auth_OpenID_CheckIDRequest extends Auth_OpenID_Request { $assoc_handle, $server); $r->namespace = $message->getOpenIDNamespace(); - $r->message =& $message; + $r->message = $message; if (!$r->trustRootValid()) { return new Auth_OpenID_UntrustedReturnURL($message, @@ -778,7 +778,7 @@ class Auth_OpenID_CheckIDRequest extends Auth_OpenID_Request { } $this->return_to = $return_to; $this->trust_root = $trust_root; - $this->server =& $server; + $this->server = $server; if ($immediate) { $this->immediate = true; @@ -817,11 +817,12 @@ class Auth_OpenID_CheckIDRequest extends Auth_OpenID_Request { */ function returnToVerified() { + $fetcher = Auth_Yadis_Yadis::getHTTPFetcher(); return call_user_func_array($this->verifyReturnTo, - array($this->trust_root, $this->return_to)); + array($this->trust_root, $this->return_to, $fetcher)); } - - function fromMessage(&$message, $server) + + static function fromMessage($message, $server) { $mode = $message->getArg(Auth_OpenID_OPENID_NS, 'mode'); $immediate = null; @@ -1097,7 +1098,7 @@ class Auth_OpenID_CheckIDRequest extends Auth_OpenID_Request { in OpenID 1.x immediate mode.'); } - $setup_request =& new Auth_OpenID_CheckIDRequest( + $setup_request = new Auth_OpenID_CheckIDRequest( $this->identity, $this->return_to, $this->trust_root, @@ -1183,9 +1184,9 @@ class Auth_OpenID_CheckIDRequest extends Auth_OpenID_Request { */ class Auth_OpenID_ServerResponse { - function Auth_OpenID_ServerResponse(&$request) + function Auth_OpenID_ServerResponse($request) { - $this->request =& $request; + $this->request = $request; $this->fields = new Auth_OpenID_Message($this->request->namespace); } @@ -1310,10 +1311,10 @@ class Auth_OpenID_Signatory { /** * Create a new signatory using a given store. */ - function Auth_OpenID_Signatory(&$store) + function Auth_OpenID_Signatory($store) { // assert store is not None - $this->store =& $store; + $this->store = $store; } /** @@ -1447,7 +1448,7 @@ class Auth_OpenID_Encoder { * Encode an {@link Auth_OpenID_ServerResponse} and return an * {@link Auth_OpenID_WebResponse}. */ - function encode(&$response) + function encode($response) { $cls = $this->responseFactory; @@ -1463,10 +1464,14 @@ class Auth_OpenID_Encoder { array('location' => $location)); } else if ($encode_as == Auth_OpenID_ENCODE_HTML_FORM) { $wr = new $cls(AUTH_OPENID_HTTP_OK, array(), - $response->toFormMarkup()); + $response->toHTML()); } else { return new Auth_OpenID_EncodingError($response); } + /* Allow the response to carry a custom error code (ex: for Association errors) */ + if(isset($response->code)) { + $wr->code = $response->code; + } return $wr; } } @@ -1478,16 +1483,16 @@ class Auth_OpenID_Encoder { */ class Auth_OpenID_SigningEncoder extends Auth_OpenID_Encoder { - function Auth_OpenID_SigningEncoder(&$signatory) + function Auth_OpenID_SigningEncoder($signatory) { - $this->signatory =& $signatory; + $this->signatory = $signatory; } /** * Sign an {@link Auth_OpenID_ServerResponse} and return an * {@link Auth_OpenID_WebResponse}. */ - function encode(&$response) + function encode($response) { // the isinstance is a bit of a kludge... it means there isn't // really an adapter to make the interfaces quite match. @@ -1516,9 +1521,9 @@ class Auth_OpenID_SigningEncoder extends Auth_OpenID_Encoder { */ class Auth_OpenID_Decoder { - function Auth_OpenID_Decoder(&$server) + function Auth_OpenID_Decoder($server) { - $this->server =& $server; + $this->server = $server; $this->handlers = array( 'checkid_setup' => 'Auth_OpenID_CheckIDRequest', @@ -1599,9 +1604,9 @@ class Auth_OpenID_Decoder { * @package OpenID */ class Auth_OpenID_EncodingError { - function Auth_OpenID_EncodingError(&$response) + function Auth_OpenID_EncodingError($response) { - $this->response =& $response; + $this->response = $response; } } @@ -1674,14 +1679,14 @@ class Auth_OpenID_UntrustedReturnURL extends Auth_OpenID_ServerError { * @package OpenID */ class Auth_OpenID_Server { - function Auth_OpenID_Server(&$store, $op_endpoint=null) + function Auth_OpenID_Server($store, $op_endpoint=null) { - $this->store =& $store; - $this->signatory =& new Auth_OpenID_Signatory($this->store); - $this->encoder =& new Auth_OpenID_SigningEncoder($this->signatory); - $this->decoder =& new Auth_OpenID_Decoder($this); + $this->store = $store; + $this->signatory = new Auth_OpenID_Signatory($this->store); + $this->encoder = new Auth_OpenID_SigningEncoder($this->signatory); + $this->decoder = new Auth_OpenID_Decoder($this); $this->op_endpoint = $op_endpoint; - $this->negotiator =& Auth_OpenID_getDefaultNegotiator(); + $this->negotiator = Auth_OpenID_getDefaultNegotiator(); } /** @@ -1699,7 +1704,7 @@ class Auth_OpenID_Server { { if (method_exists($this, "openid_" . $request->mode)) { $handler = array($this, "openid_" . $request->mode); - return call_user_func($handler, $request); + return call_user_func($handler, &$request); } return null; } @@ -1707,7 +1712,7 @@ class Auth_OpenID_Server { /** * The callback for 'check_authentication' messages. */ - function openid_check_authentication(&$request) + function openid_check_authentication($request) { return $request->answer($this->signatory); } @@ -1715,7 +1720,7 @@ class Auth_OpenID_Server { /** * The callback for 'associate' messages. */ - function openid_associate(&$request) + function openid_associate($request) { $assoc_type = $request->assoc_type; $session_type = $request->session->session_type; @@ -1738,7 +1743,7 @@ class Auth_OpenID_Server { * Encodes as response in the appropriate format suitable for * sending to the user agent. */ - function encodeResponse(&$response) + function encodeResponse($response) { return $this->encoder->encode($response); } @@ -1757,4 +1762,4 @@ class Auth_OpenID_Server { } } -?> + diff --git a/extlib/Auth/OpenID/ServerRequest.php b/extlib/Auth/OpenID/ServerRequest.php index 33a8556cea..69222a5e04 100644 --- a/extlib/Auth/OpenID/ServerRequest.php +++ b/extlib/Auth/OpenID/ServerRequest.php @@ -34,4 +34,3 @@ class Auth_OpenID_ServerRequest { } } -?> \ No newline at end of file diff --git a/extlib/Auth/OpenID/TrustRoot.php b/extlib/Auth/OpenID/TrustRoot.php index 4919a60651..000440b588 100644 --- a/extlib/Auth/OpenID/TrustRoot.php +++ b/extlib/Auth/OpenID/TrustRoot.php @@ -58,7 +58,7 @@ class Auth_OpenID_TrustRoot { * @return The URL upon which relying party discovery should be * run in order to verify the return_to URL */ - function buildDiscoveryURL($realm) + static function buildDiscoveryURL($realm) { $parsed = Auth_OpenID_TrustRoot::_parse($realm); @@ -93,7 +93,7 @@ class Auth_OpenID_TrustRoot { * @return mixed $parsed Either an associative array of trust root * parts or false if parsing failed. */ - function _parse($trust_root) + static function _parse($trust_root) { $trust_root = Auth_OpenID_urinorm($trust_root); if ($trust_root === null) { @@ -199,7 +199,7 @@ class Auth_OpenID_TrustRoot { * @param string $trust_root The trust root to check * @return bool $sanity Whether the trust root looks OK */ - function isSane($trust_root) + static function isSane($trust_root) { $parts = Auth_OpenID_TrustRoot::_parse($trust_root); if ($parts === false) { @@ -269,7 +269,7 @@ class Auth_OpenID_TrustRoot { * @return bool $matches Whether the URL matches against the * trust root */ - function match($trust_root, $url) + static function match($trust_root, $url) { $trust_root_parsed = Auth_OpenID_TrustRoot::_parse($trust_root); $url_parsed = Auth_OpenID_TrustRoot::_parse($url); @@ -341,7 +341,7 @@ class Auth_OpenID_TrustRoot { * @returns: The endpoint URL or None if the endpoint is not a * relying party endpoint. */ -function filter_extractReturnURL(&$endpoint) +function filter_extractReturnURL($endpoint) { if ($endpoint->matchTypes(array(Auth_OpenID_RP_RETURN_TO_URL_TYPE))) { return $endpoint; @@ -394,14 +394,14 @@ function Auth_OpenID_returnToMatches($allowed_return_to_urls, $return_to) * Given a relying party discovery URL return a list of return_to * URLs. */ -function Auth_OpenID_getAllowedReturnURLs($relying_party_url, &$fetcher, +function Auth_OpenID_getAllowedReturnURLs($relying_party_url, $fetcher, $discover_function=null) { if ($discover_function === null) { $discover_function = array('Auth_Yadis_Yadis', 'discover'); } - $xrds_parse_cb = array('Auth_OpenID_ServiceEndpoint', 'fromXRDS'); + $xrds_parse_cb = array('Auth_OpenID_ServiceEndpoint', 'consumerFromXRDS'); list($rp_url_after_redirects, $endpoints) = Auth_Yadis_getServiceEndpoints($relying_party_url, $xrds_parse_cb, @@ -413,7 +413,7 @@ function Auth_OpenID_getAllowedReturnURLs($relying_party_url, &$fetcher, } call_user_func_array($discover_function, - array($relying_party_url, $fetcher)); + array($relying_party_url, &$fetcher)); $return_to_urls = array(); $matching_endpoints = Auth_OpenID_extractReturnURL($endpoints); @@ -435,7 +435,7 @@ function Auth_OpenID_getAllowedReturnURLs($relying_party_url, &$fetcher, * * @return true if the return_to URL is valid for the realm */ -function Auth_OpenID_verifyReturnTo($realm_str, $return_to, &$fetcher, +function Auth_OpenID_verifyReturnTo($realm_str, $return_to, $fetcher, $_vrfy='Auth_OpenID_getAllowedReturnURLs') { $disco_url = Auth_OpenID_TrustRoot::buildDiscoveryURL($realm_str); @@ -445,7 +445,7 @@ function Auth_OpenID_verifyReturnTo($realm_str, $return_to, &$fetcher, } $allowable_urls = call_user_func_array($_vrfy, - array($disco_url, &$fetcher)); + array($disco_url, $fetcher)); // The realm_str could not be parsed. if ($allowable_urls === false) { @@ -459,4 +459,3 @@ function Auth_OpenID_verifyReturnTo($realm_str, $return_to, &$fetcher, } } -?> \ No newline at end of file diff --git a/extlib/Auth/OpenID/URINorm.php b/extlib/Auth/OpenID/URINorm.php index f821d836a9..c051b550aa 100644 --- a/extlib/Auth/OpenID/URINorm.php +++ b/extlib/Auth/OpenID/URINorm.php @@ -246,4 +246,4 @@ function Auth_OpenID_urinorm($uri) return $scheme . '://' . $authority . $path . $query . $fragment; } -?> + diff --git a/extlib/Auth/Yadis/HTTPFetcher.php b/extlib/Auth/Yadis/HTTPFetcher.php index 963b9a49a4..148cde1b2e 100644 --- a/extlib/Auth/Yadis/HTTPFetcher.php +++ b/extlib/Auth/Yadis/HTTPFetcher.php @@ -115,12 +115,40 @@ class Auth_Yadis_HTTPFetcher { /** * @access private */ - function _findRedirect($headers) + function _findRedirect($headers, $url) { foreach ($headers as $line) { if (strpos(strtolower($line), "location: ") === 0) { $parts = explode(" ", $line, 2); - return $parts[1]; + $loc = $parts[1]; + $ppos = strpos($loc, "://"); + if ($ppos === false || $ppos > strpos($loc, "/")) { + /* no host; add it */ + $hpos = strpos($url, "://"); + $prt = substr($url, 0, $hpos+3); + $url = substr($url, $hpos+3); + if (substr($loc, 0, 1) == "/") { + /* absolute path */ + $fspos = strpos($url, "/"); + if ($fspos) $loc = $prt.substr($url, 0, $fspos).$loc; + else $loc = $prt.$url.$loc; + } else { + /* relative path */ + $pp = $prt; + while (1) { + $xpos = strpos($url, "/"); + if ($xpos === false) break; + $apos = strpos($url, "?"); + if ($apos !== false && $apos < $xpos) break; + $apos = strpos($url, "&"); + if ($apos !== false && $apos < $xpos) break; + $pp .= substr($url, 0, $xpos+1); + $url = substr($url, $xpos+1); + } + $loc = $pp.$loc; + } + } + return $loc; } } return null; @@ -144,4 +172,3 @@ class Auth_Yadis_HTTPFetcher { } } -?> \ No newline at end of file diff --git a/extlib/Auth/Yadis/Manager.php b/extlib/Auth/Yadis/Manager.php index d50cf7ad65..ee6f68bcb6 100644 --- a/extlib/Auth/Yadis/Manager.php +++ b/extlib/Auth/Yadis/Manager.php @@ -387,11 +387,11 @@ class Auth_Yadis_Discovery { * @param string $session_key_suffix The optional session key * suffix override. */ - function Auth_Yadis_Discovery(&$session, $url, + function Auth_Yadis_Discovery($session, $url, $session_key_suffix = null) { /// Initialize a discovery object - $this->session =& $session; + $this->session = $session; $this->url = $url; if ($session_key_suffix === null) { $session_key_suffix = $this->DEFAULT_SUFFIX; @@ -405,7 +405,7 @@ class Auth_Yadis_Discovery { * Return the next authentication service for the pair of * user_input and session. This function handles fallback. */ - function getNextService($discover_cb, &$fetcher) + function getNextService($discover_cb, $fetcher) { $manager = $this->getManager(); if (!$manager || (!$manager->services)) { @@ -413,7 +413,7 @@ class Auth_Yadis_Discovery { list($yadis_url, $services) = call_user_func($discover_cb, $this->url, - $fetcher); + &$fetcher); $manager = $this->createManager($services, $yadis_url); } @@ -466,7 +466,7 @@ class Auth_Yadis_Discovery { * @param $force True if the manager should be returned regardless * of whether it's a manager for $this->url. */ - function &getManager($force=false) + function getManager($force=false) { // Extract the YadisServiceManager for this object's URL and // suffix from the session. @@ -481,16 +481,13 @@ class Auth_Yadis_Discovery { if ($manager && ($manager->forURL($this->url) || $force)) { return $manager; - } else { - $unused = null; - return $unused; } } /** * @access private */ - function &createManager($services, $yadis_url = null) + function createManager($services, $yadis_url = null) { $key = $this->getSessionKey(); if ($this->getManager()) { @@ -504,10 +501,6 @@ class Auth_Yadis_Discovery { $this->session->set($this->session_key, serialize($loader->toSession($manager))); return $manager; - } else { - // Oh, PHP. - $unused = null; - return $unused; } } @@ -526,4 +519,3 @@ class Auth_Yadis_Discovery { } } -?> \ No newline at end of file diff --git a/extlib/Auth/Yadis/Misc.php b/extlib/Auth/Yadis/Misc.php index 1134a4ff4b..a5afa8e9a8 100644 --- a/extlib/Auth/Yadis/Misc.php +++ b/extlib/Auth/Yadis/Misc.php @@ -56,4 +56,3 @@ function Auth_Yadis_startswith($s, $stuff) return strpos($s, $stuff) === 0; } -?> \ No newline at end of file diff --git a/extlib/Auth/Yadis/ParanoidHTTPFetcher.php b/extlib/Auth/Yadis/ParanoidHTTPFetcher.php index 6a418260ee..4da7c94c0d 100644 --- a/extlib/Auth/Yadis/ParanoidHTTPFetcher.php +++ b/extlib/Auth/Yadis/ParanoidHTTPFetcher.php @@ -109,9 +109,9 @@ class Auth_Yadis_ParanoidHTTPFetcher extends Auth_Yadis_HTTPFetcher { } curl_setopt($c, CURLOPT_WRITEFUNCTION, - array(&$this, "_writeData")); + array($this, "_writeData")); curl_setopt($c, CURLOPT_HEADERFUNCTION, - array(&$this, "_writeHeader")); + array($this, "_writeHeader")); if ($extra_headers) { curl_setopt($c, CURLOPT_HTTPHEADER, $extra_headers); @@ -128,6 +128,10 @@ class Auth_Yadis_ParanoidHTTPFetcher extends Auth_Yadis_HTTPFetcher { curl_setopt($c, CURLOPT_TIMEOUT, $off); curl_setopt($c, CURLOPT_URL, $url); + if (defined('Auth_OpenID_VERIFY_HOST')) { + curl_setopt($c, CURLOPT_SSL_VERIFYPEER, true); + curl_setopt($c, CURLOPT_SSL_VERIFYHOST, 2); + } curl_exec($c); $code = curl_getinfo($c, CURLINFO_HTTP_CODE); @@ -142,12 +146,17 @@ class Auth_Yadis_ParanoidHTTPFetcher extends Auth_Yadis_HTTPFetcher { } if (in_array($code, array(301, 302, 303, 307))) { - $url = $this->_findRedirect($headers); + $url = $this->_findRedirect($headers, $url); $redir = true; } else { $redir = false; curl_close($c); + if (defined('Auth_OpenID_VERIFY_HOST') && + $this->isHTTPS($url)) { + Auth_OpenID::log('OpenID: Verified SSL host %s using '. + 'curl/get', $url); + } $new_headers = array(); foreach ($headers as $header) { @@ -190,7 +199,12 @@ class Auth_Yadis_ParanoidHTTPFetcher extends Auth_Yadis_HTTPFetcher { curl_setopt($c, CURLOPT_TIMEOUT, $this->timeout); curl_setopt($c, CURLOPT_URL, $url); curl_setopt($c, CURLOPT_WRITEFUNCTION, - array(&$this, "_writeData")); + array($this, "_writeData")); + + if (defined('Auth_OpenID_VERIFY_HOST')) { + curl_setopt($c, CURLOPT_SSL_VERIFYPEER, true); + curl_setopt($c, CURLOPT_SSL_VERIFYHOST, 2); + } curl_exec($c); @@ -198,9 +212,15 @@ class Auth_Yadis_ParanoidHTTPFetcher extends Auth_Yadis_HTTPFetcher { if (!$code) { Auth_OpenID::log("Got no response code when fetching %s", $url); + Auth_OpenID::log("CURL error (%s): %s", + curl_errno($c), curl_error($c)); return null; } + if (defined('Auth_OpenID_VERIFY_HOST') && $this->isHTTPS($url)) { + Auth_OpenID::log('OpenID: Verified SSL host %s using '. + 'curl/post', $url); + } $body = $this->data; curl_close($c); @@ -223,4 +243,3 @@ class Auth_Yadis_ParanoidHTTPFetcher extends Auth_Yadis_HTTPFetcher { } } -?> \ No newline at end of file diff --git a/extlib/Auth/Yadis/ParseHTML.php b/extlib/Auth/Yadis/ParseHTML.php index 297ccbd2c3..6f0f8b7e28 100644 --- a/extlib/Auth/Yadis/ParseHTML.php +++ b/extlib/Auth/Yadis/ParseHTML.php @@ -256,4 +256,3 @@ class Auth_Yadis_ParseHTML { } } -?> \ No newline at end of file diff --git a/extlib/Auth/Yadis/PlainHTTPFetcher.php b/extlib/Auth/Yadis/PlainHTTPFetcher.php index 3e0ca2bb0c..26890539aa 100644 --- a/extlib/Auth/Yadis/PlainHTTPFetcher.php +++ b/extlib/Auth/Yadis/PlainHTTPFetcher.php @@ -122,7 +122,7 @@ class Auth_Yadis_PlainHTTPFetcher extends Auth_Yadis_HTTPFetcher { $code = $http_code[1]; if (in_array($code, array('301', '302'))) { - $url = $this->_findRedirect($headers); + $url = $this->_findRedirect($headers, $url); $redir = true; } else { $redir = false; @@ -246,4 +246,3 @@ class Auth_Yadis_PlainHTTPFetcher extends Auth_Yadis_HTTPFetcher { } } -?> \ No newline at end of file diff --git a/extlib/Auth/Yadis/XML.php b/extlib/Auth/Yadis/XML.php index 81b2ce2210..cf1f5c41b2 100644 --- a/extlib/Auth/Yadis/XML.php +++ b/extlib/Auth/Yadis/XML.php @@ -310,20 +310,16 @@ $__Auth_Yadis_defaultParser = null; * @param Auth_Yadis_XMLParser $parser An instance of a * Auth_Yadis_XMLParser subclass. */ -function Auth_Yadis_setDefaultParser(&$parser) +function Auth_Yadis_setDefaultParser($parser) { global $__Auth_Yadis_defaultParser; - $__Auth_Yadis_defaultParser =& $parser; + $__Auth_Yadis_defaultParser = $parser; } function Auth_Yadis_getSupportedExtensions() { - return array( - 'dom' => array('classname' => 'Auth_Yadis_dom', - 'libname' => array('dom.so', 'dom.dll')), - 'domxml' => array('classname' => 'Auth_Yadis_domxml', - 'libname' => array('domxml.so', 'php_domxml.dll')), - ); + return array('dom' => 'Auth_Yadis_dom', + 'domxml' => 'Auth_Yadis_domxml'); } /** @@ -332,43 +328,25 @@ function Auth_Yadis_getSupportedExtensions() * Auth_Yadis_setDefaultParser has been called, the parser used in * that call will be returned instead. */ -function &Auth_Yadis_getXMLParser() +function Auth_Yadis_getXMLParser() { global $__Auth_Yadis_defaultParser; - + if (isset($__Auth_Yadis_defaultParser)) { return $__Auth_Yadis_defaultParser; } - - $p = null; - $classname = null; - - $extensions = Auth_Yadis_getSupportedExtensions(); - - // Return a wrapper for the resident implementation, if any. - foreach ($extensions as $name => $params) { - if (!extension_loaded($name)) { - foreach ($params['libname'] as $libname) { - if (@dl($libname)) { - $classname = $params['classname']; - } - } - } else { - $classname = $params['classname']; - } - if (isset($classname)) { - $p = new $classname(); - return $p; - } - } - - if (!isset($p)) { - trigger_error('No XML parser was found', E_USER_ERROR); - } else { + + foreach(Auth_Yadis_getSupportedExtensions() as $extension => $classname) + { + if (extension_loaded($extension)) + { + $p = new $classname(); Auth_Yadis_setDefaultParser($p); + return $p; + } } - - return $p; + + return false; } -?> + diff --git a/extlib/Auth/Yadis/XRDS.php b/extlib/Auth/Yadis/XRDS.php index f14a7948e1..1f5af96fb2 100644 --- a/extlib/Auth/Yadis/XRDS.php +++ b/extlib/Auth/Yadis/XRDS.php @@ -255,11 +255,11 @@ class Auth_Yadis_XRDS { * Instantiate a Auth_Yadis_XRDS object. Requires an XPath * instance which has been used to parse a valid XRDS document. */ - function Auth_Yadis_XRDS(&$xmlParser, &$xrdNodes) + function Auth_Yadis_XRDS($xmlParser, $xrdNodes) { - $this->parser =& $xmlParser; + $this->parser = $xmlParser; $this->xrdNode = $xrdNodes[count($xrdNodes) - 1]; - $this->allXrdNodes =& $xrdNodes; + $this->allXrdNodes = $xrdNodes; $this->serviceList = array(); $this->_parse(); } @@ -273,7 +273,7 @@ class Auth_Yadis_XRDS { * @return mixed $xrds An instance of Auth_Yadis_XRDS or null, * depending on the validity of $xml_string */ - function &parseXRDS($xml_string, $extra_ns_map = null) + static function parseXRDS($xml_string, $extra_ns_map = null) { $_null = null; @@ -352,9 +352,9 @@ class Auth_Yadis_XRDS { $services = $this->parser->evalXPath('xrd:Service', $this->xrdNode); foreach ($services as $node) { - $s =& new Auth_Yadis_Service(); + $s = new Auth_Yadis_Service(); $s->element = $node; - $s->parser =& $this->parser; + $s->parser = $this->parser; $priority = $s->getPriority(); @@ -428,7 +428,8 @@ class Auth_Yadis_XRDS { $matches = 0; foreach ($filters as $filter) { - if (call_user_func_array($filter, array($service))) { + + if (call_user_func_array($filter, array(&$service))) { $matches++; if ($filter_mode == SERVICES_YADIS_MATCH_ANY) { @@ -475,4 +476,3 @@ class Auth_Yadis_XRDS { } } -?> \ No newline at end of file diff --git a/extlib/Auth/Yadis/XRI.php b/extlib/Auth/Yadis/XRI.php index 4e34623176..0143a692e0 100644 --- a/extlib/Auth/Yadis/XRI.php +++ b/extlib/Auth/Yadis/XRI.php @@ -190,7 +190,7 @@ function Auth_Yadis_getCanonicalID($iname, $xrds) // Now nodes are in reverse order. $xrd_list = array_reverse($xrds->allXrdNodes); - $parser =& $xrds->parser; + $parser = $xrds->parser; $node = $xrd_list[0]; $canonicalID_nodes = $parser->evalXPath('xrd:CanonicalID', $node); @@ -231,4 +231,4 @@ function Auth_Yadis_getCanonicalID($iname, $xrds) return $canonicalID; } -?> + diff --git a/extlib/Auth/Yadis/XRIRes.php b/extlib/Auth/Yadis/XRIRes.php index 4e8e8d0372..5e11587352 100644 --- a/extlib/Auth/Yadis/XRIRes.php +++ b/extlib/Auth/Yadis/XRIRes.php @@ -8,9 +8,9 @@ require_once 'Auth/Yadis/XRDS.php'; require_once 'Auth/Yadis/XRI.php'; class Auth_Yadis_ProxyResolver { - function Auth_Yadis_ProxyResolver(&$fetcher, $proxy_url = null) + function Auth_Yadis_ProxyResolver($fetcher, $proxy_url = null) { - $this->fetcher =& $fetcher; + $this->fetcher = $fetcher; $this->proxy_url = $proxy_url; if (!$this->proxy_url) { $this->proxy_url = Auth_Yadis_getDefaultProxy(); @@ -69,4 +69,4 @@ class Auth_Yadis_ProxyResolver { } } -?> + diff --git a/extlib/Auth/Yadis/Yadis.php b/extlib/Auth/Yadis/Yadis.php index d89f77c6d7..9ea2db7f91 100644 --- a/extlib/Auth/Yadis/Yadis.php +++ b/extlib/Auth/Yadis/Yadis.php @@ -105,7 +105,7 @@ class Auth_Yadis_DiscoveryResult { function usedYadisLocation() { // Was the Yadis protocol's indirection used? - return $this->normalized_uri != $this->xrds_uri; + return ($this->xrds_uri && $this->normalized_uri != $this->xrds_uri); } function isXRDS() @@ -141,7 +141,7 @@ function Auth_Yadis_getServiceEndpoints($input_url, $xrds_parse_func, } $yadis_result = call_user_func_array($discover_func, - array($input_url, $fetcher)); + array($input_url, &$fetcher)); if ($yadis_result === null) { return array($input_url, array()); @@ -196,7 +196,7 @@ function Auth_Yadis_getServiceEndpoints($input_url, $xrds_parse_func, * The filter functions (whose names appear in the array passed to * services()) take the following form: * - * <pre> function myFilter(&$service) { + * <pre> function myFilter($service) { * // Query $service object here. Return true if the service * // matches your query; false if not. * }</pre> @@ -207,7 +207,7 @@ function Auth_Yadis_getServiceEndpoints($input_url, $xrds_parse_func, * this contrived example): * * <pre> - * function URIMatcher(&$service) { + * function URIMatcher($service) { * foreach ($service->getElements('xrd:URI') as $uri) { * if (preg_match("/some_pattern/", * $service->parser->content($uri))) { @@ -250,7 +250,7 @@ class Auth_Yadis_Yadis { * If Auth_Yadis_CURL_OVERRIDE is defined, this method will always * return a {@link Auth_Yadis_PlainHTTPFetcher}. */ - function getHTTPFetcher($timeout = 20) + static function getHTTPFetcher($timeout = 20) { if (Auth_Yadis_Yadis::curlPresent() && (!defined('Auth_Yadis_CURL_OVERRIDE'))) { @@ -261,7 +261,7 @@ class Auth_Yadis_Yadis { return $fetcher; } - function curlPresent() + static function curlPresent() { return function_exists('curl_init'); } @@ -269,7 +269,7 @@ class Auth_Yadis_Yadis { /** * @access private */ - function _getHeader($header_list, $names) + static function _getHeader($header_list, $names) { foreach ($header_list as $name => $value) { foreach ($names as $n) { @@ -285,7 +285,7 @@ class Auth_Yadis_Yadis { /** * @access private */ - function _getContentType($content_type_header) + static function _getContentType($content_type_header) { if ($content_type_header) { $parts = explode(";", $content_type_header); @@ -317,7 +317,7 @@ class Auth_Yadis_Yadis { * Auth_Yadis_Yadis, depending on whether the discovery * succeeded. */ - function discover($uri, &$fetcher, + static function discover($uri, $fetcher, $extra_ns_map = null, $timeout = 20) { $result = new Auth_Yadis_DiscoveryResult($uri); @@ -379,4 +379,4 @@ class Auth_Yadis_Yadis { } } -?> + From 21f253c5845eb17b7aa599b030855324caf9f312 Mon Sep 17 00:00:00 2001 From: Brion Vibber <brion@pobox.com> Date: Tue, 29 Jun 2010 10:31:30 -0400 Subject: [PATCH 24/25] Fix regression in OStatus remote group subscribe -- a bug was previously masked silently (call to nonexistent getProfileUrl() method on User_group -- now replaced with homeUrl() which does the thing we wanted here) --- plugins/OStatus/actions/ostatusgroup.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/OStatus/actions/ostatusgroup.php b/plugins/OStatus/actions/ostatusgroup.php index f325ba0532..1b368de63c 100644 --- a/plugins/OStatus/actions/ostatusgroup.php +++ b/plugins/OStatus/actions/ostatusgroup.php @@ -104,7 +104,7 @@ class OStatusGroupAction extends OStatusSubAction } $this->showEntity($group, - $group->getProfileUrl(), + $group->homeUrl(), $group->homepage_logo, $group->description); return $ok; From 452123916d08354d11a198517cbc91980a113fcd Mon Sep 17 00:00:00 2001 From: Brion Vibber <brion@pobox.com> Date: Tue, 29 Jun 2010 11:23:35 -0400 Subject: [PATCH 25/25] Updates to README w/ summary changelist --- README | 49 ++++++++++++++++++------------------------------- 1 file changed, 18 insertions(+), 31 deletions(-) diff --git a/README b/README index 452123db49..9e59ccb440 100644 --- a/README +++ b/README @@ -77,40 +77,27 @@ for additional terms. New this version ================ -This is a minor bug and feature release since version 0.9.1 released 28 -March 2010. +This is a minor bug and feature release since version 0.9.2 released on +4 May 2010. -Because of fixes to OStatus bugs, it is highly recommended that all -public sites upgrade to the new version immediately. +For best compatibility with client software and site federation, and a lot of +bug fixes, it is highly recommended that all public sites upgrade to the new +version. Notable changes this version: -- Installer no longer fails with a PHP fatal error when trying to set up the - subscription to update@status.net -- Fixed email notifications for @-replies that come in via OStatus -- OStatus related Fixes to the cloudy theme -- Pass geo locations over Twitter bridge (will only be used if enabled on the - Twitter side) -- scripts/showplugins.php - script to dump the list of activated plugins and - their settings -- scripts/fixup_blocks.php - script to finds any stray subscriptions in - violation of blocks, and removes them -- Allow blocking someone who's not currently subscribed to you (prevents - seeing @-replies from them, or them subbing to you in future) -- Default 2-second timeout on Geonames web service lookups -- Improved localization for plugins -- New anti-spam measures: added nofollow rels to group members list, - subscribers list -- Shared cache key option for Geonames plugin (lets multi-instance sites - share their cached geoname lookups) -- Stability fixes to the TwitterStatusFetcher -- If user allows location sharing but turned off browser location use profile - location -- Improved group listing via the API -- Improved FOAF output -- Several other bugfixes +- Enhanced API output to aid StatusNet-specific clients +- Many updates to user interface translation from TranslateWiki +- OStatus now works subscribing to SSL-protected sites by default +- OpenID now works on PHP 5.3, supports closer site integration. +- Numerous API and FOAF output fixes. +- Fixes to Facebook integration for FB API behavior changes +- PostgreSQL support updates +- Initial version of a custom theme uploader (disabled by default) +- LDAP auth plugins cleanup +- Many other bugfixes -A full changelog is available at http://status.net/wiki/StatusNet_0.9.2. +A full changelog is available at http://status.net/wiki/StatusNet_0.9.3. Prerequisites ============= @@ -121,8 +108,8 @@ run correctly. - PHP 5.2.3+. It may be possible to run this software on earlier versions of PHP, but many of the functions used are only available in PHP 5.2 or above. 5.2.6 or later is needed for XMPP background - daemons on 64-bit platforms. PHP 5.3.x should work but is known - to cause some failures for OpenID. + daemons on 64-bit platforms. PHP 5.3.x should work correctly in this + release, but problems with some plugins are possible. - MySQL 5.x. The StatusNet database is stored, by default, in a MySQL server. It has been primarily tested on 5.x servers, although it may be possible to install on earlier (or later!) versions. The server