From 602dbb5f8746ac032d59794c3e8d94d47c0678b7 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Mon, 18 Jan 2010 11:12:05 +0000 Subject: [PATCH 01/53] Moved farbtastic's stylesheet to use relative paths for its own images --- {theme/base/css => js/farbtastic}/farbtastic.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename {theme/base/css => js/farbtastic}/farbtastic.css (70%) diff --git a/theme/base/css/farbtastic.css b/js/farbtastic/farbtastic.css similarity index 70% rename from theme/base/css/farbtastic.css rename to js/farbtastic/farbtastic.css index 7efcc73c3b..a88e7b868b 100644 --- a/theme/base/css/farbtastic.css +++ b/js/farbtastic/farbtastic.css @@ -16,17 +16,17 @@ height: 101px; } .farbtastic .wheel { - background: url(../../../js/farbtastic/wheel.png) no-repeat; + background: url(wheel.png) no-repeat; width: 195px; height: 195px; } .farbtastic .overlay { - background: url(../../../js/farbtastic/mask.png) no-repeat; + background: url(mask.png) no-repeat; } .farbtastic .marker { width: 17px; height: 17px; margin: -8px 0 0 -8px; overflow: hidden; - background: url(../../../js/farbtastic/marker.png) no-repeat; + background: url(marker.png) no-repeat; } From 187a70873a1af2eceafa12333e0c04750d01b5c2 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Mon, 18 Jan 2010 11:29:05 +0000 Subject: [PATCH 02/53] Updated path to farbtastic stylesheet --- actions/designadminpanel.php | 2 +- lib/designsettings.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/actions/designadminpanel.php b/actions/designadminpanel.php index f862aff0eb..72ad6ade2a 100644 --- a/actions/designadminpanel.php +++ b/actions/designadminpanel.php @@ -289,7 +289,7 @@ class DesignadminpanelAction extends AdminPanelAction function showStylesheets() { parent::showStylesheets(); - $this->cssLink('css/farbtastic.css','base','screen, projection, tv'); + $this->cssLink('js/farbtastic/farbtastic.css',null,'screen, projection, tv'); } /** diff --git a/lib/designsettings.php b/lib/designsettings.php index b70ba0dfca..8e44c03a92 100644 --- a/lib/designsettings.php +++ b/lib/designsettings.php @@ -314,7 +314,7 @@ class DesignSettingsAction extends AccountSettingsAction function showStylesheets() { parent::showStylesheets(); - $this->cssLink('css/farbtastic.css','base','screen, projection, tv'); + $this->cssLink('js/farbtastic/farbtastic.css',null,'screen, projection, tv'); } /** From 42601b1ff0f054223ca7fb11c50aa236a87d07fa Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Mon, 18 Jan 2010 12:55:14 +0000 Subject: [PATCH 03/53] Some JS cleaning up for NoticeLocationAttach (which fixes also fixes a few bugs in WebKit) --- js/util.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/js/util.js b/js/util.js index a10e9d15ae..aeec8d89d7 100644 --- a/js/util.js +++ b/js/util.js @@ -494,7 +494,7 @@ var SN = { // StatusNet $.cookie(SN.C.S.NoticeDataGeoCookie, 'disabled'); } - function getJSONgeocodeURL(geocodeURL, data, position) { + function getJSONgeocodeURL(geocodeURL, data) { $.getJSON(geocodeURL, data, function(location) { var lns, lid; @@ -509,7 +509,7 @@ var SN = { // StatusNet } if (typeof(location.name) == 'undefined') { - NLN_text = position.coords.latitude + ';' + position.coords.longitude; + NLN_text = data.lat + ';' + data.lon; } else { NLN_text = location.name; @@ -571,7 +571,7 @@ var SN = { // StatusNet token: $('#token').val() }; - getJSONgeocodeURL(geocodeURL, data, position); + getJSONgeocodeURL(geocodeURL, data); }, function(error) { @@ -593,12 +593,12 @@ var SN = { // StatusNet else { if (NLat.length > 0 && NLon.length > 0) { var data = { - 'lat': NLat, - 'lon': NLon, - 'token': $('#token').val() + lat: NLat, + lon: NLon, + token: $('#token').val() }; - getJSONgeocodeURL(geocodeURL, data, position); + getJSONgeocodeURL(geocodeURL, data); } else { removeNoticeDataGeo(); From d501acf4388e936d1b793e2516393d78809b700d Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Mon, 18 Jan 2010 17:17:02 +0000 Subject: [PATCH 04/53] Missing null className for incoming email form legend --- actions/emailsettings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/emailsettings.php b/actions/emailsettings.php index bfef2970da..08608348cd 100644 --- a/actions/emailsettings.php +++ b/actions/emailsettings.php @@ -130,7 +130,7 @@ class EmailsettingsAction extends AccountSettingsAction if (common_config('emailpost', 'enabled') && $user->email) { $this->elementStart('fieldset', array('id' => 'settings_email_incoming')); - $this->element('legend',_('Incoming email')); + $this->element('legend', null, _('Incoming email')); if ($user->incomingemail) { $this->elementStart('p'); $this->element('span', 'address', $user->incomingemail); From 3bf4056055fd5f278db8b8a46f4e524889483266 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Mon, 18 Jan 2010 09:28:58 -0800 Subject: [PATCH 05/53] Fix order of params on 'plugin not found' exception --- lib/statusnet.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/statusnet.php b/lib/statusnet.php index 29e9030267..beeb26cccd 100644 --- a/lib/statusnet.php +++ b/lib/statusnet.php @@ -63,7 +63,7 @@ class StatusNet } } if (!class_exists($pluginclass)) { - throw new ServerException(500, "Plugin $name not found."); + throw new ServerException("Plugin $name not found.", 500); } } From ae9f2bf18725d72952a7f884dc9faebe92dc0541 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Mon, 18 Jan 2010 09:37:42 -0800 Subject: [PATCH 06/53] add a quickie plugins/ dir readme mentioning how to add plugins, plus ref to wiki pages --- plugins/README-plugins | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 plugins/README-plugins diff --git a/plugins/README-plugins b/plugins/README-plugins new file mode 100644 index 0000000000..cdce7eb18c --- /dev/null +++ b/plugins/README-plugins @@ -0,0 +1,21 @@ +Several example plugins are included in the plugins/ directory. You +can enable a plugin with the following line in config.php: + + addPlugin('Example', array('param1' => 'value1', + 'param2' => 'value2')); + +This will look for and load files named 'ExamplePlugin.php' or +'Example/ExamplePlugin.php' either in the plugins/ directory (for +plugins that ship with StatusNet) or in the local/ directory (for +plugins you write yourself or that you get from somewhere else) or +local/plugins/. + +Plugins are documented in their own directories. + + +Additional information on using and developing plugins can be found +on the StatusNet wiki: + +http://status.net/wiki/Plugins +http://status.net/wiki/Plugin_development + From d29a791fff9469d2b097d62028be9c8e06482e69 Mon Sep 17 00:00:00 2001 From: Siebrand Mazeland Date: Tue, 19 Jan 2010 00:24:53 +0100 Subject: [PATCH 07/53] Localisation updates for !StatusNet from !translatewiki.net !sntrans --- locale/ar/LC_MESSAGES/statusnet.po | 30 +-- locale/ja/LC_MESSAGES/statusnet.po | 14 +- locale/pt_BR/LC_MESSAGES/statusnet.po | 14 +- locale/ru/LC_MESSAGES/statusnet.po | 12 +- locale/statusnet.po | 6 +- locale/sv/LC_MESSAGES/statusnet.po | 319 +++++++++++--------------- 6 files changed, 177 insertions(+), 218 deletions(-) diff --git a/locale/ar/LC_MESSAGES/statusnet.po b/locale/ar/LC_MESSAGES/statusnet.po index 4565870408..4024aed11b 100644 --- a/locale/ar/LC_MESSAGES/statusnet.po +++ b/locale/ar/LC_MESSAGES/statusnet.po @@ -9,12 +9,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-16 17:51:26+0000\n" +"POT-Creation-Date: 2010-01-18 23:16+0000\n" +"PO-Revision-Date: 2010-01-18 23:17:05+0000\n" "Language-Team: Arabic\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61138); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61218); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: ar\n" "X-Message-Group: out-statusnet\n" @@ -415,7 +415,7 @@ msgstr "مجموعات %s" #: actions/apioauthauthorize.php:108 actions/apioauthauthorize.php:114 msgid "Bad request." -msgstr "" +msgstr "طلب سيء." #: actions/apioauthauthorize.php:134 actions/avatarsettings.php:268 #: actions/deletenotice.php:157 actions/disfavor.php:74 @@ -531,7 +531,7 @@ msgstr "حُذِفت الحالة." #: actions/apistatusesshow.php:144 msgid "No status with that ID found." -msgstr "" +msgstr "لا حالة وُجدت بهذه الهوية." #: actions/apistatusesupdate.php:162 actions/newnotice.php:155 #: lib/mailhandler.php:60 @@ -1026,7 +1026,7 @@ msgstr "لا مستند كهذا." #: actions/editapplication.php:54 lib/applicationeditform.php:136 msgid "Edit application" -msgstr "" +msgstr "عدّل التطبيق" #: actions/editapplication.php:66 msgid "You must be logged in to edit an application." @@ -1072,7 +1072,7 @@ msgstr "مسار المصدر ليس صحيحا." #: actions/editapplication.php:200 actions/newapplication.php:185 msgid "Organization is required." -msgstr "" +msgstr "المنظمة مطلوبة." #: actions/editapplication.php:203 actions/newapplication.php:188 msgid "Organization is too long (max 255 chars)." @@ -1080,7 +1080,7 @@ msgstr "المنظمة طويلة جدا (الأقصى 255 حرفا)." #: actions/editapplication.php:206 actions/newapplication.php:191 msgid "Organization homepage is required." -msgstr "" +msgstr "صفحة المنظمة الرئيسية مطلوبة." #: actions/editapplication.php:215 actions/newapplication.php:203 msgid "Callback is too long." @@ -1289,7 +1289,7 @@ msgstr "أزيل هذا العنوان." #: actions/emailsettings.php:446 actions/smssettings.php:518 msgid "No incoming email address." -msgstr "" +msgstr "لا عنوان بريد إلكتروني وارد." #: actions/emailsettings.php:456 actions/emailsettings.php:478 #: actions/smssettings.php:528 actions/smssettings.php:552 @@ -1395,7 +1395,7 @@ msgstr "المستخدم الذي تستمع إليه غير موجود." #: actions/finishremotesubscribe.php:87 actions/remotesubscribe.php:59 msgid "You can use the local subscription!" -msgstr "" +msgstr "تستطيع استخدام الاشتراك المحلي!" #: actions/finishremotesubscribe.php:99 msgid "That user has blocked you from subscribing." @@ -2078,7 +2078,7 @@ msgstr "" #: actions/oauthconnectionssettings.php:170 msgid "You are not a user of that application." -msgstr "أنت لست مستخدما لهذا التطبيق." +msgstr "لست مستخدما لهذا التطبيق." #: actions/oauthconnectionssettings.php:180 msgid "Unable to revoke access for app: " @@ -4028,7 +4028,7 @@ msgstr "" #: actions/version.php:189 msgid "Plugins" -msgstr "" +msgstr "ملحقات" #: actions/version.php:196 lib/action.php:741 msgid "Version" @@ -4116,12 +4116,12 @@ msgstr "" msgid "Problem saving notice." msgstr "مشكلة أثناء حفظ الإشعار." -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, php-format msgid "RT @%1$s %2$s" msgstr "آر تي @%1$s %2$s" @@ -4291,7 +4291,7 @@ msgstr "" #: lib/action.php:773 msgid "StatusNet software license" -msgstr "" +msgstr "رخصة برنامج StatusNet" #: lib/action.php:776 #, php-format diff --git a/locale/ja/LC_MESSAGES/statusnet.po b/locale/ja/LC_MESSAGES/statusnet.po index e3eb8b28f7..792ff4d39e 100644 --- a/locale/ja/LC_MESSAGES/statusnet.po +++ b/locale/ja/LC_MESSAGES/statusnet.po @@ -11,12 +11,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-15 19:17:22+0000\n" +"POT-Creation-Date: 2010-01-18 23:16+0000\n" +"PO-Revision-Date: 2010-01-18 23:18:49+0000\n" "Language-Team: Japanese\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61101); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61218); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: ja\n" "X-Message-Group: out-statusnet\n" @@ -54,9 +54,9 @@ msgid "No such user." msgstr "そのような利用者はいません。" #: actions/all.php:84 -#, fuzzy, php-format +#, php-format msgid "%1$s and friends, page %2$d" -msgstr "%1$s ブロックされたプロファイル、ページ %2$d" +msgstr "%1$s と友人、ページ %2$d" #: actions/all.php:86 actions/all.php:167 actions/allrss.php:115 #: actions/apitimelinefriends.php:114 actions/apitimelinehome.php:115 @@ -4358,12 +4358,12 @@ msgstr "あなたはこのサイトでつぶやきを投稿するのが禁止さ msgid "Problem saving notice." msgstr "つぶやきを保存する際に問題が発生しました。" -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "返信を追加する際にデータベースエラー : %s" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, php-format msgid "RT @%1$s %2$s" msgstr "" diff --git a/locale/pt_BR/LC_MESSAGES/statusnet.po b/locale/pt_BR/LC_MESSAGES/statusnet.po index c3162d4700..3b07494f25 100644 --- a/locale/pt_BR/LC_MESSAGES/statusnet.po +++ b/locale/pt_BR/LC_MESSAGES/statusnet.po @@ -10,12 +10,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-16 17:53:00+0000\n" +"POT-Creation-Date: 2010-01-18 23:16+0000\n" +"PO-Revision-Date: 2010-01-18 23:19:44+0000\n" "Language-Team: Brazilian Portuguese\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61138); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61218); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: pt-br\n" "X-Message-Group: out-statusnet\n" @@ -53,9 +53,9 @@ msgid "No such user." msgstr "Este usuário não existe." #: actions/all.php:84 -#, fuzzy, php-format +#, php-format msgid "%1$s and friends, page %2$d" -msgstr "Perfis bloqueados no %1$s, pág. %2$d" +msgstr "%1$s e amigos, pág. %2$d" #: actions/all.php:86 actions/all.php:167 actions/allrss.php:115 #: actions/apitimelinefriends.php:114 actions/apitimelinehome.php:115 @@ -4397,12 +4397,12 @@ msgstr "Você está proibido de publicar mensagens neste site." msgid "Problem saving notice." msgstr "Problema no salvamento da mensagem." -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "Erro no banco de dados na inserção da reposta: %s" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, php-format msgid "RT @%1$s %2$s" msgstr "RT @%1$s %2$s" diff --git a/locale/ru/LC_MESSAGES/statusnet.po b/locale/ru/LC_MESSAGES/statusnet.po index 19868d34b2..505325bae6 100644 --- a/locale/ru/LC_MESSAGES/statusnet.po +++ b/locale/ru/LC_MESSAGES/statusnet.po @@ -2,6 +2,7 @@ # # Author@translatewiki.net: Brion # Author@translatewiki.net: Lockal +# Author@translatewiki.net: Rubin # Author@translatewiki.net: Александр Сигачёв # -- # This file is distributed under the same license as the StatusNet package. @@ -10,12 +11,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-15 19:17:57+0000\n" +"POT-Creation-Date: 2010-01-18 23:16+0000\n" +"PO-Revision-Date: 2010-01-18 23:19:49+0000\n" "Language-Team: Russian\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61101); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61218); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: ru\n" "X-Message-Group: out-statusnet\n" @@ -453,7 +454,6 @@ msgid "There was a problem with your session token. Try again, please." msgstr "Проблема с Вашей сессией. Попробуйте ещё раз, пожалуйста." #: actions/apioauthauthorize.php:146 -#, fuzzy msgid "Invalid nickname / password!" msgstr "Неверное имя или пароль." @@ -4406,12 +4406,12 @@ msgstr "Вам запрещено поститься на этом сайте ( msgid "Problem saving notice." msgstr "Проблемы с сохранением записи." -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "Ошибка баз данных при вставке ответа для %s" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, php-format msgid "RT @%1$s %2$s" msgstr "RT @%1$s %2$s" diff --git a/locale/statusnet.po b/locale/statusnet.po index a7f7f9f74b..097ed22237 100644 --- a/locale/statusnet.po +++ b/locale/statusnet.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-16 17:51+0000\n" +"POT-Creation-Date: 2010-01-18 23:16+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -4102,12 +4102,12 @@ msgstr "" msgid "Problem saving notice." msgstr "" -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, php-format msgid "RT @%1$s %2$s" msgstr "" diff --git a/locale/sv/LC_MESSAGES/statusnet.po b/locale/sv/LC_MESSAGES/statusnet.po index 8d093bc493..f8e290877c 100644 --- a/locale/sv/LC_MESSAGES/statusnet.po +++ b/locale/sv/LC_MESSAGES/statusnet.po @@ -9,12 +9,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-15 19:18:00+0000\n" +"POT-Creation-Date: 2010-01-18 23:16+0000\n" +"PO-Revision-Date: 2010-01-18 23:19:55+0000\n" "Language-Team: Swedish\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61101); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61218); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: sv\n" "X-Message-Group: out-statusnet\n" @@ -52,9 +52,9 @@ msgid "No such user." msgstr "Ingen sådan användare." #: actions/all.php:84 -#, fuzzy, php-format +#, php-format msgid "%1$s and friends, page %2$d" -msgstr "%s blockerade profiler, sida %d" +msgstr "%1$s blockerade profiler, sida %2$d" #: actions/all.php:86 actions/all.php:167 actions/allrss.php:115 #: actions/apitimelinefriends.php:114 actions/apitimelinehome.php:115 @@ -268,18 +268,16 @@ msgid "No status found with that ID." msgstr "Ingen status hittad med det ID:t." #: actions/apifavoritecreate.php:119 -#, fuzzy msgid "This status is already a favorite." -msgstr "Denna status är redan en favorit!" +msgstr "Denna status är redan en favorit." #: actions/apifavoritecreate.php:130 actions/favor.php:84 lib/command.php:176 msgid "Could not create favorite." msgstr "Kunde inte skapa favorit." #: actions/apifavoritedestroy.php:122 -#, fuzzy msgid "That status is not a favorite." -msgstr "Denna status är inte en favorit!" +msgstr "Denna status är inte en favorit." #: actions/apifavoritedestroy.php:134 actions/disfavor.php:87 msgid "Could not delete favorite." @@ -299,9 +297,8 @@ msgid "Could not unfollow user: User not found." msgstr "Kunde inte sluta följa användaren: användaren hittades inte." #: actions/apifriendshipsdestroy.php:120 -#, fuzzy msgid "You cannot unfollow yourself." -msgstr "Du kan inte sluta följa dig själv!" +msgstr "Du kan inte sluta följa dig själv." #: actions/apifriendshipsexists.php:94 msgid "Two user ids or screen_names must be supplied." @@ -397,18 +394,18 @@ msgid "You have been blocked from that group by the admin." msgstr "Du har blivit blockerad från denna grupp av administratören." #: actions/apigroupjoin.php:138 actions/joingroup.php:124 -#, fuzzy, php-format +#, php-format msgid "Could not join user %1$s to group %2$s." -msgstr "Kunde inte ansluta användare % till grupp %s." +msgstr "Kunde inte ansluta användare %1$s till grupp %2$s." #: actions/apigroupleave.php:114 msgid "You are not a member of this group." msgstr "Du är inte en medlem i denna grupp." #: actions/apigroupleave.php:124 actions/leavegroup.php:119 -#, fuzzy, php-format +#, php-format msgid "Could not remove user %1$s from group %2$s." -msgstr "Kunde inte ta bort användare %s från grupp %s." +msgstr "Kunde inte ta bort användare %1$s från grupp %2$s." #: actions/apigrouplist.php:95 #, php-format @@ -448,9 +445,8 @@ msgid "There was a problem with your session token. Try again, please." msgstr "Det var ett problem med din sessions-token. Var vänlig försök igen." #: actions/apioauthauthorize.php:146 -#, fuzzy msgid "Invalid nickname / password!" -msgstr "Ogiltigt användarnamn eller lösenord." +msgstr "Ogiltigt smeknamn / lösenord!" #: actions/apioauthauthorize.php:170 #, fuzzy @@ -489,7 +485,7 @@ msgstr "" #: actions/apioauthauthorize.php:290 msgid "Allow or deny access" -msgstr "" +msgstr "Tillåt eller neka åtkomst" #: actions/apioauthauthorize.php:320 lib/action.php:435 msgid "Account" @@ -508,18 +504,16 @@ msgid "Password" msgstr "Lösenord" #: actions/apioauthauthorize.php:338 -#, fuzzy msgid "Deny" -msgstr "Utseende" +msgstr "Neka" #: actions/apioauthauthorize.php:344 -#, fuzzy msgid "Allow" -msgstr "Alla" +msgstr "Tillåt" #: actions/apioauthauthorize.php:361 msgid "Allow or deny access to your account information." -msgstr "" +msgstr "Tillåt eller neka åtkomst till din kontoinformation." #: actions/apistatusesdestroy.php:107 msgid "This method requires a POST or DELETE." @@ -570,14 +564,14 @@ msgid "Unsupported format." msgstr "Format som inte stödjs." #: actions/apitimelinefavorites.php:108 -#, fuzzy, php-format +#, php-format msgid "%1$s / Favorites from %2$s" -msgstr "%s / Favoriter från %s" +msgstr "%1$s / Favoriter från %2$s" #: actions/apitimelinefavorites.php:120 -#, fuzzy, php-format +#, php-format msgid "%1$s updates favorited by %2$s / %2$s." -msgstr "%s uppdateringar markerade som favorit av %s / %s." +msgstr "%1$s uppdateringar markerade som favorit av %2$s / %2$s." #: actions/apitimelinegroup.php:109 actions/apitimelineuser.php:118 #: actions/grouprss.php:131 actions/userrss.php:90 @@ -782,9 +776,9 @@ msgid "%s blocked profiles" msgstr "%s blockerade profiler" #: actions/blockedfromgroup.php:93 -#, fuzzy, php-format +#, php-format msgid "%1$s blocked profiles, page %2$d" -msgstr "%s blockerade profiler, sida %d" +msgstr "%1$s blockerade profiler, sida %2$d" #: actions/blockedfromgroup.php:108 msgid "A list of the users blocked from joining this group." @@ -842,7 +836,6 @@ msgid "Couldn't delete email confirmation." msgstr "Kunde inte ta bort e-postbekräftelse." #: actions/confirmaddress.php:144 -#, fuzzy msgid "Confirm address" msgstr "Bekräfta adress" @@ -1055,7 +1048,7 @@ msgstr "Inget sådant dokument." #: actions/editapplication.php:54 lib/applicationeditform.php:136 msgid "Edit application" -msgstr "" +msgstr "Redigera applikation" #: actions/editapplication.php:66 #, fuzzy @@ -1069,9 +1062,8 @@ msgstr "Du är inte en medlem i denna grupp." #: actions/editapplication.php:81 actions/oauthconnectionssettings.php:163 #: actions/showapplication.php:87 -#, fuzzy msgid "No such application." -msgstr "Ingen sådan notis." +msgstr "Ingen sådan applikation." #: actions/editapplication.php:127 actions/newapplication.php:110 #: actions/showapplication.php:118 lib/action.php:1167 @@ -1079,9 +1071,8 @@ msgid "There was a problem with your session token." msgstr "Det var ett problem med din sessions-token." #: actions/editapplication.php:161 -#, fuzzy msgid "Use this form to edit your application." -msgstr "Använd detta formulär för att redigera gruppen." +msgstr "Använd detta formulär för att redigera din applikation." #: actions/editapplication.php:177 actions/newapplication.php:159 #, fuzzy @@ -1089,9 +1080,8 @@ msgid "Name is required." msgstr "Samma som lösenordet ovan. Måste fyllas i." #: actions/editapplication.php:180 actions/newapplication.php:162 -#, fuzzy msgid "Name is too long (max 255 chars)." -msgstr "Fullständigt namn är för långt (max 255 tecken)." +msgstr "Namnet är för långt (max 255 tecken)." #: actions/editapplication.php:183 actions/newapplication.php:165 #, fuzzy @@ -1145,9 +1135,8 @@ msgstr "Du måste vara inloggad för att skapa en grupp." #: actions/editgroup.php:103 actions/editgroup.php:168 #: actions/groupdesignsettings.php:104 actions/grouplogo.php:106 -#, fuzzy msgid "You must be an admin to edit the group." -msgstr "Du måste vara inloggad för att redigera gruppen" +msgstr "Du måste vara en administratör för att redigera gruppen." #: actions/editgroup.php:154 msgid "Use this form to edit the group." @@ -1171,7 +1160,6 @@ msgid "Options saved." msgstr "Alternativ sparade." #: actions/emailsettings.php:60 -#, fuzzy msgid "Email settings" msgstr "E-postinställningar" @@ -1210,9 +1198,8 @@ msgid "Cancel" msgstr "Avbryt" #: actions/emailsettings.php:121 -#, fuzzy msgid "Email address" -msgstr "E-postadresser" +msgstr "E-postadress" #: actions/emailsettings.php:123 msgid "Email address, like \"UserName@example.org\"" @@ -1514,14 +1501,14 @@ msgid "Block user from group" msgstr "Blockera användare från grupp" #: actions/groupblock.php:162 -#, fuzzy, php-format +#, php-format msgid "" "Are you sure you want to block user \"%1$s\" from the group \"%2$s\"? They " "will be removed from the group, unable to post, and unable to subscribe to " "the group in the future." msgstr "" -"Är du säker på att du vill blockera användare \"%s\" från gruppen \"%s\"? De " -"kommer bli borttagna från gruppen, inte kunna posta och inte kunna " +"Är du säker på att du vill blockera användare \"%1$s\" från gruppen \"%2$s" +"\"? De kommer bli borttagna från gruppen, inte kunna posta och inte kunna " "prenumerera på gruppen i framtiden." #: actions/groupblock.php:178 @@ -1577,9 +1564,8 @@ msgstr "" "s." #: actions/grouplogo.php:178 -#, fuzzy msgid "User without matching profile." -msgstr "Användare utan matchande profil" +msgstr "Användare utan matchande profil." #: actions/grouplogo.php:362 msgid "Pick a square area of the image to be the logo." @@ -1599,9 +1585,9 @@ msgid "%s group members" msgstr "%s gruppmedlemmar" #: actions/groupmembers.php:96 -#, fuzzy, php-format +#, php-format msgid "%1$s group members, page %2$d" -msgstr "%s gruppmedlemmar, sida %d" +msgstr "%1$s gruppmedlemmar, sida %2$d" #: actions/groupmembers.php:111 msgid "A list of the users in this group." @@ -1651,9 +1637,9 @@ msgid "" "for one](%%%%action.groupsearch%%%%) or [start your own!](%%%%action.newgroup" "%%%%)" msgstr "" -"%%%%site.name%%%% grupper låter dig hitta och prata med personer med " +"%%%%site.name%%%% grupper låter dig hitta och samtala med personer med " "liknande intressen. Efter att ha gått med i en grupp kan du skicka " -"meddelanden till alla andra medlemmar mha. syntaxen \"!gruppnamn\". Ser du " +"meddelanden till alla andra medlemmar mha syntaxen \"!gruppnamn\". Ser du " "inte någon grupp du gillar? Prova att [söka efter en](%%%%action.groupsearch%" "%%%) eller [starta din egen!](%%%%action.newgroup%%%%)" @@ -1711,9 +1697,8 @@ msgid "Error removing the block." msgstr "Fel vid hävning av blockering." #: actions/imsettings.php:59 -#, fuzzy msgid "IM settings" -msgstr "IM-inställningar" +msgstr "Inställningar för snabbmeddelanden" #: actions/imsettings.php:70 #, php-format @@ -1721,7 +1706,7 @@ msgid "" "You can send and receive notices through Jabber/GTalk [instant messages](%%" "doc.im%%). Configure your address and settings below." msgstr "" -"Du kan skicka och ta emot notiser genom Jabber/GTalk [snabbmeddelanden](%%" +"Du kan skicka och ta emot notiser genom Jabber/GTalk-[snabbmeddelanden](%%" "doc.im%%). Konfigurera din adress och dina inställningar nedan." #: actions/imsettings.php:89 @@ -1742,9 +1727,8 @@ msgstr "" "vidare instruktioner. (La du till %s i din kompislista?)" #: actions/imsettings.php:124 -#, fuzzy msgid "IM address" -msgstr "IM-adress" +msgstr "Adress för snabbmeddelanden" #: actions/imsettings.php:126 #, php-format @@ -1934,9 +1918,9 @@ msgid "You must be logged in to join a group." msgstr "Du måste vara inloggad för att kunna gå med i en grupp." #: actions/joingroup.php:131 -#, fuzzy, php-format +#, php-format msgid "%1$s joined group %2$s" -msgstr "%s gick med i grupp %s" +msgstr "%1$s gick med i grupp %2$s" #: actions/leavegroup.php:60 msgid "You must be logged in to leave a group." @@ -1947,9 +1931,9 @@ msgid "You are not a member of that group." msgstr "Du är inte en medlem i den gruppen." #: actions/leavegroup.php:127 -#, fuzzy, php-format +#, php-format msgid "%1$s left group %2$s" -msgstr "%s lämnade grupp %s" +msgstr "%1$s lämnade grupp %2$s" #: actions/login.php:80 actions/otp.php:62 actions/register.php:137 msgid "Already logged in." @@ -2006,19 +1990,19 @@ msgid "Only an admin can make another user an admin." msgstr "Bara en administratör kan göra en annan användare till administratör." #: actions/makeadmin.php:95 -#, fuzzy, php-format +#, php-format msgid "%1$s is already an admin for group \"%2$s\"." -msgstr "%s är redan en administratör för grupp \"%s\"." +msgstr "%1$s är redan en administratör för grupp \"%2$s\"." #: actions/makeadmin.php:132 -#, fuzzy, php-format +#, php-format msgid "Can't get membership record for %1$s in group %2$s." -msgstr "Kan inte hämta uppgift om medlemskap för %s i grupp %s" +msgstr "Kan inte hämta uppgift om medlemskap för %1$s i grupp %2$s." #: actions/makeadmin.php:145 -#, fuzzy, php-format +#, php-format msgid "Can't make %1$s an admin for group %2$s." -msgstr "Kan inte göra %s till en administratör för grupp %s" +msgstr "Kan inte göra %1$s till en administratör för grupp %2$s." #: actions/microsummary.php:69 msgid "No current status" @@ -2026,26 +2010,23 @@ msgstr "Ingen aktuell status" #: actions/newapplication.php:52 msgid "New application" -msgstr "" +msgstr "Ny applikation" #: actions/newapplication.php:64 -#, fuzzy msgid "You must be logged in to register an application." -msgstr "Du måste vara inloggad för att skapa en grupp." +msgstr "Du måste vara inloggad för att registrera en applikation." #: actions/newapplication.php:143 -#, fuzzy msgid "Use this form to register a new application." -msgstr "Använd detta formulär för att skapa en ny grupp." +msgstr "Använd detta formulär för att registrera en ny applikation." #: actions/newapplication.php:173 msgid "Source URL is required." msgstr "" #: actions/newapplication.php:255 actions/newapplication.php:264 -#, fuzzy msgid "Could not create application." -msgstr "Kunde inte skapa alias." +msgstr "Kunde inte skapa applikation." #: actions/newgroup.php:53 msgid "New group" @@ -2084,9 +2065,9 @@ msgid "Message sent" msgstr "Meddelande skickat" #: actions/newmessage.php:185 -#, fuzzy, php-format +#, php-format msgid "Direct message to %s sent." -msgstr "Direktmeddelande till %s skickat" +msgstr "Direktmeddelande till %s skickat." #: actions/newmessage.php:210 actions/newnotice.php:245 lib/channel.php:170 msgid "Ajax Error" @@ -2114,9 +2095,9 @@ msgid "Text search" msgstr "Textsökning" #: actions/noticesearch.php:91 -#, fuzzy, php-format +#, php-format msgid "Search results for \"%1$s\" on %2$s" -msgstr "Sökresultat för \"%s\" på %s" +msgstr "Sökresultat för \"%1$s\" på %2$s" #: actions/noticesearch.php:121 #, php-format @@ -2162,9 +2143,8 @@ msgid "Nudge sent!" msgstr "Knuff sänd!" #: actions/oauthappssettings.php:59 -#, fuzzy msgid "You must be logged in to list your applications." -msgstr "Du måste vara inloggad för att redigera en grupp." +msgstr "Du måste vara inloggad för att lista dina applikationer." #: actions/oauthappssettings.php:74 #, fuzzy @@ -2173,20 +2153,20 @@ msgstr "Övriga alternativ" #: actions/oauthappssettings.php:85 msgid "Applications you have registered" -msgstr "" +msgstr "Applikationer du har registrerat" #: actions/oauthappssettings.php:135 #, php-format msgid "You have not registered any applications yet." -msgstr "" +msgstr "Du har inte registrerat några applikationer än." #: actions/oauthconnectionssettings.php:71 msgid "Connected applications" -msgstr "" +msgstr "Anslutna applikationer" #: actions/oauthconnectionssettings.php:87 msgid "You have allowed the following applications to access you account." -msgstr "" +msgstr "Du har tillåtit följande applikationer att komma åt ditt konto." #: actions/oauthconnectionssettings.php:170 #, fuzzy @@ -2195,12 +2175,12 @@ msgstr "Du är inte en medlem i den gruppen." #: actions/oauthconnectionssettings.php:180 msgid "Unable to revoke access for app: " -msgstr "" +msgstr "Kunde inte återkalla åtkomst för applikation: " #: actions/oauthconnectionssettings.php:192 #, php-format msgid "You have not authorized any applications to use your account." -msgstr "" +msgstr "Du har inte tillåtit några applikationer att använda ditt konto." #: actions/oauthconnectionssettings.php:205 msgid "Developers can edit the registration settings for their applications " @@ -2237,7 +2217,6 @@ msgid "Notice Search" msgstr "Notissökning" #: actions/othersettings.php:60 -#, fuzzy msgid "Other settings" msgstr "Övriga inställningar" @@ -2490,7 +2469,6 @@ msgid "When to use SSL" msgstr "När SSL skall användas" #: actions/pathsadminpanel.php:308 -#, fuzzy msgid "SSL server" msgstr "SSL-server" @@ -2521,9 +2499,9 @@ msgid "Not a valid people tag: %s" msgstr "Inte en giltig persontagg: %s" #: actions/peopletag.php:144 -#, fuzzy, php-format +#, php-format msgid "Users self-tagged with %1$s - page %2$d" -msgstr "Användare som taggat sig själv med %s - sida %d" +msgstr "Användare som taggat sig själv med %1$s - sida %2$d" #: actions/postnotice.php:84 msgid "Invalid notice content" @@ -2728,8 +2706,8 @@ msgid "" "tool. [Join now](%%action.register%%) to share notices about yourself with " "friends, family, and colleagues! ([Read more](%%doc.help%%))" msgstr "" -"Detta är %%site.name%%, en [mikroblogg](http://en.wikipedia.org/wiki/Micro-" -"blogging)-tjänst baserad på den fria programvaran [StatusNet](http://status." +"Detta är %%site.name%%, en [mikroblogg](http://sv.wikipedia.org/wiki/" +"Mikroblogg)tjänst baserad på den fria programvaran [StatusNet](http://status." "net/). [Gå med nu](%%action.register%%) för att dela notiser om dig själv " "med vänner, familj och kollegor! ([Läs mer](%%doc.help%%))" @@ -2740,8 +2718,8 @@ msgid "" "blogging) service based on the Free Software [StatusNet](http://status.net/) " "tool." msgstr "" -"Detta är %%site.name%%, en [mikroblogg](http://en.wikipedia.org/wiki/Micro-" -"blogging)-tjänst baserad på den fria programvaran [StatusNet](http://status." +"Detta är %%site.name%%, en [mikroblogg](http://sv.wikipedia.org/wiki/" +"Mikroblogg)tjänst baserad på den fria programvaran [StatusNet](http://status." "net/)." #: actions/publictagcloud.php:57 @@ -3163,24 +3141,21 @@ msgid "You must be logged in to view an application." msgstr "Du måste vara inloggad för att lämna en grupp." #: actions/showapplication.php:158 -#, fuzzy msgid "Application profile" -msgstr "Notisen har ingen profil" +msgstr "Applikationsprofil" #: actions/showapplication.php:160 lib/applicationeditform.php:182 msgid "Icon" -msgstr "" +msgstr "Ikon" #: actions/showapplication.php:170 actions/version.php:195 #: lib/applicationeditform.php:197 -#, fuzzy msgid "Name" -msgstr "Smeknamn" +msgstr "Namn" #: actions/showapplication.php:179 lib/applicationeditform.php:224 -#, fuzzy msgid "Organization" -msgstr "Numrering av sidor" +msgstr "Organisation" #: actions/showapplication.php:188 actions/version.php:198 #: lib/applicationeditform.php:211 lib/groupeditform.php:172 @@ -3207,7 +3182,7 @@ msgstr "" #: actions/showapplication.php:241 msgid "Application info" -msgstr "" +msgstr "Information om applikation" #: actions/showapplication.php:243 msgid "Consumer key" @@ -3354,8 +3329,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** är en användargrupp på %%%%site.name%%%%, en [mikroblogg](http://en." -"wikipedia.org/wiki/Micro-blogging)-tjänst baserad den fria programvaran " +"**%s** är en användargrupp på %%%%site.name%%%%, en [mikroblogg](http://sv." +"wikipedia.org/wiki/Mikroblogg)tjänst baserad den fria programvaran " "[StatusNet](http://status.net/). Dess medlemmar delar korta meddelande om " "sina liv och intressen. [Gå med nu](%%%%action.register%%%%) för att bli en " "del av denna grupp och många fler! ([Läs mer](%%%%doc.help%%%%))" @@ -3369,7 +3344,7 @@ msgid "" "their life and interests. " msgstr "" "**%s** är en användargrupp på %%%%site.name%%%%, en [mikroblogg](http://en." -"wikipedia.org/wiki/Micro-blogging)-tjänst baserad den fria programvaran " +"wikipedia.org/wiki/Micro-blogging)tjänst baserad den fria programvaran " "[StatusNet](http://status.net/). Dess medlemmar delar korta meddelande om " "sina liv och intressen. " @@ -3405,9 +3380,9 @@ msgid " tagged %s" msgstr "taggade %s" #: actions/showstream.php:122 -#, fuzzy, php-format +#, php-format msgid "Notice feed for %1$s tagged %2$s (RSS 1.0)" -msgstr "Flöde av notiser för %s taggade %s (RSS 1.0)" +msgstr "Flöde av notiser för %1$s taggade %2$s (RSS 1.0)" #: actions/showstream.php:129 #, php-format @@ -3430,9 +3405,9 @@ msgid "FOAF for %s" msgstr "FOAF för %s" #: actions/showstream.php:191 -#, fuzzy, php-format +#, php-format msgid "This is the timeline for %1$s but %2$s hasn't posted anything yet." -msgstr "Detta är tidslinjen för %s men %s har inte postat något än." +msgstr "Detta är tidslinjen för %1$s men %2$s har inte postat något än." #: actions/showstream.php:196 msgid "" @@ -3460,7 +3435,7 @@ msgid "" "follow **%s**'s notices and many more! ([Read more](%%%%doc.help%%%%))" msgstr "" "**%s** har ett konto på %%%%site.name%%%%, en [mikroblogg](http://en." -"wikipedia.org/wiki/Micro-blogging)-tjänst baserad på den fria programvaran " +"wikipedia.org/wiki/Micro-blogging)tjänst baserad på den fria programvaran " "[StatusNet](http://status.net/). [Gå med nu](%%%%action.register%%%%) för " "att följa **%s**s notiser och många fler! ([Läs mer](%%%%doc.help%%%%))" @@ -3472,7 +3447,7 @@ msgid "" "[StatusNet](http://status.net/) tool. " msgstr "" "**%s** har ett konto på %%%%site.name%%%%, en [mikroblogg](http://en." -"wikipedia.org/wiki/Micro-blogging)-tjänst baserad på den fria programvaran " +"wikipedia.org/wiki/Micro-blogging)tjänst baserad på den fria programvaran " "[StatusNet](http://status.net/). " #: actions/showstream.php:313 @@ -3497,14 +3472,13 @@ msgid "Site name must have non-zero length." msgstr "Webbplatsnamnet måste vara minst ett tecken långt." #: actions/siteadminpanel.php:154 -#, fuzzy msgid "You must have a valid contact email address." -msgstr "Du måste ha en giltig kontakte-postadress" +msgstr "Du måste ha en giltig e-postadress." #: actions/siteadminpanel.php:172 -#, fuzzy, php-format +#, php-format msgid "Unknown language \"%s\"." -msgstr "Okänt språk \"%s\"" +msgstr "Okänt språk \"%s\"." #: actions/siteadminpanel.php:179 msgid "Invalid snapshot report URL." @@ -3654,7 +3628,7 @@ msgstr "Ögonblicksbild kommer skickas var N:te webbträff" #: actions/siteadminpanel.php:359 msgid "Report URL" -msgstr "Rapport-URL" +msgstr "URL för rapport" #: actions/siteadminpanel.php:360 msgid "Snapshots will be sent to this URL" @@ -3686,14 +3660,13 @@ msgid "Save site settings" msgstr "Spara webbplatsinställningar" #: actions/smssettings.php:58 -#, fuzzy msgid "SMS settings" -msgstr "SMS-inställningar" +msgstr "Inställningar för SMS" #: actions/smssettings.php:69 #, php-format msgid "You can receive SMS messages through email from %%site.name%%." -msgstr "Du kan ta emot SMS-meddelande genom e-post från %%site.name%%." +msgstr "Du kan ta emot SMS-meddelanden genom e-post från %%site.name%%." #: actions/smssettings.php:91 msgid "SMS is not available." @@ -3716,7 +3689,6 @@ msgid "Enter the code you received on your phone." msgstr "Fyll i koden du mottog i din telefon." #: actions/smssettings.php:138 -#, fuzzy msgid "SMS phone number" msgstr "Telefonnummer för SMS" @@ -3808,9 +3780,9 @@ msgid "%s subscribers" msgstr "%s prenumeranter" #: actions/subscribers.php:52 -#, fuzzy, php-format +#, php-format msgid "%1$s subscribers, page %2$d" -msgstr "%s prenumeranter, sida %d" +msgstr "%1$s prenumeranter, sida %2$d" #: actions/subscribers.php:63 msgid "These are the people who listen to your notices." @@ -3849,9 +3821,9 @@ msgid "%s subscriptions" msgstr "%s prenumerationer" #: actions/subscriptions.php:54 -#, fuzzy, php-format +#, php-format msgid "%1$s subscriptions, page %2$d" -msgstr "%s prenumerationer, sida %d" +msgstr "%1$s prenumerationer, sida %2$d" #: actions/subscriptions.php:65 msgid "These are the people whose notices you listen to." @@ -3974,12 +3946,12 @@ msgid "Unsubscribed" msgstr "Prenumeration avslutad" #: actions/updateprofile.php:62 actions/userauthorization.php:330 -#, fuzzy, php-format +#, php-format msgid "" "Listenee stream license ‘%1$s’ is not compatible with site license ‘%2$s’." msgstr "" -"Licensen för lyssnarströmmen '%s' är inte förenlig med webbplatslicensen '%" -"s'." +"Licensen för lyssnarströmmen '%1$s' är inte förenlig med webbplatslicensen '%" +"2$s'." #: actions/useradminpanel.php:58 lib/adminpanelaction.php:321 #: lib/personalgroupnav.php:115 @@ -4138,9 +4110,9 @@ msgstr "" "prenumerationen." #: actions/userauthorization.php:296 -#, fuzzy, php-format +#, php-format msgid "Listener URI ‘%s’ not found here." -msgstr "Lyssnar-URI '%s' hittades inte här" +msgstr "URI för lyssnare '%s' hittades inte här." #: actions/userauthorization.php:301 #, php-format @@ -4203,9 +4175,9 @@ msgstr "" "Prova att [söka efter grupper](%%action.groupsearch%%) och gå med i dem." #: actions/version.php:73 -#, fuzzy, php-format +#, php-format msgid "StatusNet %s" -msgstr "Statistik" +msgstr "StatusNet %s" #: actions/version.php:153 #, php-format @@ -4215,9 +4187,8 @@ msgid "" msgstr "" #: actions/version.php:157 -#, fuzzy msgid "StatusNet" -msgstr "Status borttagen." +msgstr "StatusNet" #: actions/version.php:161 msgid "Contributors" @@ -4248,15 +4219,13 @@ msgstr "" #: actions/version.php:189 msgid "Plugins" -msgstr "" +msgstr "Insticksmoduler" #: actions/version.php:196 lib/action.php:741 -#, fuzzy msgid "Version" -msgstr "Sessioner" +msgstr "Version" #: actions/version.php:197 -#, fuzzy msgid "Author(s)" msgstr "Författare" @@ -4347,12 +4316,12 @@ msgstr "Du är utestängd från att posta notiser på denna webbplats." msgid "Problem saving notice." msgstr "Problem med att spara notis." -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "Databasfel vid infogning av svar: %s" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, php-format msgid "RT @%1$s %2$s" msgstr "RT @%1$s %2$s" @@ -4399,9 +4368,9 @@ msgid "Other options" msgstr "Övriga alternativ" #: lib/action.php:144 -#, fuzzy, php-format +#, php-format msgid "%1$s - %2$s" -msgstr "%1$s (%2$s)" +msgstr "%1$s - %2$s" #: lib/action.php:159 msgid "Untitled page" @@ -4531,7 +4500,7 @@ msgid "" "broughtby%%](%%site.broughtbyurl%%). " msgstr "" "**%%site.name%%** är en mikrobloggtjänst tillhandahållen av [%%site.broughtby" -"%%](%%site.broughtbyurl%%)" +"%%](%%site.broughtbyurl%%). " #: lib/action.php:778 #, php-format @@ -4545,7 +4514,7 @@ msgid "" "s, available under the [GNU Affero General Public License](http://www.fsf." "org/licensing/licenses/agpl-3.0.html)." msgstr "" -"Den drivs med mikroblogg-programvaran [StatusNet](http://status.net/), " +"Den drivs med mikrobloggprogramvaran [StatusNet](http://status.net/), " "version %s, tillgänglig under [GNU Affero General Public License](http://www." "fsf.org/licensing/licenses/agpl-3.0.html)." @@ -4608,7 +4577,7 @@ msgstr "Konfiguration av sökvägar" #: lib/applicationeditform.php:186 msgid "Icon for this application" -msgstr "" +msgstr "Ikon för denna applikation" #: lib/applicationeditform.php:206 #, fuzzy, php-format @@ -4616,14 +4585,12 @@ msgid "Describe your application in %d characters" msgstr "Beskriv gruppen eller ämnet med högst %d tecken" #: lib/applicationeditform.php:209 -#, fuzzy msgid "Describe your application" -msgstr "Beskriv gruppen eller ämnet" +msgstr "Beskriv din applikation" #: lib/applicationeditform.php:218 -#, fuzzy msgid "Source URL" -msgstr "Källa" +msgstr "URL för källa" #: lib/applicationeditform.php:220 #, fuzzy @@ -4632,7 +4599,7 @@ msgstr "URL till gruppen eller ämnets hemsida eller blogg" #: lib/applicationeditform.php:226 msgid "Organization responsible for this application" -msgstr "" +msgstr "Organisation som ansvarar för denna applikation" #: lib/applicationeditform.php:232 #, fuzzy @@ -4645,32 +4612,32 @@ msgstr "" #: lib/applicationeditform.php:260 msgid "Browser" -msgstr "" +msgstr "Webbläsare" #: lib/applicationeditform.php:276 msgid "Desktop" -msgstr "" +msgstr "Skrivbord" #: lib/applicationeditform.php:277 msgid "Type of application, browser or desktop" -msgstr "" +msgstr "Typ av applikation, webbläsare eller skrivbord" #: lib/applicationeditform.php:299 msgid "Read-only" -msgstr "" +msgstr "Skrivskyddad" #: lib/applicationeditform.php:317 msgid "Read-write" -msgstr "" +msgstr "Läs och skriv" #: lib/applicationeditform.php:318 msgid "Default access for this application: read-only, or read-write" msgstr "" +"Standardåtkomst för denna applikation: skrivskyddad, eller läs och skriv" #: lib/applicationlist.php:154 -#, fuzzy msgid "Revoke" -msgstr "Ta bort" +msgstr "Återkalla" #: lib/attachmentlist.php:87 msgid "Attachments" @@ -4991,9 +4958,8 @@ msgid "Updates by SMS" msgstr "Uppdateringar via SMS" #: lib/connectsettingsaction.php:120 -#, fuzzy msgid "Connections" -msgstr "Anslut" +msgstr "Anslutningar" #: lib/connectsettingsaction.php:121 msgid "Authorized connected applications" @@ -5251,11 +5217,9 @@ msgid "" msgstr "" #: lib/mail.php:258 -#, fuzzy, php-format +#, php-format msgid "Bio: %s" -msgstr "" -"Biografi: %s\n" -"\n" +msgstr "Biografi: %s" #: lib/mail.php:286 #, php-format @@ -5456,18 +5420,16 @@ msgid "File upload stopped by extension." msgstr "Filuppladdningen stoppad pga filändelse" #: lib/mediafile.php:179 lib/mediafile.php:216 -#, fuzzy msgid "File exceeds user's quota." -msgstr "Fil överstiger användaren kvot!" +msgstr "Fil överstiger användaren kvot." #: lib/mediafile.php:196 lib/mediafile.php:233 msgid "File could not be moved to destination directory." msgstr "Fil kunde inte flyttas till destinationskatalog." #: lib/mediafile.php:201 lib/mediafile.php:237 -#, fuzzy msgid "Could not determine file's MIME type." -msgstr "Kunde inte fastställa filens MIME-typ!" +msgstr "Kunde inte fastställa filens MIME-typ." #: lib/mediafile.php:270 #, php-format @@ -5475,13 +5437,13 @@ msgid " Try using another %s format." msgstr "Försök använda ett annat %s-format." #: lib/mediafile.php:275 -#, fuzzy, php-format +#, php-format msgid "%s is not a supported file type on this server." msgstr "%s är en filtyp som saknar stöd på denna server." #: lib/messageform.php:120 msgid "Send a direct notice" -msgstr "Skicka ett direktinlägg" +msgstr "Skicka en direktnotis" #: lib/messageform.php:146 msgid "To" @@ -5493,7 +5455,7 @@ msgstr "Tillgängliga tecken" #: lib/noticeform.php:160 msgid "Send a notice" -msgstr "Skicka ett inlägg" +msgstr "Skicka en notis" #: lib/noticeform.php:173 #, php-format @@ -5509,14 +5471,12 @@ msgid "Attach a file" msgstr "Bifoga en fil" #: lib/noticeform.php:212 -#, fuzzy msgid "Share my location" -msgstr "Dela din plats" +msgstr "Dela min plats" #: lib/noticeform.php:215 -#, fuzzy msgid "Do not share my location" -msgstr "Dela din plats" +msgstr "Dela inte min plats" #: lib/noticeform.php:216 msgid "" @@ -5559,7 +5519,7 @@ msgstr "Upprepad av" #: lib/noticelist.php:585 msgid "Reply to this notice" -msgstr "Svara på detta inlägg" +msgstr "Svara på denna notis" #: lib/noticelist.php:586 msgid "Reply" @@ -5607,7 +5567,7 @@ msgstr "Kunde inte infoga ny prenumeration." #: lib/personalgroupnav.php:99 msgid "Personal" -msgstr "Personlig" +msgstr "Personligt" #: lib/personalgroupnav.php:104 msgid "Replies" @@ -5639,9 +5599,8 @@ msgid "Tags in %s's notices" msgstr "Taggar i %ss notiser" #: lib/plugin.php:114 -#, fuzzy msgid "Unknown" -msgstr "Okänd funktion" +msgstr "Okänd" #: lib/profileaction.php:109 lib/profileaction.php:192 lib/subgroupnav.php:82 msgid "Subscriptions" @@ -5681,7 +5640,7 @@ msgstr "Inte implementerad metod." #: lib/publicgroupnav.php:78 msgid "Public" -msgstr "Publik" +msgstr "Publikt" #: lib/publicgroupnav.php:82 msgid "User groups" @@ -5705,7 +5664,7 @@ msgstr "Upprepa denna notis?" #: lib/repeatform.php:132 msgid "Repeat this notice" -msgstr "Upprepa detta inlägg" +msgstr "Upprepa denna notis" #: lib/sandboxform.php:67 msgid "Sandbox" @@ -5927,6 +5886,6 @@ msgid "%s is not a valid color! Use 3 or 6 hex chars." msgstr "%s är inte en giltig färg! Använd 3 eller 6 hexadecimala tecken." #: scripts/xmppdaemon.php:301 -#, fuzzy, php-format +#, php-format msgid "Message too long - maximum is %1$d characters, you sent %2$d." -msgstr "Meddelande för långt - maximum är %d tecken, du skickade %d" +msgstr "Meddelande för långt - maximum är %1$d tecken, du skickade %2$d." From 0ddfcc5521e023db7be52fe783800a39701ff94f Mon Sep 17 00:00:00 2001 From: Eric Helgeson Date: Mon, 18 Jan 2010 18:31:13 -0500 Subject: [PATCH 08/53] Added Plugin Version info to recaptcha plugin --- plugins/Recaptcha/RecaptchaPlugin.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/plugins/Recaptcha/RecaptchaPlugin.php b/plugins/Recaptcha/RecaptchaPlugin.php index 3665214f85..c585da43c4 100644 --- a/plugins/Recaptcha/RecaptchaPlugin.php +++ b/plugins/Recaptcha/RecaptchaPlugin.php @@ -31,8 +31,6 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } -define('RECAPTCHA', '0.2'); - require_once(INSTALLDIR.'/plugins/Recaptcha/recaptchalib.php'); class RecaptchaPlugin extends Plugin @@ -88,4 +86,16 @@ class RecaptchaPlugin extends Plugin return false; } } + + function onPluginVersion(&$versions) + { + $versions[] = array('name' => 'Recaptcha', + 'version' => STATUSNET_VERSION, + 'author' => 'Eric Helgeson', + 'homepage' => 'http://status.net/wiki/Plugin:Recaptcha', + 'rawdescription' => + _m('Uses Recaptcha service to add a '. + 'captcha to the registration page.')); + return true; + } } From 71f519f64aed1dd6823a0f09db5c4c2e409da778 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 18 Jan 2010 23:25:45 -0500 Subject: [PATCH 09/53] add event for showing content license in action --- EVENTS.txt | 6 ++++++ lib/action.php | 37 ++++++++++++++++++++----------------- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/EVENTS.txt b/EVENTS.txt index e6400244e4..6e6afa070f 100644 --- a/EVENTS.txt +++ b/EVENTS.txt @@ -687,3 +687,9 @@ StartLeaveGroup: when a user is leaving a group EndLeaveGroup: when a user has left a group - $group: the group being left - $user: the user leaving + +StartShowContentLicense: Showing the default license for content +- $action: the current action + +EndShowContentLicense: Showing the default license for content +- $action: the current action diff --git a/lib/action.php b/lib/action.php index a521bcb507..813d089fef 100644 --- a/lib/action.php +++ b/lib/action.php @@ -791,23 +791,26 @@ class Action extends HTMLOutputter // lawsuit */ function showContentLicense() { - $this->element('dt', array('id' => 'site_content_license'), _('Site content license')); - $this->elementStart('dd', array('id' => 'site_content_license_cc')); - $this->elementStart('p'); - $this->element('img', array('id' => 'license_cc', - 'src' => common_config('license', 'image'), - 'alt' => common_config('license', 'title'), - 'width' => '80', - 'height' => '15')); - //TODO: This is dirty: i18n - $this->text(_('All '.common_config('site', 'name').' content and data are available under the ')); - $this->element('a', array('class' => 'license', - 'rel' => 'external license', - 'href' => common_config('license', 'url')), - common_config('license', 'title')); - $this->text(_('license.')); - $this->elementEnd('p'); - $this->elementEnd('dd'); + if (Event::handle('StartShowContentLicense', array($this))) { + $this->element('dt', array('id' => 'site_content_license'), _('Site content license')); + $this->elementStart('dd', array('id' => 'site_content_license_cc')); + $this->elementStart('p'); + $this->element('img', array('id' => 'license_cc', + 'src' => common_config('license', 'image'), + 'alt' => common_config('license', 'title'), + 'width' => '80', + 'height' => '15')); + //TODO: This is dirty: i18n + $this->text(_('All '.common_config('site', 'name').' content and data are available under the ')); + $this->element('a', array('class' => 'license', + 'rel' => 'external license', + 'href' => common_config('license', 'url')), + common_config('license', 'title')); + $this->text(_('license.')); + $this->elementEnd('p'); + $this->elementEnd('dd'); + Event::handle('EndShowContentLicense', array($this)); + } } /** From c7f14cd7774d21e16aa6b020da71f318c648e3f0 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 19 Jan 2010 00:04:58 -0500 Subject: [PATCH 10/53] allow all rights reserved, private data --- README | 6 ++++++ lib/action.php | 47 +++++++++++++++++++++++++++++++++-------------- lib/default.php | 4 +++- 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/README b/README index 7457215a1f..386b3264a2 100644 --- a/README +++ b/README @@ -1035,6 +1035,12 @@ Creative Commons Attribution 3.0 license, which is probably the right choice for any public site. Note that some other servers will not accept notices if you apply a stricter license than this. +type: one of 'cc' (for Creative Commons licenses), 'allrightsreserved' + (default copyright), or 'private' (for private and confidential + information). +owner: for 'allrightsreserved' or 'private', an assigned copyright + holder (for example, an employer for a private site). If + not specified, will be attributed to 'contributors'. url: URL of the license, used for links. title: Title for the license, like 'Creative Commons Attribution 3.0'. image: A button shown on each page for the license. diff --git a/lib/action.php b/lib/action.php index 813d089fef..171bea17c7 100644 --- a/lib/action.php +++ b/lib/action.php @@ -794,20 +794,39 @@ class Action extends HTMLOutputter // lawsuit if (Event::handle('StartShowContentLicense', array($this))) { $this->element('dt', array('id' => 'site_content_license'), _('Site content license')); $this->elementStart('dd', array('id' => 'site_content_license_cc')); - $this->elementStart('p'); - $this->element('img', array('id' => 'license_cc', - 'src' => common_config('license', 'image'), - 'alt' => common_config('license', 'title'), - 'width' => '80', - 'height' => '15')); - //TODO: This is dirty: i18n - $this->text(_('All '.common_config('site', 'name').' content and data are available under the ')); - $this->element('a', array('class' => 'license', - 'rel' => 'external license', - 'href' => common_config('license', 'url')), - common_config('license', 'title')); - $this->text(_('license.')); - $this->elementEnd('p'); + + switch (common_config('license', 'type')) { + case 'private': + $this->element('p', null, sprintf(_('Content and data of %1$s are private and confidential.'), + common_config('site', 'name'))); + // fall through + case 'allrightsreserved': + if (common_config('license', 'owner')) { + $this->element('p', null, sprintf(_('Content and data copyright by %1$s. All rights reserved.'), + common_config('license', 'owner'))); + } else { + $this->element('p', null, _('Content and data copyright by contributors. All rights reserved.')); + } + break; + case 'cc': // fall through + default: + $this->elementStart('p'); + $this->element('img', array('id' => 'license_cc', + 'src' => common_config('license', 'image'), + 'alt' => common_config('license', 'title'), + 'width' => '80', + 'height' => '15')); + //TODO: This is dirty: i18n + $this->text(_('All '.common_config('site', 'name').' content and data are available under the ')); + $this->element('a', array('class' => 'license', + 'rel' => 'external license', + 'href' => common_config('license', 'url')), + common_config('license', 'title')); + $this->text(_('license.')); + $this->elementEnd('p'); + break; + } + $this->elementEnd('dd'); Event::handle('EndShowContentLicense', array($this)); } diff --git a/lib/default.php b/lib/default.php index f7f4777a2e..5b2ae6c7c1 100644 --- a/lib/default.php +++ b/lib/default.php @@ -83,7 +83,9 @@ $default = 'softlimit' => '90%', // total size or % of memory_limit at which to restart queue threads gracefully ), 'license' => - array('url' => 'http://creativecommons.org/licenses/by/3.0/', + array('type' => 'cc', # can be 'cc', 'allrightsreserved', 'private' + 'owner' => null, # can be name of content owner e.g. for enterprise + 'url' => 'http://creativecommons.org/licenses/by/3.0/', 'title' => 'Creative Commons Attribution 3.0', 'image' => 'http://i.creativecommons.org/l/by/3.0/80x15.png'), 'mail' => From 71df23642c60d24669def858a8059d70f284744c Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 19 Jan 2010 12:26:59 -0800 Subject: [PATCH 11/53] Extra debug instrumentation for xmppdaemon --- scripts/xmppdaemon.php | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/xmppdaemon.php b/scripts/xmppdaemon.php index cef9c4bd07..0c118c53d6 100755 --- a/scripts/xmppdaemon.php +++ b/scripts/xmppdaemon.php @@ -148,6 +148,7 @@ class XMPPDaemon extends Daemon function handle_message(&$pl) { + $this->log(LOG_DEBUG, "Received message: " . str_replace("\n", " ", var_export($pl, true))); $from = jabber_normalize_jid($pl['from']); if ($pl['type'] != 'chat') { From b0be2da0ca11f0d077e82fc7efe5781cea4d84bf Mon Sep 17 00:00:00 2001 From: Siebrand Mazeland Date: Wed, 20 Jan 2010 00:58:11 +0100 Subject: [PATCH 12/53] Localisation updates for !StatusNet from !translatewiki.net !sntrans --- locale/ar/LC_MESSAGES/statusnet.po | 6 +- locale/arz/LC_MESSAGES/statusnet.po | 8 +- locale/statusnet.po | 2 +- locale/sv/LC_MESSAGES/statusnet.po | 287 ++++++++++++++-------------- 4 files changed, 155 insertions(+), 148 deletions(-) diff --git a/locale/ar/LC_MESSAGES/statusnet.po b/locale/ar/LC_MESSAGES/statusnet.po index 4024aed11b..28e85d92fc 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-01-18 23:16+0000\n" -"PO-Revision-Date: 2010-01-18 23:17:05+0000\n" +"PO-Revision-Date: 2010-01-19 23:52:48+0000\n" "Language-Team: Arabic\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61218); Translate extension (2010-01-16)\n" +"X-Generator: MediaWiki 1.16alpha (r61275); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: ar\n" "X-Message-Group: out-statusnet\n" @@ -2919,7 +2919,7 @@ msgstr "" #: actions/repeat.php:57 msgid "Only logged-in users can repeat notices." -msgstr "" +msgstr "يستطيع المستخدمون الوالجون وحدهم تكرار الإشعارات." #: actions/repeat.php:64 actions/repeat.php:71 msgid "No notice specified." diff --git a/locale/arz/LC_MESSAGES/statusnet.po b/locale/arz/LC_MESSAGES/statusnet.po index 8de26e44b9..b5f740c4f4 100644 --- a/locale/arz/LC_MESSAGES/statusnet.po +++ b/locale/arz/LC_MESSAGES/statusnet.po @@ -10,11 +10,11 @@ msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-16 17:51:30+0000\n" +"PO-Revision-Date: 2010-01-19 23:52:52+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.16alpha (r61138); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61275); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: arz\n" "X-Message-Group: out-statusnet\n" @@ -4116,12 +4116,12 @@ msgstr "" msgid "Problem saving notice." msgstr "مشكله أثناء حفظ الإشعار." -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, php-format msgid "RT @%1$s %2$s" msgstr "آر تى @%1$s %2$s" diff --git a/locale/statusnet.po b/locale/statusnet.po index 097ed22237..9c28de8029 100644 --- a/locale/statusnet.po +++ b/locale/statusnet.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-18 23:16+0000\n" +"POT-Creation-Date: 2010-01-19 23:52+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 f8e290877c..d7e0f19c9b 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-01-18 23:16+0000\n" -"PO-Revision-Date: 2010-01-18 23:19:55+0000\n" +"PO-Revision-Date: 2010-01-19 23:55:02+0000\n" "Language-Team: Swedish\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61218); Translate extension (2010-01-16)\n" +"X-Generator: MediaWiki 1.16alpha (r61275); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: sv\n" "X-Message-Group: out-statusnet\n" @@ -82,7 +82,7 @@ msgstr "Flöden för %ss vänner (Atom)" #, php-format msgid "" "This is the timeline for %s and friends but no one has posted anything yet." -msgstr "Detta är tidslinjen för %s och vänner men ingen har postat något än." +msgstr "Detta är tidslinjen för %s och vänner, men ingen har skrivit något än." #: actions/all.php:132 #, php-format @@ -91,17 +91,17 @@ msgid "" "something yourself." msgstr "" "Prova att prenumerera på fler personer, [gå med i en grupp](%%action.groups%" -"%) eller posta något själv." +"%) eller skriv något själv." #: actions/all.php:134 -#, fuzzy, php-format +#, php-format msgid "" "You can try to [nudge %1$s](../%2$s) from his profile or [post something to " "his or her attention](%%%%action.newnotice%%%%?status_textarea=%3$s)." msgstr "" -"Du kan prova att [knuffa %s](../%s) från dennes profil eller [posta " +"Du kan prova att [knuffa %1$s](../%2$s) från dennes profil eller [skriva " "någonting för hans eller hennes uppmärksamhet](%%%%action.newnotice%%%%?" -"status_textarea=%s)." +"status_textarea=%3$s)." #: actions/all.php:137 actions/replies.php:209 actions/showstream.php:202 #, php-format @@ -110,7 +110,7 @@ msgid "" "post a notice to his or her attention." msgstr "" "Varför inte [registrera ett konto](%%%%action.register%%%%) och sedan knuffa " -"%s eller posta en notis för hans eller hennes uppmärksamhet." +"%s eller skriva en notis för hans eller hennes uppmärksamhet." #: actions/all.php:165 msgid "You and friends" @@ -145,7 +145,7 @@ msgstr "Uppdateringar från %1$s och vänner på %2$s!" #: actions/apitimelineretweetsofme.php:122 actions/apitimelinetag.php:141 #: actions/apitimelineuser.php:165 actions/apiusershow.php:101 msgid "API method not found." -msgstr "API-metoden hittades inte" +msgstr "API-metod hittades inte." #: actions/apiaccountupdatedeliverydevice.php:85 #: actions/apiaccountupdateprofile.php:89 @@ -306,11 +306,11 @@ msgstr "Två användar-ID:n eller screen_names måste tillhandahållas." #: actions/apifriendshipsshow.php:135 msgid "Could not determine source user." -msgstr "" +msgstr "Kunde inte fastställa användare hos källan." #: actions/apifriendshipsshow.php:143 msgid "Could not find target user." -msgstr "" +msgstr "Kunde inte hitta målanvändare." #: actions/apigroupcreate.php:164 actions/editgroup.php:182 #: actions/newgroup.php:126 actions/profilesettings.php:215 @@ -348,7 +348,7 @@ msgstr "Fullständigt namn är för långt (max 255 tecken)." #: actions/newapplication.php:169 #, php-format msgid "Description is too long (max %d chars)." -msgstr "Beskrivning är för lång (max 140 tecken)" +msgstr "Beskrivning är för lång (max 140 tecken)." #: actions/apigroupcreate.php:224 actions/editgroup.php:204 #: actions/newgroup.php:148 actions/profilesettings.php:232 @@ -424,7 +424,7 @@ msgstr "grupper på %s" #: actions/apioauthauthorize.php:108 actions/apioauthauthorize.php:114 msgid "Bad request." -msgstr "" +msgstr "Dålig förfrågan." #: actions/apioauthauthorize.php:134 actions/avatarsettings.php:268 #: actions/deletenotice.php:157 actions/disfavor.php:74 @@ -449,26 +449,24 @@ msgid "Invalid nickname / password!" msgstr "Ogiltigt smeknamn / lösenord!" #: actions/apioauthauthorize.php:170 -#, fuzzy msgid "DB error deleting OAuth app user." -msgstr "Fel uppstog i användarens inställning" +msgstr "Databasfel vid borttagning av OAuth-applikationsanvändare." #: actions/apioauthauthorize.php:196 -#, fuzzy msgid "DB error inserting OAuth app user." -msgstr "Databasfel vid infogning av hashtag: %s" +msgstr "Databasfel vid infogning av OAuth-applikationsanvändare." #: actions/apioauthauthorize.php:231 #, php-format msgid "" "The request token %s has been authorized. Please exchange it for an access " "token." -msgstr "" +msgstr "Begäran-token %s har godkänts. Byt ut den mot en åtkomst-token." #: actions/apioauthauthorize.php:241 #, php-format msgid "The request token %s has been denied." -msgstr "" +msgstr "Begäran-token %s har nekats." #: actions/apioauthauthorize.php:246 actions/avatarsettings.php:281 #: actions/designadminpanel.php:103 actions/editapplication.php:139 @@ -481,7 +479,7 @@ msgstr "Oväntat inskick av formulär." #: actions/apioauthauthorize.php:273 msgid "An application would like to connect to your account" -msgstr "" +msgstr "En applikation skulle vilja ansluta till ditt konto" #: actions/apioauthauthorize.php:290 msgid "Allow or deny access" @@ -557,7 +555,7 @@ msgstr "Hittades inte" #: actions/apistatusesupdate.php:226 actions/newnotice.php:178 #, php-format msgid "Max notice size is %d chars, including attachment URL." -msgstr "Maximal notisstorlek är %d tecken, inklusive bilage-URL." +msgstr "Maximal notisstorlek är %d tecken, inklusive URL för bilaga." #: actions/apisubscriptions.php:231 actions/apisubscriptions.php:261 msgid "Unsupported format." @@ -1051,14 +1049,12 @@ msgid "Edit application" msgstr "Redigera applikation" #: actions/editapplication.php:66 -#, fuzzy msgid "You must be logged in to edit an application." -msgstr "Du måste vara inloggad för att redigera en grupp." +msgstr "Du måste vara inloggad för att redigera en applikation." #: actions/editapplication.php:77 actions/showapplication.php:94 -#, fuzzy msgid "You are not the owner of this application." -msgstr "Du är inte en medlem i denna grupp." +msgstr "Du är inte ägaren av denna applikation." #: actions/editapplication.php:81 actions/oauthconnectionssettings.php:163 #: actions/showapplication.php:87 @@ -1075,54 +1071,48 @@ msgid "Use this form to edit your application." msgstr "Använd detta formulär för att redigera din applikation." #: actions/editapplication.php:177 actions/newapplication.php:159 -#, fuzzy msgid "Name is required." -msgstr "Samma som lösenordet ovan. Måste fyllas i." +msgstr "Namn krävs." #: actions/editapplication.php:180 actions/newapplication.php:162 msgid "Name is too long (max 255 chars)." msgstr "Namnet är för långt (max 255 tecken)." #: actions/editapplication.php:183 actions/newapplication.php:165 -#, fuzzy msgid "Description is required." -msgstr "Beskrivning" +msgstr "Beskrivning krävs." #: actions/editapplication.php:191 msgid "Source URL is too long." -msgstr "" +msgstr "URL till källa är för lång." #: actions/editapplication.php:197 actions/newapplication.php:182 -#, fuzzy msgid "Source URL is not valid." -msgstr "Avatar-URL ‘%s’ är inte giltig." +msgstr "URL till källa är inte giltig." #: actions/editapplication.php:200 actions/newapplication.php:185 msgid "Organization is required." -msgstr "" +msgstr "Organisation krävs." #: actions/editapplication.php:203 actions/newapplication.php:188 -#, fuzzy msgid "Organization is too long (max 255 chars)." -msgstr "Beskrivning av plats är för lång (max 255 tecken)." +msgstr "Organisation är för lång (max 255 tecken)." #: actions/editapplication.php:206 actions/newapplication.php:191 msgid "Organization homepage is required." -msgstr "" +msgstr "Hemsida för organisation krävs." #: actions/editapplication.php:215 actions/newapplication.php:203 msgid "Callback is too long." -msgstr "" +msgstr "Anrop är för lång." #: actions/editapplication.php:222 actions/newapplication.php:212 -#, fuzzy msgid "Callback URL is not valid." -msgstr "Avatar-URL ‘%s’ är inte giltig." +msgstr "URL för anrop är inte giltig." #: actions/editapplication.php:255 -#, fuzzy msgid "Could not update application." -msgstr "Kunde inte uppdatera grupp." +msgstr "Kunde inte uppdatera applikation." #: actions/editgroup.php:56 #, php-format @@ -1280,7 +1270,7 @@ msgstr "Inte en giltig e-postadress." #: actions/emailsettings.php:334 msgid "That is already your email address." -msgstr "Detta är redan din e-postadress." +msgstr "Det är redan din e-postadress." #: actions/emailsettings.php:337 msgid "That email address already belongs to another user." @@ -1316,7 +1306,7 @@ msgstr "Bekräftelse avbruten." #: actions/emailsettings.php:413 msgid "That is not your email address." -msgstr "Detta är inte din e-postadress." +msgstr "Det är inte din e-postadress." #: actions/emailsettings.php:432 actions/imsettings.php:408 #: actions/smssettings.php:425 @@ -1373,8 +1363,8 @@ msgid "" "Be the first to add a notice to your favorites by clicking the fave button " "next to any notice you like." msgstr "" -"Bli först att lägga en notis till dina favoriter genom att klicka på favorit-" -"knappen bredvid någon notis du gillar." +"Var den första att lägga en notis till dina favoriter genom att klicka på " +"favorit-knappen bredvid någon notis du gillar." #: actions/favorited.php:156 #, php-format @@ -1382,8 +1372,8 @@ msgid "" "Why not [register an account](%%action.register%%) and be the first to add a " "notice to your favorites!" msgstr "" -"Varför inte [registrera ett konto](%%action.register%%) och bli först att " -"lägga en notis till dina favoriter!" +"Varför inte [registrera ett konto](%%action.register%%) och vara först med " +"att lägga en notis till dina favoriter!" #: actions/favoritesrss.php:111 actions/showfavorites.php:77 #: lib/personalgroupnav.php:115 @@ -1449,7 +1439,7 @@ msgstr "Du har inte tillstånd." #: actions/finishremotesubscribe.php:113 msgid "Could not convert request token to access token." -msgstr "Kunde inte konvertera förfrågnings-token till access-token." +msgstr "Kunde inte konvertera token för begäran till token för åtkomst." #: actions/finishremotesubscribe.php:118 msgid "Remote service uses unknown version of OMB protocol." @@ -1508,8 +1498,8 @@ msgid "" "the group in the future." msgstr "" "Är du säker på att du vill blockera användare \"%1$s\" från gruppen \"%2$s" -"\"? De kommer bli borttagna från gruppen, inte kunna posta och inte kunna " -"prenumerera på gruppen i framtiden." +"\"? De kommer bli borttagna från gruppen, inte kunna skriva till och inte " +"kunna prenumerera på gruppen i framtiden." #: actions/groupblock.php:178 msgid "Do not block this user from this group" @@ -1723,8 +1713,8 @@ msgid "" "Awaiting confirmation on this address. Check your Jabber/GTalk account for a " "message with further instructions. (Did you add %s to your buddy list?)" msgstr "" -"Väntar bekräftelse av denna adress. Kontrollera ditt Jabber/GTalk-konto för " -"vidare instruktioner. (La du till %s i din kompislista?)" +"Väntar på bekräftelse för denna adress. Kontrollera ditt Jabber/GTalk-konto " +"för vidare instruktioner. (La du till %s i din kompislista?)" #: actions/imsettings.php:124 msgid "IM address" @@ -1736,8 +1726,8 @@ msgid "" "Jabber or GTalk address, like \"UserName@example.org\". First, make sure to " "add %s to your buddy list in your IM client or on GTalk." msgstr "" -"Jabber- eller GTalk-adress liknande \"användarnamn@example.org\". Se först " -"till att lägga till %s i din kompislista i din IM-klient eller hos GTalk." +"Jabber- eller GTalk-adress, som \"användarnamn@example.org\". Se först till " +"att lägga till %s i din kompislista i din IM-klient eller hos GTalk." #: actions/imsettings.php:143 msgid "Send me notices through Jabber/GTalk." @@ -1783,8 +1773,8 @@ msgid "" "A confirmation code was sent to the IM address you added. You must approve %" "s for sending messages to you." msgstr "" -"En bekräftelsekod har skickats till den IM-adress du angav. Du måste " -"godkänna att %s får skicka meddelanden till dig." +"En bekräftelsekod skickades till den IM-adress du angav. Du måste godkänna " +"att %s får skicka meddelanden till dig." #: actions/imsettings.php:387 msgid "That is not your Jabber ID." @@ -1854,8 +1844,8 @@ msgstr "" msgid "" "Use this form to invite your friends and colleagues to use this service." msgstr "" -"Använd detta formulär för att bjuda in dina vänner och kollegor till denna " -"webbplats." +"Använd detta formulär för att bjuda in dina vänner och kollegor att använda " +"denna tjänst." #: actions/invite.php:187 msgid "Email addresses" @@ -2022,7 +2012,7 @@ msgstr "Använd detta formulär för att registrera en ny applikation." #: actions/newapplication.php:173 msgid "Source URL is required." -msgstr "" +msgstr "URL till källa krävs." #: actions/newapplication.php:255 actions/newapplication.php:264 msgid "Could not create application." @@ -2105,8 +2095,8 @@ msgid "" "Be the first to [post on this topic](%%%%action.newnotice%%%%?" "status_textarea=%s)!" msgstr "" -"Bli först att [posta i detta ämne](%%%%action.newnotice%%%%?status_textarea=%" -"s)!" +"Var den första att [skriva i detta ämne](%%%%action.newnotice%%%%?" +"status_textarea=%s)!" #: actions/noticesearch.php:124 #, php-format @@ -2114,8 +2104,8 @@ msgid "" "Why not [register an account](%%%%action.register%%%%) and be the first to " "[post on this topic](%%%%action.newnotice%%%%?status_textarea=%s)!" msgstr "" -"Varför inte [registrera ett konto](%%%%action.register%%%%) och bli först " -"att [posta i detta ämne](%%%%action.newnotice%%%%?status_textarea=%s)!" +"Varför inte [registrera ett konto](%%%%action.register%%%%) och vara först " +"med att [skriva i detta ämne](%%%%action.newnotice%%%%?status_textarea=%s)!" #: actions/noticesearchrss.php:96 #, php-format @@ -2147,9 +2137,8 @@ msgid "You must be logged in to list your applications." msgstr "Du måste vara inloggad för att lista dina applikationer." #: actions/oauthappssettings.php:74 -#, fuzzy msgid "OAuth applications" -msgstr "Övriga alternativ" +msgstr "OAuth-applikationer" #: actions/oauthappssettings.php:85 msgid "Applications you have registered" @@ -2169,9 +2158,8 @@ msgid "You have allowed the following applications to access you account." msgstr "Du har tillåtit följande applikationer att komma åt ditt konto." #: actions/oauthconnectionssettings.php:170 -#, fuzzy msgid "You are not a user of that application." -msgstr "Du är inte en medlem i den gruppen." +msgstr "Du är inte en användare av den applikationen." #: actions/oauthconnectionssettings.php:180 msgid "Unable to revoke access for app: " @@ -2185,6 +2173,7 @@ msgstr "Du har inte tillåtit några applikationer att använda ditt konto." #: actions/oauthconnectionssettings.php:205 msgid "Developers can edit the registration settings for their applications " msgstr "" +"Utvecklare kan redigera registreringsinställningarna för sina applikationer " #: actions/oembed.php:79 actions/shownotice.php:100 msgid "Notice has no profile" @@ -2249,29 +2238,24 @@ msgid "URL shortening service is too long (max 50 chars)." msgstr "Namnet på URL-förkortningstjänsen är för långt (max 50 tecken)." #: actions/otp.php:69 -#, fuzzy msgid "No user ID specified." -msgstr "Ingen grupp angiven." +msgstr "Ingen användar-ID angiven." #: actions/otp.php:83 -#, fuzzy msgid "No login token specified." -msgstr "Ingen notis angiven." +msgstr "Ingen inloggnings-token angiven." #: actions/otp.php:90 -#, fuzzy msgid "No login token requested." -msgstr "Ingen profil-ID i begäran." +msgstr "Ingen token för inloggning begärd." #: actions/otp.php:95 -#, fuzzy msgid "Invalid login token specified." -msgstr "Ogiltig eller utgången token." +msgstr "Ogiltig inloggnings-token angiven." #: actions/otp.php:104 -#, fuzzy msgid "Login token expired." -msgstr "Logga in på webbplatsen" +msgstr "Inloggnings-token förfallen." #: actions/outbox.php:61 #, php-format @@ -2474,7 +2458,7 @@ msgstr "SSL-server" #: actions/pathsadminpanel.php:309 msgid "Server to direct SSL requests to" -msgstr "Server att dirigera SSL-förfrågningar till" +msgstr "Server att dirigera SSL-begäran till" #: actions/pathsadminpanel.php:325 msgid "Save paths" @@ -2508,9 +2492,9 @@ msgid "Invalid notice content" msgstr "Ogiltigt notisinnehåll" #: actions/postnotice.php:90 -#, fuzzy, php-format +#, php-format msgid "Notice license ‘%1$s’ is not compatible with site license ‘%2$s’." -msgstr "Licensen för notiser ‘%s’ är inte förenlig webbplatslicensen ‘%s’." +msgstr "Licensen för notiser ‘%1$s’ är inte förenlig webbplatslicensen ‘%2$s’." #: actions/profilesettings.php:60 msgid "Profile settings" @@ -2520,8 +2504,8 @@ msgstr "Profilinställningar" msgid "" "You can update your personal profile info here so people know more about you." msgstr "" -"Du kan uppdatera din personliga profilinformation här så personer får veta " -"mer om dig." +"Du kan uppdatera din personliga profilinformation här så att folk vet mer om " +"dig." #: actions/profilesettings.php:99 msgid "Profile information" @@ -2607,7 +2591,8 @@ msgstr "I vilken tidszon befinner du dig normalt?" msgid "" "Automatically subscribe to whoever subscribes to me (best for non-humans)" msgstr "" -"Prenumerera automatiskt på den prenumererar på mig (bäst för icke-människa) " +"Prenumerera automatiskt på den som prenumererar på mig (bäst för icke-" +"människa) " #: actions/profilesettings.php:228 actions/register.php:223 #, php-format @@ -2880,11 +2865,11 @@ msgstr "Nya lösenordet sparat. Du är nu inloggad." #: actions/register.php:85 actions/register.php:189 actions/register.php:405 msgid "Sorry, only invited people can register." -msgstr "Ledsen, bara inbjudna personer kan registrera sig." +msgstr "Tyvärr, bara inbjudna personer kan registrera sig." #: actions/register.php:92 msgid "Sorry, invalid invitation code." -msgstr "Ledsen, ogiltig inbjudningskod." +msgstr "Tyvärr, ogiltig inbjudningskod." #: actions/register.php:112 msgid "Registration successful" @@ -3048,7 +3033,7 @@ msgstr "Det där är en lokal profil! Logga in för att prenumerera." #: actions/remotesubscribe.php:183 msgid "Couldn’t get a request token." -msgstr "Kunde inte få en förfrågnings-token." +msgstr "Kunde inte få en token för begäran." #: actions/repeat.php:57 msgid "Only logged-in users can repeat notices." @@ -3096,12 +3081,12 @@ msgid "Replies feed for %s (Atom)" msgstr "Flöde med svar för %s (Atom)" #: actions/replies.php:198 -#, fuzzy, php-format +#, php-format msgid "" "This is the timeline showing replies to %1$s but %2$s hasn't received a " "notice to his attention yet." msgstr "" -"Detta är tidslinjen som visar svar till %s men %s har inte tagit emot en " +"Detta är tidslinjen som visar svar till %s1$ men %2$s har inte tagit emot en " "notis för dennes uppmärksamhet än." #: actions/replies.php:203 @@ -3114,13 +3099,13 @@ msgstr "" "personer eller [gå med i grupper](%%action.groups%%)." #: actions/replies.php:205 -#, fuzzy, php-format +#, php-format msgid "" "You can try to [nudge %1$s](../%2$s) or [post something to his or her " "attention](%%%%action.newnotice%%%%?status_textarea=%3$s)." msgstr "" -"Du kan prova att [knuffa %s](../%s) eller [posta någonting för hans eller " -"hennes uppmärksamhet](%%%%action.newnotice%%%%?status_textarea=%s)." +"Du kan prova att [knuffa %1$s](../%2$s) eller [posta någonting för hans " +"eller hennes uppmärksamhet](%%%%action.newnotice%%%%?status_textarea=%3$s)." #: actions/repliesrss.php:72 #, php-format @@ -3136,9 +3121,8 @@ msgid "User is already sandboxed." msgstr "Användare är redan flyttad till sandlådan." #: actions/showapplication.php:82 -#, fuzzy msgid "You must be logged in to view an application." -msgstr "Du måste vara inloggad för att lämna en grupp." +msgstr "Du måste vara inloggad för att se en applikation." #: actions/showapplication.php:158 msgid "Application profile" @@ -3170,15 +3154,15 @@ msgstr "Statistik" #: actions/showapplication.php:204 #, php-format msgid "created by %1$s - %2$s access by default - %3$d users" -msgstr "" +msgstr "skapad av %1$s - %2$s standardåtkomst - %3$d användare" #: actions/showapplication.php:214 msgid "Application actions" -msgstr "" +msgstr "Åtgärder för applikation" #: actions/showapplication.php:233 msgid "Reset key & secret" -msgstr "" +msgstr "Återställ nyckel & hemlighet" #: actions/showapplication.php:241 msgid "Application info" @@ -3186,30 +3170,31 @@ msgstr "Information om applikation" #: actions/showapplication.php:243 msgid "Consumer key" -msgstr "" +msgstr "Nyckel för konsument" #: actions/showapplication.php:248 msgid "Consumer secret" -msgstr "" +msgstr "Hemlighet för konsument" #: actions/showapplication.php:253 msgid "Request token URL" -msgstr "" +msgstr "URL för begäran-token" #: actions/showapplication.php:258 msgid "Access token URL" -msgstr "" +msgstr "URL för åtkomst-token" #: actions/showapplication.php:263 -#, fuzzy msgid "Authorize URL" -msgstr "Författare" +msgstr "Tillåt URL" #: actions/showapplication.php:268 msgid "" "Note: We support HMAC-SHA1 signatures. We do not support the plaintext " "signature method." msgstr "" +"Notera: Vi stöjder HMAC-SHA1-signaturer. Vi stödjer inte metoden med " +"klartextsignatur." #: actions/showfavorites.php:132 msgid "Could not retrieve favorite notices." @@ -3235,6 +3220,9 @@ msgid "" "You haven't chosen any favorite notices yet. Click the fave button on " "notices you like to bookmark them for later or shed a spotlight on them." msgstr "" +"Du har inte valt några favoritnotiser ännu. Klicka på favorit-knappen " +"bredvid någon notis du skulle vilja bokmärka för senare tillfälle eller för " +"att sätta strålkastarljuset på." #: actions/showfavorites.php:207 #, php-format @@ -3242,6 +3230,8 @@ msgid "" "%s hasn't added any notices to his favorites yet. Post something interesting " "they would add to their favorites :)" msgstr "" +"%s har inte lagt till några notiser till sina favoriter ännu. Posta något " +"intressant de skulle lägga till sina favoriter :)" #: actions/showfavorites.php:211 #, php-format @@ -3250,10 +3240,13 @@ msgid "" "account](%%%%action.register%%%%) and then post something interesting they " "would add to their favorites :)" msgstr "" +"%s har inte lagt till några notiser till sina favoriter ännu. Varför inte " +"[registrera ett konto](%%%%action.register%%%%) och posta något intressant " +"de skulle lägga till sina favoriter :)" #: actions/showfavorites.php:242 msgid "This is a way to share what you like." -msgstr "Detta är ett sätt att dela vad du gillar." +msgstr "Detta är ett sätt att dela med av det du gillar." #: actions/showgroup.php:82 lib/groupnav.php:86 #, php-format @@ -3280,7 +3273,7 @@ msgstr "Alias" #: actions/showgroup.php:293 msgid "Group actions" -msgstr "Gruppåtgärder" +msgstr "Åtgärder för grupp" #: actions/showgroup.php:328 #, php-format @@ -3418,13 +3411,13 @@ msgstr "" "inte börja nu?" #: actions/showstream.php:198 -#, fuzzy, php-format +#, php-format msgid "" "You can try to nudge %1$s or [post something to his or her attention](%%%%" "action.newnotice%%%%?status_textarea=%2$s)." msgstr "" -"Du kan prova att knuffa %s eller [posta något för hans eller hennes " -"uppmärksamhet](%%%%action.newnotice%%%%?status_textarea=%s)." +"Du kan prova att knuffa %1$s eller [posta något för hans eller hennes " +"uppmärksamhet](%%%%action.newnotice%%%%?status_textarea=%2$s)." #: actions/showstream.php:234 #, php-format @@ -3827,12 +3820,12 @@ msgstr "%1$s prenumerationer, sida %2$d" #: actions/subscriptions.php:65 msgid "These are the people whose notices you listen to." -msgstr "Dessa är de personer vars notiser du lyssnar på." +msgstr "Det är dessa personer vars meddelanden du lyssnar på." #: actions/subscriptions.php:69 #, php-format msgid "These are the people whose notices %s listens to." -msgstr "Dessa är de personer vars notiser %s lyssnar på." +msgstr "Det är dessa personer vars notiser %s lyssnar på." #: actions/subscriptions.php:121 #, php-format @@ -3843,6 +3836,12 @@ msgid "" "featured%%). If you're a [Twitter user](%%action.twittersettings%%), you can " "automatically subscribe to people you already follow there." msgstr "" +"Du lyssnar inte på någons notiser just nu. Prova att prenumerera på personer " +"du känner. Prova [personsökning] (%%action.peoplesearch%%), leta bland " +"medlemmar i grupper som intresserad dig och bland våra [profilerade " +"användare] (%%action.featured%%). Om du är en [Twitter-användare] (%%action." +"twittersettings%%) kan du prenumerera automatiskt på personer som du redan " +"följer där." #: actions/subscriptions.php:123 actions/subscriptions.php:127 #, php-format @@ -4079,7 +4078,7 @@ msgstr "Avvisa denna prenumeration" #: actions/userauthorization.php:225 msgid "No authorization request!" -msgstr "Ingen auktoriseringsförfrågan!" +msgstr "Ingen begäran om godkännande!" #: actions/userauthorization.php:247 msgid "Subscription authorized" @@ -4091,7 +4090,7 @@ msgid "" "with the site’s instructions for details on how to authorize the " "subscription. Your subscription token is:" msgstr "" -"Prenumerationen har blivit bekräftad, men ingen URL har gått igenom. Kolla " +"Prenumerationen har godkänts, men ingen anrops-URL har gått igenom. Kolla " "med webbplatsens instruktioner hur du bekräftar en prenumeration. Din " "prenumerations-token är:" @@ -4185,6 +4184,8 @@ msgid "" "This site is powered by %1$s version %2$s, Copyright 2008-2010 StatusNet, " "Inc. and contributors." msgstr "" +"Denna webbplats drivs med %1$s version %2$s, Copyright 2008-2010 StatusNet, " +"Inc. och medarbetare." #: actions/version.php:157 msgid "StatusNet" @@ -4192,7 +4193,7 @@ msgstr "StatusNet" #: actions/version.php:161 msgid "Contributors" -msgstr "" +msgstr "Medarbetare" #: actions/version.php:168 msgid "" @@ -4201,6 +4202,10 @@ msgid "" "Software Foundation, either version 3 of the License, or (at your option) " "any later version. " msgstr "" +"StatusNet är fri programvara: du kan distribuera det och/eller modifiera den " +"under GNU Affero General Public License såsom publicerad av Free Software " +"Foundation, antingen version 3 av licensen, eller (utifrån ditt val) någon " +"senare version. " #: actions/version.php:174 msgid "" @@ -4209,6 +4214,10 @@ msgid "" "FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License " "for more details. " msgstr "" +"Detta program distribueras i hopp om att det kommer att vara användbart, men " +"UTAN NÅGRA GARANTIER; även utan underförstådda garantier om SÄLJBARHET eller " +"LÄMPLIGHET FÖR ETT SÄRSKILT ÄNDAMÅL. Se GNU Affero General Public License " +"för mer information. " #: actions/version.php:180 #, php-format @@ -4216,6 +4225,8 @@ msgid "" "You should have received a copy of the GNU Affero General Public License " "along with this program. If not, see %s." msgstr "" +"Du bör ha fått en kopia av GNU Affero General Public License tillsammans med " +"detta program. Om inte, se% s." #: actions/version.php:189 msgid "Plugins" @@ -4249,19 +4260,16 @@ msgid "A file this large would exceed your monthly quota of %d bytes." msgstr "En sådan här stor fil skulle överskrida din månatliga kvot på %d byte." #: classes/Group_member.php:41 -#, fuzzy msgid "Group join failed." -msgstr "Grupprofil" +msgstr "Gruppanslutning misslyckades." #: classes/Group_member.php:53 -#, fuzzy msgid "Not part of group." -msgstr "Kunde inte uppdatera grupp." +msgstr "Inte med i grupp." #: classes/Group_member.php:60 -#, fuzzy msgid "Group leave failed." -msgstr "Grupprofil" +msgstr "Grupputträde misslyckades." #: classes/Login_token.php:76 #, php-format @@ -4547,9 +4555,8 @@ msgid "You cannot make changes to this site." msgstr "Du kan inte göra förändringar av denna webbplats." #: lib/adminpanelaction.php:107 -#, fuzzy msgid "Changes to that panel are not allowed." -msgstr "Registrering inte tillåten." +msgstr "Ändringar av den panelen tillåts inte." #: lib/adminpanelaction.php:206 msgid "showForm() not implemented." @@ -4580,9 +4587,9 @@ msgid "Icon for this application" msgstr "Ikon för denna applikation" #: lib/applicationeditform.php:206 -#, fuzzy, php-format +#, php-format msgid "Describe your application in %d characters" -msgstr "Beskriv gruppen eller ämnet med högst %d tecken" +msgstr "Beskriv din applikation med högst %d tecken" #: lib/applicationeditform.php:209 msgid "Describe your application" @@ -4593,22 +4600,20 @@ msgid "Source URL" msgstr "URL för källa" #: lib/applicationeditform.php:220 -#, fuzzy msgid "URL of the homepage of this application" -msgstr "URL till gruppen eller ämnets hemsida eller blogg" +msgstr "URL till hemsidan för denna applikation" #: lib/applicationeditform.php:226 msgid "Organization responsible for this application" msgstr "Organisation som ansvarar för denna applikation" #: lib/applicationeditform.php:232 -#, fuzzy msgid "URL for the homepage of the organization" -msgstr "URL till gruppen eller ämnets hemsida eller blogg" +msgstr "URL till organisationens hemsidan" #: lib/applicationeditform.php:238 msgid "URL to redirect to after authentication" -msgstr "" +msgstr "URL att omdirigera till efter autentisering" #: lib/applicationeditform.php:260 msgid "Browser" @@ -4681,7 +4686,7 @@ msgstr "Kommando misslyckades" #: lib/command.php:44 msgid "Sorry, this command is not yet implemented." -msgstr "Ledsen, detta kommando är inte implementerat än." +msgstr "Tyvärr, detta kommando är inte implementerat än." #: lib/command.php:88 #, php-format @@ -4963,7 +4968,7 @@ msgstr "Anslutningar" #: lib/connectsettingsaction.php:121 msgid "Authorized connected applications" -msgstr "" +msgstr "Tillåt anslutna applikationer" #: lib/dberroraction.php:60 msgid "Database error" @@ -5155,9 +5160,9 @@ msgid "[%s]" msgstr "[%s]" #: lib/jabber.php:385 -#, fuzzy, php-format +#, php-format msgid "Unknown inbox source %d." -msgstr "Okänt språk \"%s\"" +msgstr "Okänd källa för inkorg %d." #: lib/joinform.php:114 msgid "Join" @@ -5374,16 +5379,16 @@ msgstr "Inte en registrerad användare." #: lib/mailhandler.php:46 msgid "Sorry, that is not your incoming email address." -msgstr "Ledsen, det är inte din inkommande e-postadress." +msgstr "Tyvärr, det är inte din inkommande e-postadress." #: lib/mailhandler.php:50 msgid "Sorry, no incoming email allowed." -msgstr "Ledsen, ingen inkommande e-post tillåts." +msgstr "Tyvärr, ingen inkommande e-post tillåts." #: lib/mailhandler.php:228 -#, fuzzy, php-format +#, php-format msgid "Unsupported message type: %s" -msgstr "Bildfilens format stödjs inte." +msgstr "Formatet %s för meddelande stödjs inte." #: lib/mediafile.php:98 lib/mediafile.php:123 msgid "There was a database error while saving your file. Please try again." @@ -5483,6 +5488,8 @@ msgid "" "Sorry, retrieving your geo location is taking longer than expected, please " "try again later" msgstr "" +"Tyvärr, hämtning av din geografiska plats tar längre tid än förväntat, var " +"god försök igen senare" #: lib/noticelist.php:428 #, php-format @@ -5539,7 +5546,7 @@ msgstr "Knuffa" #: lib/nudgeform.php:128 msgid "Send a nudge to this user" -msgstr "Skicka en knuff till den användaren." +msgstr "Skicka en knuff till denna användare" #: lib/oauthstore.php:283 msgid "Error inserting new profile" @@ -5555,7 +5562,7 @@ msgstr "Fel vid infogning av fjärrprofilen" #: lib/oauthstore.php:345 msgid "Duplicate notice" -msgstr "Duplicera notis" +msgstr "Duplicerad notis" #: lib/oauthstore.php:466 lib/subs.php:48 msgid "You have been banned from subscribing." @@ -5764,12 +5771,12 @@ msgstr "Kunde inte ta bort prenumeration." #: lib/subscriberspeopleselftagcloudsection.php:48 #: lib/subscriptionspeopleselftagcloudsection.php:48 msgid "People Tagcloud as self-tagged" -msgstr "" +msgstr "Taggmoln för person, såsom taggat själv" #: lib/subscriberspeopletagcloudsection.php:48 #: lib/subscriptionspeopletagcloudsection.php:48 msgid "People Tagcloud as tagged" -msgstr "" +msgstr "Taggmoln för person, såsom taggats" #: lib/tagcloudsection.php:56 msgid "None" @@ -5809,7 +5816,7 @@ msgstr "Redigera avatar" #: lib/userprofile.php:236 msgid "User actions" -msgstr "Användaråtgärd" +msgstr "Åtgärder för användare" #: lib/userprofile.php:248 msgid "Edit profile settings" From 906450e2f5b78a1c6f2dec2e21b9b5841df210f4 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 20 Jan 2010 08:37:58 -0800 Subject: [PATCH 13/53] DEBUG HACK: error checking for xml_parse in XMPPHP input stream --- extlib/XMPPHP/XMLStream.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/extlib/XMPPHP/XMLStream.php b/extlib/XMPPHP/XMLStream.php index d33411ec54..dbc4719e42 100644 --- a/extlib/XMPPHP/XMLStream.php +++ b/extlib/XMPPHP/XMLStream.php @@ -417,7 +417,12 @@ class XMPPHP_XMLStream { } } $this->log->log("RECV: $buff", XMPPHP_Log::LEVEL_VERBOSE); - xml_parse($this->parser, $buff, false); + $ok = xml_parse($this->parser, $buff, false); + if (!$ok) { + $errcode = xml_get_error_code($this->parser); + $errstr = xml_error_string($errcode); + $this->log->log("XML ERROR: $errstr", XMPPHP_Log::LEVEL_VERBOSE); + } } else { # $updated == 0 means no changes during timeout. } @@ -671,7 +676,12 @@ class XMPPHP_XMLStream { } } $this->log->log("RECV: $buff", XMPPHP_Log::LEVEL_VERBOSE); - xml_parse($this->parser, $buff, false); + $ok = xml_parse($this->parser, $buff, false); + if (!$ok) { + $errcode = xml_get_error_code($this->parser); + $errstr = xml_error_string($errcode); + $this->log->log("XML ERROR: $errstr", XMPPHP_Log::LEVEL_VERBOSE); + } } /** From b87c80e0a903119e97484333445c8944607a6b0d Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 20 Jan 2010 18:32:24 +0100 Subject: [PATCH 14/53] Updated notice item view where a) notice text no longer wraps around (under author's photo) b) supplemental notice content and options will start right under notice text. --- plugins/MobileProfile/mp-screen.css | 12 +++++++++++- theme/base/css/display.css | 22 +++++++++++++++++++--- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/plugins/MobileProfile/mp-screen.css b/plugins/MobileProfile/mp-screen.css index 472fbb0013..76071352d0 100644 --- a/plugins/MobileProfile/mp-screen.css +++ b/plugins/MobileProfile/mp-screen.css @@ -176,8 +176,18 @@ margin-bottom:0; .profile { padding-top:4px; padding-bottom:4px; +min-height:65px; } -.notice div.entry-content { +#content .notice .entry-title { +float:left; +width:100%; +margin-left:0; +} +#content .notice .author .photo { +position:static; +float:left; +} +#content .notice div.entry-content { margin-left:0; width:75%; max-width:100%; diff --git a/theme/base/css/display.css b/theme/base/css/display.css index fbf3b6a5b9..84e9426c77 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -1012,6 +1012,16 @@ float:left; #shownotice .vcard .photo { margin-bottom:4px; } +#content .notice .author .photo { +position:absolute; +top:11px; +left:0; +float:none; +} +#content .notice .entry-title { +margin-left:59px; +} + .vcard .url { text-decoration:none; } @@ -1020,13 +1030,19 @@ text-decoration:underline; } .notice .entry-title { -float:left; -width:100%; overflow:hidden; } .notice .entry-title.ov { overflow:visible; } +#showstream .notice .entry-title, +#showstream .notice div.entry-content { +margin-left:0; +} +#shownotice .notice .entry-title, +#shownotice .notice div.entry-content { +margin-left:110px; +} #shownotice .notice .entry-title { font-size:2.2em; } @@ -1056,7 +1072,6 @@ max-width:70%; } #showstream .notice div.entry-content, #shownotice .notice div.entry-content { -margin-left:0; max-width:79%; } @@ -1120,6 +1135,7 @@ position:relative; font-size:0.95em; width:113px; float:right; +margin-top:3px; margin-right:4px; } From 6815ddafe011d534e7d6e16972833e120c36e4e3 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Wed, 20 Jan 2010 18:50:48 +0100 Subject: [PATCH 15/53] Better alignment for notice options in MobileProfile --- plugins/MobileProfile/mp-screen.css | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/plugins/MobileProfile/mp-screen.css b/plugins/MobileProfile/mp-screen.css index 76071352d0..04fa5fb002 100644 --- a/plugins/MobileProfile/mp-screen.css +++ b/plugins/MobileProfile/mp-screen.css @@ -194,7 +194,7 @@ max-width:100%; min-width:0; } .notice-options { -width:50px; +width:43px; margin-right:1%; } @@ -202,6 +202,13 @@ margin-right:1%; width:16px; height:16px; } +.notice-options form.processing { +background-image:none; +} +#wrap .notice-options form.processing input.submit { +background-position:0 47%; +} + .notice .notice-options a, .notice .notice-options input { box-shadow:none; @@ -212,16 +219,16 @@ box-shadow:none; .notice .notice-options form { margin:-4px 0 0 0; } -.notice .notice-options .notice_repeat, +.notice .notice-options .form_repeat, .notice .notice-options .notice_delete { -margin-top:18px; +margin-top:11px; } -.notice .notice-options .notice_reply, -.notice .notice-options .notice_repeat { -margin-left:18px; +.notice .notice-options .form_favor, +.notice .notice-options .form_disfavor, +.notice .notice-options .form_repeat { +margin-right:11px; } - .notice .notice-options .notice_delete { float:left; } From dbccebb14bbc46ea0e53e5bd0e3681c77692a40a Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 20 Jan 2010 15:43:24 -0500 Subject: [PATCH 16/53] update friends, not user, timeline for recipients of notice in PuSH plugin --- plugins/PubSubHubBub/PubSubHubBubPlugin.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/PubSubHubBub/PubSubHubBubPlugin.php b/plugins/PubSubHubBub/PubSubHubBubPlugin.php index 367b354034..d3ff3882fc 100644 --- a/plugins/PubSubHubBub/PubSubHubBubPlugin.php +++ b/plugins/PubSubHubBub/PubSubHubBubPlugin.php @@ -103,8 +103,8 @@ class PubSubHubBubPlugin extends Plugin if (empty($user)) { continue; } - $feeds[]=common_local_url('ApiTimelineUser',array('id' => $user->nickname, 'format'=>'rss')); - $feeds[]=common_local_url('ApiTimelineUser',array('id' => $user->nickname, 'format'=>'atom')); + $feeds[]=common_local_url('ApiTimelineFriends', array('id' => $user->nickname, 'format'=>'rss')); + $feeds[]=common_local_url('ApiTimelineFriends', array('id' => $user->nickname, 'format'=>'atom')); } //feed of user replied to From 7679f058efc43137519167f0e862f89475d43d6f Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 20 Jan 2010 15:56:24 -0500 Subject: [PATCH 17/53] Revert "DEBUG HACK: error checking for xml_parse in XMPPHP input stream" This reverts commit 906450e2f5b78a1c6f2dec2e21b9b5841df210f4. 1) It was a quick debug hack 2) it doesn't meet the requirements for changing extlib/ libraries --- extlib/XMPPHP/XMLStream.php | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/extlib/XMPPHP/XMLStream.php b/extlib/XMPPHP/XMLStream.php index dbc4719e42..d33411ec54 100644 --- a/extlib/XMPPHP/XMLStream.php +++ b/extlib/XMPPHP/XMLStream.php @@ -417,12 +417,7 @@ class XMPPHP_XMLStream { } } $this->log->log("RECV: $buff", XMPPHP_Log::LEVEL_VERBOSE); - $ok = xml_parse($this->parser, $buff, false); - if (!$ok) { - $errcode = xml_get_error_code($this->parser); - $errstr = xml_error_string($errcode); - $this->log->log("XML ERROR: $errstr", XMPPHP_Log::LEVEL_VERBOSE); - } + xml_parse($this->parser, $buff, false); } else { # $updated == 0 means no changes during timeout. } @@ -676,12 +671,7 @@ class XMPPHP_XMLStream { } } $this->log->log("RECV: $buff", XMPPHP_Log::LEVEL_VERBOSE); - $ok = xml_parse($this->parser, $buff, false); - if (!$ok) { - $errcode = xml_get_error_code($this->parser); - $errstr = xml_error_string($errcode); - $this->log->log("XML ERROR: $errstr", XMPPHP_Log::LEVEL_VERBOSE); - } + xml_parse($this->parser, $buff, false); } /** From 365b0b1e14a34ed433ac169d5cfb6066f11919ba Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 20 Jan 2010 16:13:52 -0500 Subject: [PATCH 18/53] use standard plugin configuration for PubSubHubBub --- plugins/PubSubHubBub/PubSubHubBubPlugin.php | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/plugins/PubSubHubBub/PubSubHubBubPlugin.php b/plugins/PubSubHubBub/PubSubHubBubPlugin.php index d3ff3882fc..f134086290 100644 --- a/plugins/PubSubHubBub/PubSubHubBubPlugin.php +++ b/plugins/PubSubHubBub/PubSubHubBubPlugin.php @@ -37,20 +37,13 @@ require_once(INSTALLDIR.'/plugins/PubSubHubBub/publisher.php'); class PubSubHubBubPlugin extends Plugin { - private $hub; + public $hub = DEFAULT_HUB; function __construct() { parent::__construct(); } - function onInitializePlugin(){ - $this->hub = common_config('PubSubHubBub', 'hub'); - if(empty($this->hub)){ - $this->hub = DEFAULT_HUB; - } - } - function onStartApiAtom($action){ $action->element('link',array('rel'=>'hub','href'=>$this->hub),null); } From 1d37a6c428ac2d89b0fa01f73a9e6e05a412b605 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 20 Jan 2010 16:16:22 -0500 Subject: [PATCH 19/53] correctly get replies for a notice in PuSH plugin --- plugins/PubSubHubBub/PubSubHubBubPlugin.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/plugins/PubSubHubBub/PubSubHubBubPlugin.php b/plugins/PubSubHubBub/PubSubHubBubPlugin.php index f134086290..96500404bc 100644 --- a/plugins/PubSubHubBub/PubSubHubBubPlugin.php +++ b/plugins/PubSubHubBub/PubSubHubBubPlugin.php @@ -100,11 +100,15 @@ class PubSubHubBubPlugin extends Plugin $feeds[]=common_local_url('ApiTimelineFriends', array('id' => $user->nickname, 'format'=>'atom')); } + $replies = $notice->getReplies(); + //feed of user replied to - if($notice->reply_to){ - $user = User::staticGet('id',$notice->reply_to); + foreach ($replies as $recipient) { + $user = User::staticGet('id',$recipient); + if (!empty($user)) { $feeds[]=common_local_url('ApiTimelineMentions',array('id' => $user->nickname,'format'=>'rss')); $feeds[]=common_local_url('ApiTimelineMentions',array('id' => $user->nickname,'format'=>'atom')); + } } foreach(array_unique($feeds) as $feed){ From 0167ff6d2702f90c46aa311a6a7ca17db222780f Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 20 Jan 2010 16:29:11 -0500 Subject: [PATCH 20/53] whitespace changes to make phpcs happy for PuSH plugin --- plugins/PubSubHubBub/PubSubHubBubPlugin.php | 89 ++++++++++++++------- 1 file changed, 62 insertions(+), 27 deletions(-) diff --git a/plugins/PubSubHubBub/PubSubHubBubPlugin.php b/plugins/PubSubHubBub/PubSubHubBubPlugin.php index 96500404bc..c4af2c854b 100644 --- a/plugins/PubSubHubBub/PubSubHubBubPlugin.php +++ b/plugins/PubSubHubBub/PubSubHubBubPlugin.php @@ -31,9 +31,9 @@ if (!defined('STATUSNET')) { exit(1); } -define('DEFAULT_HUB','http://pubsubhubbub.appspot.com'); +define('DEFAULT_HUB', 'http://pubsubhubbub.appspot.com'); -require_once(INSTALLDIR.'/plugins/PubSubHubBub/publisher.php'); +require_once INSTALLDIR.'/plugins/PubSubHubBub/publisher.php'; class PubSubHubBubPlugin extends Plugin { @@ -44,46 +44,67 @@ class PubSubHubBubPlugin extends Plugin parent::__construct(); } - function onStartApiAtom($action){ - $action->element('link',array('rel'=>'hub','href'=>$this->hub),null); + function onStartApiAtom($action) + { + $action->element('link', array('rel' => 'hub', 'href' => $this->hub), null); } - function onStartApiRss($action){ - $action->element('atom:link',array('rel'=>'hub','href'=>$this->hub),null); + function onStartApiRss($action) + { + $action->element('atom:link', array('rel' => 'hub', + 'href' => $this->hub), + null); } - function onHandleQueuedNotice($notice){ + function onHandleQueuedNotice($notice) + { $publisher = new Publisher($this->hub); $feeds = array(); //public timeline feeds - $feeds[]=common_local_url('ApiTimelinePublic',array('format' => 'rss')); - $feeds[]=common_local_url('ApiTimelinePublic',array('format' => 'atom')); + $feeds[] = common_local_url('ApiTimelinePublic', array('format' => 'rss')); + $feeds[] = common_local_url('ApiTimelinePublic', array('format' => 'atom')); //author's own feeds - $user = User::staticGet('id',$notice->profile_id); - $feeds[]=common_local_url('ApiTimelineUser',array('id' => $user->nickname, 'format'=>'rss')); - $feeds[]=common_local_url('ApiTimelineUser',array('id' => $user->nickname, 'format'=>'atom')); + $user = User::staticGet('id', $notice->profile_id); + + $feeds[] = common_local_url('ApiTimelineUser', + array('id' => $user->nickname, + 'format' => 'rss')); + $feeds[] = common_local_url('ApiTimelineUser', + array('id' => $user->nickname, + 'format' => 'atom')); //tag feeds $tag = new Notice_tag(); + $tag->notice_id = $notice->id; if ($tag->find()) { while ($tag->fetch()) { - $feeds[]=common_local_url('ApiTimelineTag',array('tag'=>$tag->tag, 'format'=>'rss')); - $feeds[]=common_local_url('ApiTimelineTag',array('tag'=>$tag->tag, 'format'=>'atom')); + $feeds[] = common_local_url('ApiTimelineTag', + array('tag' => $tag->tag, + 'format' => 'rss')); + $feeds[] = common_local_url('ApiTimelineTag', + array('tag' => $tag->tag, + 'format' => 'atom')); } } //group feeds $group_inbox = new Group_inbox(); + $group_inbox->notice_id = $notice->id; if ($group_inbox->find()) { while ($group_inbox->fetch()) { - $group = User_group::staticGet('id',$group_inbox->group_id); - $feeds[]=common_local_url('ApiTimelineGroup',array('id' => $group->nickname,'format'=>'rss')); - $feeds[]=common_local_url('ApiTimelineGroup',array('id' => $group->nickname,'format'=>'atom')); + $group = User_group::staticGet('id', $group_inbox->group_id); + + $feeds[] = common_local_url('ApiTimelineGroup', + array('id' => $group->nickname, + 'format' => 'rss')); + $feeds[] = common_local_url('ApiTimelineGroup', + array('id' => $group->nickname, + 'format' => 'atom')); } } @@ -96,24 +117,34 @@ class PubSubHubBubPlugin extends Plugin if (empty($user)) { continue; } - $feeds[]=common_local_url('ApiTimelineFriends', array('id' => $user->nickname, 'format'=>'rss')); - $feeds[]=common_local_url('ApiTimelineFriends', array('id' => $user->nickname, 'format'=>'atom')); + $feeds[] = common_local_url('ApiTimelineFriends', + array('id' => $user->nickname, + 'format' => 'rss')); + $feeds[] = common_local_url('ApiTimelineFriends', + array('id' => $user->nickname, + 'format' => 'atom')); } $replies = $notice->getReplies(); //feed of user replied to foreach ($replies as $recipient) { - $user = User::staticGet('id',$recipient); + $user = User::staticGet('id', $recipient); if (!empty($user)) { - $feeds[]=common_local_url('ApiTimelineMentions',array('id' => $user->nickname,'format'=>'rss')); - $feeds[]=common_local_url('ApiTimelineMentions',array('id' => $user->nickname,'format'=>'atom')); + $feeds[] = common_local_url('ApiTimelineMentions', + array('id' => $user->nickname, + 'format' => 'rss')); + $feeds[] = common_local_url('ApiTimelineMentions', + array('id' => $user->nickname, + 'format' => 'atom')); } } - foreach(array_unique($feeds) as $feed){ - if(! $publisher->publish_update($feed)){ - common_log_line(LOG_WARNING,$feed.' was not published to hub at '.$this->hub.':'.$publisher->last_response()); + foreach (array_unique($feeds) as $feed) { + if (!$publisher->publish_update($feed)) { + common_log_line(LOG_WARNING, + $feed.' was not published to hub at '. + $this->hub.':'.$publisher->last_response()); } } } @@ -123,9 +154,13 @@ class PubSubHubBubPlugin extends Plugin $versions[] = array('name' => 'PubSubHubBub', 'version' => STATUSNET_VERSION, 'author' => 'Craig Andrews', - 'homepage' => 'http://status.net/wiki/Plugin:PubSubHubBub', + 'homepage' => + 'http://status.net/wiki/Plugin:PubSubHubBub', 'rawdescription' => - _m('The PubSubHubBub plugin pushes RSS/Atom updates to a PubSubHubBub hub.')); + _m('The PubSubHubBub plugin pushes RSS/Atom updates '. + 'to a PubSubHubBub hub.')); return true; } From 10f21e1f414dfd9a369df8b1c71aa2e099fca9f2 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 20 Jan 2010 16:37:41 -0500 Subject: [PATCH 21/53] add class and function doc comments to PuSH plugin --- plugins/PubSubHubBub/PubSubHubBubPlugin.php | 85 +++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/plugins/PubSubHubBub/PubSubHubBubPlugin.php b/plugins/PubSubHubBub/PubSubHubBubPlugin.php index c4af2c854b..8286cd5489 100644 --- a/plugins/PubSubHubBub/PubSubHubBubPlugin.php +++ b/plugins/PubSubHubBub/PubSubHubBubPlugin.php @@ -35,27 +35,99 @@ define('DEFAULT_HUB', 'http://pubsubhubbub.appspot.com'); require_once INSTALLDIR.'/plugins/PubSubHubBub/publisher.php'; +/** + * Plugin to provide publisher side of PubSubHubBub (PuSH) + * relationship. + * + * PuSH is a real-time or near-real-time protocol for Atom + * and RSS feeds. More information here: + * + * http://code.google.com/p/pubsubhubbub/ + * + * To enable, add the following line to your config.php: + * + * addPlugin('PubSubHubBub'); + * + * This will use the Google default hub. If you'd like to use + * another, try: + * + * addPlugin('PubSubHubBub', + * array('hub' => 'http://yourhub.example.net/')); + * + * @category Plugin + * @package StatusNet + * @author Craig Andrews + * @copyright 2009 Craig Andrews http://candrews.integralblue.com + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3 + * @link http://status.net/ + */ + class PubSubHubBubPlugin extends Plugin { + /** + * URL of the hub to advertise and publish to. + */ + public $hub = DEFAULT_HUB; + /** + * Default constructor. + */ + function __construct() { parent::__construct(); } + /** + * Hooks the StartApiAtom event + * + * Adds the necessary bits to advertise PubSubHubBub + * for the Atom feed. + * + * @param Action $action The API action being shown. + * + * @return boolean hook value + */ + function onStartApiAtom($action) { $action->element('link', array('rel' => 'hub', 'href' => $this->hub), null); + + return true; } + /** + * Hooks the StartApiRss event + * + * Adds the necessary bits to advertise PubSubHubBub + * for the RSS 2.0 feeds. + * + * @param Action $action The API action being shown. + * + * @return boolean hook value + */ + function onStartApiRss($action) { $action->element('atom:link', array('rel' => 'hub', 'href' => $this->hub), null); + return true; } + /** + * Hook for a queued notice. + * + * When a notice has been queued, will ping the + * PuSH hub for each Atom and RSS feed in which + * the notice appears. + * + * @param Notice $notice The notice that's been queued + * + * @return boolean hook value + */ + function onHandleQueuedNotice($notice) { $publisher = new Publisher($this->hub); @@ -147,8 +219,21 @@ class PubSubHubBubPlugin extends Plugin $this->hub.':'.$publisher->last_response()); } } + + return true; } + /** + * Provide version information + * + * Adds this plugin's version data to the global + * version array, for e.g. displaying on the version page. + * + * @param array &$versions array of array of versions + * + * @return boolean hook value + */ + function onPluginVersion(&$versions) { $versions[] = array('name' => 'PubSubHubBub', From 9e3013c6b613528eac4ace08524360330910801e Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 20 Jan 2010 17:00:42 -0500 Subject: [PATCH 22/53] mark retweet api actions read-only where applicable --- actions/apistatusesretweets.php | 15 +++++++++++++++ actions/apitimelineretweetedbyme.php | 15 +++++++++++++++ actions/apitimelineretweetedtome.php | 15 +++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/actions/apistatusesretweets.php b/actions/apistatusesretweets.php index f7a3dd60a0..81744c2b4a 100644 --- a/actions/apistatusesretweets.php +++ b/actions/apistatusesretweets.php @@ -113,4 +113,19 @@ class ApiStatusesRetweetsAction extends ApiAuthAction break; } } + + /** + * Return true if read only. + * + * MAY override + * + * @param array $args other arguments + * + * @return boolean is read only action? + */ + + function isReadOnly($args) + { + return false; + } } diff --git a/actions/apitimelineretweetedbyme.php b/actions/apitimelineretweetedbyme.php index 88652c3fdc..7958dab374 100644 --- a/actions/apitimelineretweetedbyme.php +++ b/actions/apitimelineretweetedbyme.php @@ -123,4 +123,19 @@ class ApiTimelineRetweetedByMeAction extends ApiAuthAction break; } } + + /** + * Return true if read only. + * + * MAY override + * + * @param array $args other arguments + * + * @return boolean is read only action? + */ + + function isReadOnly($args) + { + return false; + } } diff --git a/actions/apitimelineretweetedtome.php b/actions/apitimelineretweetedtome.php index 113ab96d2c..66f06cc0ec 100644 --- a/actions/apitimelineretweetedtome.php +++ b/actions/apitimelineretweetedtome.php @@ -122,4 +122,19 @@ class ApiTimelineRetweetedToMeAction extends ApiAuthAction break; } } + + /** + * Return true if read only. + * + * MAY override + * + * @param array $args other arguments + * + * @return boolean is read only action? + */ + + function isReadOnly($args) + { + return false; + } } From 4175ec7c6eeb0a5308341327e0e768a6489320e8 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 20 Jan 2010 17:49:13 -0500 Subject: [PATCH 23/53] update changes in README --- README | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/README b/README index 386b3264a2..6022887899 100644 --- a/README +++ b/README @@ -2,8 +2,8 @@ README ------ -StatusNet 0.9.0 ("Stand") Release Candidate 2 -22 Dec 2009 +StatusNet 0.9.0 ("Stand") Beta 3 +20 Jan 2010 This is the README file for StatusNet (formerly Laconica), the Open Source microblogging platform. It includes installation instructions, @@ -167,6 +167,37 @@ Notable changes this version: - Add support for "repeats" (similar to Twitter's "retweets"). - Support for repeats in Twitter API. - Better notification of direct messages. +- New plugin to add "powered by StatusNet" to logo. +- Returnto works for private sites. +- Localisation updates, including new Persian translation. +- CAS authentication plugin +- Get rid of DB_DataObject native cache (big memory leaker) +- setconfig.php script to set configuration variables +- Blacklist plugin, to blacklist URLs and nicknames +- Users can set flag whether they want to share location + both in notice form (for one notice) and profile settings + (any notice) +- notice inboxes moved from normalized notice_inbox table to + denormalized inbox table +- Automatic compression of Memcache +- Memory caching pluginized +- Memcache, XCache, APC and Diskcache plugins +- A script to update user locations +- cache empty query results +- A sample plugin to show best plugin practices +- CacheLog plugin to debug cache accesses +- Require users to login to view attachments on private sites +- Plugin to use Mollom spam detection service +- Plugin for RSSCloud +- Add an array of default plugins +- A version action to give credit to contributors and plugin + developers +- Daemon to read IMAP mailbox instead of using a mailbox script +- Pass session information between SSL and non-SSL server + when SSL set to 'sometimes' +- Major refactoring of queue handlers to manage very + large hosting site (like status.net) +- SubscriptionThrottle plugin to prevent subscription spamming Prerequisites ============= From c63832f7bf3ddde0f66fb36a3ace638d50b4b3d6 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 20 Jan 2010 17:58:23 -0500 Subject: [PATCH 24/53] add PubSubHubBub and RSSCloud to list of default plugins --- lib/default.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/default.php b/lib/default.php index 1c3c5e7ffb..ceae0efaae 100644 --- a/lib/default.php +++ b/lib/default.php @@ -251,6 +251,8 @@ $default = 'Mapstraction' => null, 'Linkback' => null, 'WikiHashtags' => null, + 'PubSubHubBub' => null, + 'RSSCloud' => null, 'OpenID' => null), ), 'admin' => From 05156b708a16c5a20d4081242c398e667792de15 Mon Sep 17 00:00:00 2001 From: Michele Date: Sun, 17 Jan 2010 11:21:07 +0100 Subject: [PATCH 25/53] HTTP auth provided is evaluated even if it's not required --- lib/apiauth.php | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/lib/apiauth.php b/lib/apiauth.php index 691db584b7..b4292408a1 100644 --- a/lib/apiauth.php +++ b/lib/apiauth.php @@ -79,10 +79,13 @@ class ApiAuthAction extends ApiAction $this->checkOAuthRequest(); } else { $this->checkBasicAuthUser(); - // By default, all basic auth users have read and write access - - $this->access = self::READ_WRITE; } + } else { + + // Check to see if a basic auth user is there even + // if one's not required + + $this->checkBasicAuthUser(false); } return true; @@ -198,13 +201,13 @@ class ApiAuthAction extends ApiAction * @return boolean true or false */ - function checkBasicAuthUser() + function checkBasicAuthUser($required = true) { $this->basicAuthProcessHeader(); $realm = common_config('site', 'name') . ' API'; - if (!isset($this->auth_user)) { + if (!isset($this->auth_user) && $required) { header('WWW-Authenticate: Basic realm="' . $realm . '"'); // show error if the user clicks 'cancel' @@ -212,12 +215,16 @@ class ApiAuthAction extends ApiAction $this->showBasicAuthError(); exit; - } else { + } else if (isset($this->auth_user)) { $nickname = $this->auth_user; $password = $this->auth_pw; $user = common_check_user($nickname, $password); if (Event::handle('StartSetApiUser', array(&$user))) { $this->auth_user = $user; + + // By default, all basic auth users have read and write access + $this->access = self::READ_WRITE; + Event::handle('EndSetApiUser', array($user)); } From fd276ff9e7a1292a217ddb144d600d04bc473d03 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 20 Jan 2010 18:01:07 -0800 Subject: [PATCH 26/53] Add Start/EndSetApiUser events when setting API user via OAuth --- lib/apiauth.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/apiauth.php b/lib/apiauth.php index b4292408a1..927dcad6af 100644 --- a/lib/apiauth.php +++ b/lib/apiauth.php @@ -148,7 +148,10 @@ class ApiAuthAction extends ApiAction $this->access = ($appUser->access_type & Oauth_application::$writeAccess) ? self::READ_WRITE : self::READ_ONLY; - $this->auth_user = User::staticGet('id', $appUser->profile_id); + if (Event::handle('StartSetApiUser', array(&$user))) { + $this->auth_user = User::staticGet('id', $appUser->profile_id); + Event::handle('EndSetApiUser', array($user)); + } $msg = "API OAuth authentication for user '%s' (id: %d) on behalf of " . "application '%s' (id: %d)."; From d4fcc8777f5655d0be678075a9bc38e8c02afbc8 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 21 Jan 2010 13:23:04 +0100 Subject: [PATCH 27/53] Removed mobile stylesheet from core output. If Mobile support is seeked, MobileProfile plugin should be used. --- lib/action.php | 4 - theme/base/css/mobile.css | 150 -------------------------------------- 2 files changed, 154 deletions(-) delete mode 100644 theme/base/css/mobile.css diff --git a/lib/action.php b/lib/action.php index 171bea17c7..e9207a66a6 100644 --- a/lib/action.php +++ b/lib/action.php @@ -199,10 +199,6 @@ class Action extends HTMLOutputter // lawsuit if (Event::handle('StartShowStatusNetStyles', array($this)) && Event::handle('StartShowLaconicaStyles', array($this))) { $this->cssLink('css/display.css',null,'screen, projection, tv'); - if (common_config('site', 'mobile')) { - // TODO: "handheld" CSS for other mobile devices - $this->cssLink('css/mobile.css','base','only screen and (max-device-width: 480px)'); // Mobile WebKit - } $this->cssLink('css/print.css','base','print'); Event::handle('EndShowStatusNetStyles', array($this)); Event::handle('EndShowLaconicaStyles', array($this)); diff --git a/theme/base/css/mobile.css b/theme/base/css/mobile.css deleted file mode 100644 index f6c53ea8dc..0000000000 --- a/theme/base/css/mobile.css +++ /dev/null @@ -1,150 +0,0 @@ -/** theme: base - * - * @package StatusNet - * @author Meitar Moscovitz - * @author Sarven Capadisli - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://status.net/ - */ - -body { -font-size:2.5em; -} - -#wrap { -width:95%; -} - -#header, -#header address, -#anon_notice, -#site_nav_local_views .nav, -#form_notice, -#form_notice .form_data li, -#core, -#content_inner, -#notices_primary, -.notice, -.notice .entry-title, -.notice div.entry-content, -.notice-options, -.notice .notice-options a, -.pagination, -.pagination .nav, -.aside .section { -float:none; -} - -.notice-options .notice_reply, -.notice-options .notice_delete, -.notice-options .form_favor, -.notice-options .form_disfavor { -position:static; -} - -#form_notice, -#anon_notice, -#footer, -#form_notice .form_actions input.submit { -width:auto; -} - -.form_settings label { -width:25%; -} -.form_settings .form_data p.form_guide { -margin-left:26%; -} - -#site_nav_global_primary { -width:75%; -} - -.entity_profile { -width:65%; -} -.entity_actions { -margin-left:0; -} - -#form_notice, -#anon_notice { -clear:both; -} - -#content, -#aside_primary { -width:96%; -padding-left:2%; -padding-right:2%; -} - -#site_notice { -position:static; -float:right; -clear:right; -width:75%; -margin-right:0; -margin-bottom:11px; -} - -.notices { -font-size:1.5em; -} - -#form_notice textarea { -width:80%; -height:5em; -} -#form_notice .form_note { -right:20%; -top:6em; -} - - -.vcard .photo, -.section .vcard .photo { -margin-right:18px; -} -.notice, -.profile { -margin-bottom:18px; -} - -.notices .entry-title, -.notices div.entry-content { -width:90%; -} -.notice div.entry-content { -margin-left:0; -} - -.notice .author .photo { -height:4.5em; -width:4.5em; -} -.notice-options { -position:absolute; -top:0; -right:0; -padding-left:7%; -width:3%; -} - -.notice-options .notice_delete a { -float:left; -} -.pagination .nav { -overflow:auto; -} - -#export_data { -display:none; -} - -#site_nav_local_views li { -margin-right:4px; -} -#site_nav_local_views a { -padding:18px 11px; -} From 373206ac0042c37624844fb738ff869fa7190041 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Thu, 21 Jan 2010 16:49:49 +0100 Subject: [PATCH 28/53] Event hooks for before and after site_notice --- EVENTS.txt | 6 ++++++ lib/action.php | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/EVENTS.txt b/EVENTS.txt index 6e6afa070f..1ed670697b 100644 --- a/EVENTS.txt +++ b/EVENTS.txt @@ -150,6 +150,12 @@ StartAddressData: Allows the site owner to provide additional information about EndAddressData: At the end of
- $action: the current action +StartShowSiteNotice: Before showing site notice +- $action: the current action + +EndShowSiteNotice: After showing site notice +- $action: the current action + StartLoginGroupNav: Before showing the login and register navigation menu - $action: the current action diff --git a/lib/action.php b/lib/action.php index e9207a66a6..e242775585 100644 --- a/lib/action.php +++ b/lib/action.php @@ -369,7 +369,11 @@ class Action extends HTMLOutputter // lawsuit $this->elementStart('div', array('id' => 'header')); $this->showLogo(); $this->showPrimaryNav(); - $this->showSiteNotice(); + if (Event::handle('StartShowSiteNotice', array($this))) { + $this->showSiteNotice(); + + Event::handle('EndShowSiteNotice', array($this)); + } if (common_logged_in()) { $this->showNoticeForm(); } else { From e5eb95ab59598392bfae99adac1ac0716397ba13 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 21 Jan 2010 11:32:01 -0500 Subject: [PATCH 29/53] retweet API methods are readonly --- actions/apistatusesretweets.php | 2 +- actions/apitimelineretweetedbyme.php | 2 +- actions/apitimelineretweetedtome.php | 2 +- actions/apitimelineretweetsofme.php | 15 +++++++++++++++ 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/actions/apistatusesretweets.php b/actions/apistatusesretweets.php index 81744c2b4a..a79d43168e 100644 --- a/actions/apistatusesretweets.php +++ b/actions/apistatusesretweets.php @@ -126,6 +126,6 @@ class ApiStatusesRetweetsAction extends ApiAuthAction function isReadOnly($args) { - return false; + return true; } } diff --git a/actions/apitimelineretweetedbyme.php b/actions/apitimelineretweetedbyme.php index 7958dab374..54d32e5fa2 100644 --- a/actions/apitimelineretweetedbyme.php +++ b/actions/apitimelineretweetedbyme.php @@ -136,6 +136,6 @@ class ApiTimelineRetweetedByMeAction extends ApiAuthAction function isReadOnly($args) { - return false; + return true; } } diff --git a/actions/apitimelineretweetedtome.php b/actions/apitimelineretweetedtome.php index 66f06cc0ec..e47bc30b85 100644 --- a/actions/apitimelineretweetedtome.php +++ b/actions/apitimelineretweetedtome.php @@ -135,6 +135,6 @@ class ApiTimelineRetweetedToMeAction extends ApiAuthAction function isReadOnly($args) { - return false; + return true; } } diff --git a/actions/apitimelineretweetsofme.php b/actions/apitimelineretweetsofme.php index 6ca2c779cb..e4b09e9bda 100644 --- a/actions/apitimelineretweetsofme.php +++ b/actions/apitimelineretweetsofme.php @@ -123,4 +123,19 @@ class ApiTimelineRetweetsOfMeAction extends ApiAuthAction break; } } + + /** + * Return true if read only. + * + * MAY override + * + * @param array $args other arguments + * + * @return boolean is read only action? + */ + + function isReadOnly($args) + { + return true; + } } From 1d64ba6602f7ccd4c049167355445ca3600c28e6 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 21 Jan 2010 11:38:08 -0500 Subject: [PATCH 30/53] Unimplement retweeted_by_me API action until we have a more efficient query --- actions/apitimelineretweetedbyme.php | 56 +--------------------------- 1 file changed, 2 insertions(+), 54 deletions(-) diff --git a/actions/apitimelineretweetedbyme.php b/actions/apitimelineretweetedbyme.php index 54d32e5fa2..564e98619a 100644 --- a/actions/apitimelineretweetedbyme.php +++ b/actions/apitimelineretweetedbyme.php @@ -69,66 +69,14 @@ class ApiTimelineRetweetedByMeAction extends ApiAuthAction { parent::prepare($args); - $cnt = $this->int('count', self::DEFAULTCOUNT, self::MAXCOUNT, 1); + $this->serverError('Unimplemented', 503); - $page = $this->int('page', 1, (self::MAXNOTICES/$this->cnt)); - - $since_id = $this->int('since_id'); - - $max_id = $this->int('max_id'); - - return true; - } - - /** - * Handle the request - * - * show a timeline of the user's repeated notices - * - * @param array $args $_REQUEST data (unused) - * - * @return void - */ - - function handle($args) - { - parent::handle($args); - - $offset = ($this->page-1) * $this->cnt; - $limit = $this->cnt; - - $strm = $this->auth_user->repeatedByMe($offset, $limit, $this->since_id, $this->max_id); - - switch ($this->format) { - case 'xml': - $this->showXmlTimeline($strm); - break; - case 'json': - $this->showJsonTimeline($strm); - break; - case 'atom': - $profile = $this->auth_user->getProfile(); - - $title = sprintf(_("Repeated by %s"), $this->auth_user->nickname); - $taguribase = common_config('integration', 'taguri'); - $id = "tag:$taguribase:RepeatedByMe:" . $this->auth_user->id; - $link = common_local_url('showstream', - array('nickname' => $this->auth_user->nickname)); - - $this->showAtomTimeline($strm, $title, $id, $link); - break; - - default: - $this->clientError(_('API method not found.'), $code = 404); - break; - } + return false; } /** * Return true if read only. * - * MAY override - * * @param array $args other arguments * * @return boolean is read only action? From 383703d170c59baf0cae32b612e04b4d292d1880 Mon Sep 17 00:00:00 2001 From: Michele Date: Thu, 21 Jan 2010 19:30:12 +0100 Subject: [PATCH 31/53] if the id is an alias we redirect using group_id --- actions/apigroupshow.php | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/actions/apigroupshow.php b/actions/apigroupshow.php index 7aa49b1bf3..8524281444 100644 --- a/actions/apigroupshow.php +++ b/actions/apigroupshow.php @@ -85,12 +85,18 @@ class ApiGroupShowAction extends ApiPrivateAuthAction { parent::handle($args); - if (empty($this->group)) { - $this->clientError( - _('Group not found!'), - 404, - $this->format - ); + if (!$this->group) { + $alias = Group_alias::staticGet('alias', common_canonical_nickname($this->arg('id'))); + if ($alias) { + $args = array('id' => $alias->group_id, 'format'=>$this->format); + common_redirect(common_local_url('ApiGroupShow', $args), 301); + } else { + $this->clientError( + _('Group not found!'), + 404, + $this->format + ); + } return; } From 8dafe09ab25335c26e33548e988828a72e984239 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Thu, 21 Jan 2010 11:07:52 -0800 Subject: [PATCH 32/53] Option to log slow db queries or all db queries $config['db']['log_queries'] = true; // all $config['db']['log_slow_queries'] = 10; // queries taking > 10 seconds --- classes/Memcached_DataObject.php | 33 ++++++++++++++++++++++++++++++++ lib/default.php | 4 +++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/classes/Memcached_DataObject.php b/classes/Memcached_DataObject.php index 4ecab9db62..6ceb59e8b4 100644 --- a/classes/Memcached_DataObject.php +++ b/classes/Memcached_DataObject.php @@ -315,6 +315,39 @@ class Memcached_DataObject extends DB_DataObject return new ArrayWrapper($cached); } + /** + * sends query to database - this is the private one that must work + * - internal functions use this rather than $this->query() + * + * Overridden to do logging. + * + * @param string $string + * @access private + * @return mixed none or PEAR_Error + */ + function _query($string) + { + $start = microtime(true); + $result = parent::_query($string); + $delta = microtime(true) - $start; + + $limit = common_config('db', 'log_slow_queries'); + if (($limit > 0 && $delta >= $limit) || common_config('db', 'log_queries')) { + $clean = $this->sanitizeQuery($string); + common_log(LOG_DEBUG, sprintf("DB query (%0.3fs): %s", $delta, $clean)); + } + return $result; + } + + // Sanitize a query for logging + // @fixme don't trim spaces in string literals + function sanitizeQuery($string) + { + $string = preg_replace('/\s+/', ' ', $string); + $string = trim($string); + return $string; + } + // We overload so that 'SET NAMES "utf8"' is called for // each connection diff --git a/lib/default.php b/lib/default.php index 5b2ae6c7c1..fc6b4ab79c 100644 --- a/lib/default.php +++ b/lib/default.php @@ -67,7 +67,9 @@ $default = 'db_driver' => 'DB', # XXX: JanRain libs only work with DB 'quote_identifiers' => false, 'type' => 'mysql', - 'schemacheck' => 'runtime'), // 'runtime' or 'script' + 'schemacheck' => 'runtime', // 'runtime' or 'script' + 'log_queries' => false, // true to log all DB queries + 'log_slow_queries' => 0), // if set, log queries taking over N seconds 'syslog' => array('appname' => 'statusnet', # for syslog 'priority' => 'debug', # XXX: currently ignored From 308442407ee7814a7691a4d364068b995b28aef3 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 21 Jan 2010 11:37:20 -0800 Subject: [PATCH 33/53] - Moved checking for group aliases and redirection to prepare() - phpcs cleanup - add @macno to the list of authors --- actions/apigroupshow.php | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/actions/apigroupshow.php b/actions/apigroupshow.php index 8524281444..ef9cbf0e75 100644 --- a/actions/apigroupshow.php +++ b/actions/apigroupshow.php @@ -45,6 +45,7 @@ require_once INSTALLDIR . '/lib/apiprivateauth.php'; * @author Evan Prodromou * @author Jeffery To * @author Zach Copley + * @author Michele * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ */ @@ -68,6 +69,24 @@ class ApiGroupShowAction extends ApiPrivateAuthAction $this->group = $this->getTargetGroup($this->arg('id')); + if (empty($this->group)) { + $alias = Group_alias::staticGet( + 'alias', + common_canonical_nickname($this->arg('id')) + ); + if (!empty($alias)) { + $args = array('id' => $alias->group_id, 'format' => $this->format); + common_redirect(common_local_url('ApiGroupShow', $args), 301); + } else { + $this->clientError( + _('Group not found!'), + 404, + $this->format + ); + } + return; + } + return true; } @@ -85,21 +104,6 @@ class ApiGroupShowAction extends ApiPrivateAuthAction { parent::handle($args); - if (!$this->group) { - $alias = Group_alias::staticGet('alias', common_canonical_nickname($this->arg('id'))); - if ($alias) { - $args = array('id' => $alias->group_id, 'format'=>$this->format); - common_redirect(common_local_url('ApiGroupShow', $args), 301); - } else { - $this->clientError( - _('Group not found!'), - 404, - $this->format - ); - } - return; - } - switch($this->format) { case 'xml': $this->showSingleXmlGroup($this->group); @@ -111,7 +115,6 @@ class ApiGroupShowAction extends ApiPrivateAuthAction $this->clientError(_('API method not found.'), 404, $this->format); break; } - } /** From dcba61332223cfc875b355f6a5f4d2e574dd55b2 Mon Sep 17 00:00:00 2001 From: Siebrand Mazeland Date: Thu, 21 Jan 2010 23:45:09 +0100 Subject: [PATCH 34/53] Localisation updates for !StatusNet from !translatewiki.net !sntrans --- locale/ar/LC_MESSAGES/statusnet.po | 80 ++++++++++++++++++--------- locale/arz/LC_MESSAGES/statusnet.po | 38 +++++++++---- locale/bg/LC_MESSAGES/statusnet.po | 42 +++++++++----- locale/ca/LC_MESSAGES/statusnet.po | 42 +++++++++----- locale/cs/LC_MESSAGES/statusnet.po | 42 +++++++++----- locale/de/LC_MESSAGES/statusnet.po | 42 +++++++++----- locale/el/LC_MESSAGES/statusnet.po | 42 +++++++++----- locale/en_GB/LC_MESSAGES/statusnet.po | 42 +++++++++----- locale/es/LC_MESSAGES/statusnet.po | 42 +++++++++----- locale/fa/LC_MESSAGES/statusnet.po | 42 +++++++++----- locale/fi/LC_MESSAGES/statusnet.po | 42 +++++++++----- locale/fr/LC_MESSAGES/statusnet.po | 42 +++++++++----- locale/ga/LC_MESSAGES/statusnet.po | 42 +++++++++----- locale/he/LC_MESSAGES/statusnet.po | 42 +++++++++----- locale/hsb/LC_MESSAGES/statusnet.po | 42 +++++++++----- locale/ia/LC_MESSAGES/statusnet.po | 42 +++++++++----- locale/is/LC_MESSAGES/statusnet.po | 42 +++++++++----- locale/it/LC_MESSAGES/statusnet.po | 42 +++++++++----- locale/ja/LC_MESSAGES/statusnet.po | 70 +++++++++++++---------- locale/ko/LC_MESSAGES/statusnet.po | 42 +++++++++----- locale/mk/LC_MESSAGES/statusnet.po | 42 +++++++++----- locale/nb/LC_MESSAGES/statusnet.po | 42 +++++++++----- locale/nl/LC_MESSAGES/statusnet.po | 42 +++++++++----- locale/nn/LC_MESSAGES/statusnet.po | 42 +++++++++----- locale/pl/LC_MESSAGES/statusnet.po | 42 +++++++++----- locale/pt/LC_MESSAGES/statusnet.po | 42 +++++++++----- locale/pt_BR/LC_MESSAGES/statusnet.po | 38 +++++++++---- locale/ru/LC_MESSAGES/statusnet.po | 38 +++++++++---- locale/statusnet.po | 34 ++++++++---- locale/sv/LC_MESSAGES/statusnet.po | 38 +++++++++---- locale/te/LC_MESSAGES/statusnet.po | 42 +++++++++----- locale/tr/LC_MESSAGES/statusnet.po | 42 +++++++++----- locale/uk/LC_MESSAGES/statusnet.po | 42 +++++++++----- locale/vi/LC_MESSAGES/statusnet.po | 42 +++++++++----- locale/zh_CN/LC_MESSAGES/statusnet.po | 42 +++++++++----- locale/zh_TW/LC_MESSAGES/statusnet.po | 42 +++++++++----- 36 files changed, 1035 insertions(+), 519 deletions(-) diff --git a/locale/ar/LC_MESSAGES/statusnet.po b/locale/ar/LC_MESSAGES/statusnet.po index 28e85d92fc..bbe2597a25 100644 --- a/locale/ar/LC_MESSAGES/statusnet.po +++ b/locale/ar/LC_MESSAGES/statusnet.po @@ -9,12 +9,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-18 23:16+0000\n" -"PO-Revision-Date: 2010-01-19 23:52:48+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:37:00+0000\n" "Language-Team: Arabic\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61275); Translate extension (2010-01-16)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: ar\n" "X-Message-Group: out-statusnet\n" @@ -127,7 +127,7 @@ msgstr "" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -372,7 +372,7 @@ msgstr "" #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 msgid "Group not found!" msgstr "لم توجد المجموعة!" @@ -597,7 +597,7 @@ msgstr "" #: actions/apitimelineretweetedbyme.php:112 #, php-format msgid "Repeated by %s" -msgstr "" +msgstr "كرّره %s" #: actions/apitimelineretweetedtome.php:111 #, php-format @@ -1042,7 +1042,7 @@ msgid "No such application." msgstr "لا تطبيق كهذا." #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "" @@ -1838,7 +1838,7 @@ msgstr "" #: actions/joingroup.php:60 msgid "You must be logged in to join a group." -msgstr "" +msgstr "يجب أن تلج لتنضم إلى مجموعة." #: actions/joingroup.php:131 #, php-format @@ -1847,7 +1847,7 @@ msgstr "%1$s انضم للمجموعة %2$s" #: actions/leavegroup.php:60 msgid "You must be logged in to leave a group." -msgstr "" +msgstr "يجب أن تلج لتغادر مجموعة." #: actions/leavegroup.php:90 lib/command.php:265 msgid "You are not a member of that group." @@ -1929,7 +1929,7 @@ msgstr "لا حالة حالية" #: actions/newapplication.php:52 msgid "New application" -msgstr "" +msgstr "تطبيق جديد" #: actions/newapplication.php:64 msgid "You must be logged in to register an application." @@ -1961,7 +1961,7 @@ msgstr "رسالة جديدة" #: actions/newmessage.php:121 actions/newmessage.php:161 lib/command.php:358 msgid "You can't send a message to this user." -msgstr "" +msgstr "لا يمكنك إرسال رسائل إلى هذا المستخدم." #: actions/newmessage.php:144 actions/newnotice.php:136 lib/command.php:342 #: lib/command.php:475 @@ -2004,6 +2004,8 @@ msgid "" "Search for notices on %%site.name%% by their contents. Separate search terms " "by spaces; they must be 3 characters or more." msgstr "" +"ابحث عن إشعارات على %%site.name%% عبر محتوياتها. افصل عبارات البحث بمسافات؛ " +"ويجب أن تتكون هذه العبارات من 3 أحرف أو أكثر." #: actions/noticesearch.php:78 msgid "Text search" @@ -2470,7 +2472,7 @@ msgstr "" #: actions/profilesettings.php:138 msgid "Share my current location when posting notices" -msgstr "" +msgstr "شارك مكاني الحالي عند إرسال إشعارات" #: actions/profilesettings.php:145 actions/tagother.php:149 #: actions/tagother.php:209 lib/subscriptionlist.php:106 @@ -3006,7 +3008,7 @@ msgstr "" #: actions/showapplication.php:160 lib/applicationeditform.php:182 msgid "Icon" -msgstr "" +msgstr "أيقونة" #: actions/showapplication.php:170 actions/version.php:195 #: lib/applicationeditform.php:197 @@ -3296,7 +3298,7 @@ msgstr "" #: actions/showstream.php:313 #, php-format msgid "Repeat of %s" -msgstr "تكرارات %s" +msgstr "تكرار ل%s" #: actions/silence.php:65 actions/unsilence.php:65 msgid "You cannot silence users on this site." @@ -3971,7 +3973,7 @@ msgstr "استمتع بالنقانق!" #: actions/usergroups.php:130 msgid "Search for more groups" -msgstr "" +msgstr "ابحث عن المزيد من المجموعات" #: actions/usergroups.php:153 #, php-format @@ -4318,27 +4320,41 @@ msgstr "" "المتوفر تحت [رخصة غنو أفيرو العمومية](http://www.fsf.org/licensing/licenses/" "agpl-3.0.html)." -#: lib/action.php:794 +#: lib/action.php:795 msgid "Site content license" msgstr "رخصة محتوى الموقع" -#: lib/action.php:803 -msgid "All " +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." msgstr "" #: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 +msgid "All " +msgstr "" + +#: lib/action.php:825 msgid "license." msgstr "الرخصة." -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "" -#: lib/action.php:1111 +#: lib/action.php:1133 msgid "After" msgstr "بعد" -#: lib/action.php:1119 +#: lib/action.php:1141 msgid "Before" msgstr "قبل" @@ -4898,7 +4914,7 @@ msgstr "أضف أو عدّل شعار %s" #: lib/groupnav.php:120 #, php-format msgid "Add or edit %s design" -msgstr "" +msgstr "أضف أو عدل تصميم %s" #: lib/groupsbymemberssection.php:71 msgid "Groups with most members" @@ -4911,7 +4927,7 @@ msgstr "المجموعات الأكثر مرسلات" #: lib/grouptagcloudsection.php:56 #, php-format msgid "Tags in %s group's notices" -msgstr "" +msgstr "وسوم في إشعارات المجموعة %s" #: lib/htmloutputter.php:103 msgid "This page is not available in a media type you accept" @@ -5004,7 +5020,7 @@ msgstr "" #: lib/mail.php:236 #, php-format msgid "%1$s is now listening to your notices on %2$s." -msgstr "" +msgstr "%1$s يستمع الآن إلى إشعاراتك على %2$s." #: lib/mail.php:241 #, php-format @@ -5020,6 +5036,16 @@ msgid "" "----\n" "Change your email address or notification options at %8$s\n" msgstr "" +"%1$s يستمع الآن إلى إشعاراتك على %2$s.\n" +"\n" +"%3$s\n" +"\n" +"%4$s%5$s%6$s\n" +"بوفاء،\n" +"%7$s.\n" +"\n" +"----\n" +"غيّر خيارات البريد الإلكتروني والإشعار في %8$s\n" #: lib/mail.php:258 #, php-format @@ -5386,7 +5412,7 @@ msgstr "رسائلك المُرسلة" #: lib/personaltagcloudsection.php:56 #, php-format msgid "Tags in %s's notices" -msgstr "" +msgstr "وسوم في إشعارات %s" #: lib/plugin.php:114 msgid "Unknown" @@ -5450,11 +5476,11 @@ msgstr "مشهورة" #: lib/repeatform.php:107 msgid "Repeat this notice?" -msgstr "كرر هذا الإشعار؟" +msgstr "أأكرّر هذا الإشعار؟ّ" #: lib/repeatform.php:132 msgid "Repeat this notice" -msgstr "كرر هذا الإشعار" +msgstr "كرّر هذا الإشعار" #: lib/sandboxform.php:67 msgid "Sandbox" diff --git a/locale/arz/LC_MESSAGES/statusnet.po b/locale/arz/LC_MESSAGES/statusnet.po index b5f740c4f4..20bb7a4b2e 100644 --- a/locale/arz/LC_MESSAGES/statusnet.po +++ b/locale/arz/LC_MESSAGES/statusnet.po @@ -9,12 +9,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-19 23:52:52+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:37:03+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.16alpha (r61275); Translate extension (2010-01-16)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: arz\n" "X-Message-Group: out-statusnet\n" @@ -127,7 +127,7 @@ msgstr "" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -372,7 +372,7 @@ msgstr "" #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 msgid "Group not found!" msgstr "لم توجد المجموعة!" @@ -1042,7 +1042,7 @@ msgid "No such application." msgstr "لا تطبيق كهذا." #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "" @@ -4318,27 +4318,41 @@ msgstr "" "المتوفر تحت [رخصه غنو أفيرو العمومية](http://www.fsf.org/licensing/licenses/" "agpl-3.0.html)." -#: lib/action.php:794 +#: lib/action.php:795 msgid "Site content license" msgstr "رخصه محتوى الموقع" -#: lib/action.php:803 -msgid "All " +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." msgstr "" #: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 +msgid "All " +msgstr "" + +#: lib/action.php:825 msgid "license." msgstr "الرخصه." -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "" -#: lib/action.php:1111 +#: lib/action.php:1133 msgid "After" msgstr "بعد" -#: lib/action.php:1119 +#: lib/action.php:1141 msgid "Before" msgstr "قبل" diff --git a/locale/bg/LC_MESSAGES/statusnet.po b/locale/bg/LC_MESSAGES/statusnet.po index 5bca81663a..e7bc79a133 100644 --- a/locale/bg/LC_MESSAGES/statusnet.po +++ b/locale/bg/LC_MESSAGES/statusnet.po @@ -9,12 +9,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-15 19:16:04+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:37:06+0000\n" "Language-Team: Bulgarian\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61101); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: bg\n" "X-Message-Group: out-statusnet\n" @@ -126,7 +126,7 @@ msgstr "Бележки от %1$s и приятели в %2$s." #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -381,7 +381,7 @@ msgstr "" #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 msgid "Group not found!" msgstr "Групата не е открита." @@ -1068,7 +1068,7 @@ msgid "No such application." msgstr "Няма такава бележка." #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "Имаше проблем със сесията ви в сайта." @@ -4323,12 +4323,12 @@ msgstr "Забранено ви е да публикувате бележки в msgid "Problem saving notice." msgstr "Проблем при записване на бележката." -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "Грешка в базата от данни — отговор при вмъкването: %s" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, php-format msgid "RT @%1$s %2$s" msgstr "RT @%1$s %2$s" @@ -4531,27 +4531,41 @@ msgstr "" "достъпна под [GNU Affero General Public License](http://www.fsf.org/" "licensing/licenses/agpl-3.0.html)." -#: lib/action.php:794 +#: lib/action.php:795 msgid "Site content license" msgstr "Лиценз на съдържанието" -#: lib/action.php:803 +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." +msgstr "" + +#: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 msgid "All " msgstr "Всички " -#: lib/action.php:808 +#: lib/action.php:825 msgid "license." msgstr "лиценз." -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "Страниране" -#: lib/action.php:1111 +#: lib/action.php:1133 msgid "After" msgstr "След" -#: lib/action.php:1119 +#: lib/action.php:1141 msgid "Before" msgstr "Преди" diff --git a/locale/ca/LC_MESSAGES/statusnet.po b/locale/ca/LC_MESSAGES/statusnet.po index ce09f82d37..ef08bf3f1f 100644 --- a/locale/ca/LC_MESSAGES/statusnet.po +++ b/locale/ca/LC_MESSAGES/statusnet.po @@ -9,12 +9,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-15 19:16:11+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:37:10+0000\n" "Language-Team: Catalan\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61101); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: ca\n" "X-Message-Group: out-statusnet\n" @@ -128,7 +128,7 @@ msgstr "Actualitzacions de %1$s i amics a %2$s!" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -389,7 +389,7 @@ msgstr "L'àlies no pot ser el mateix que el sobrenom." #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 msgid "Group not found!" msgstr "No s'ha trobat el grup!" @@ -1081,7 +1081,7 @@ msgid "No such application." msgstr "No existeix aquest avís." #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "Ha ocorregut algun problema amb la teva sessió." @@ -4377,12 +4377,12 @@ msgstr "Ha estat bandejat de publicar notificacions en aquest lloc." msgid "Problem saving notice." msgstr "Problema en guardar l'avís." -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "Error de BD en inserir resposta: %s" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, fuzzy, php-format msgid "RT @%1$s %2$s" msgstr "%1$s (%2$s)" @@ -4581,27 +4581,41 @@ msgstr "" "%s, disponible sota la [GNU Affero General Public License](http://www.fsf." "org/licensing/licenses/agpl-3.0.html)." -#: lib/action.php:794 +#: lib/action.php:795 msgid "Site content license" msgstr "Llicència de contingut del lloc" -#: lib/action.php:803 +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." +msgstr "" + +#: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 msgid "All " msgstr "Tot " -#: lib/action.php:808 +#: lib/action.php:825 msgid "license." msgstr "llicència." -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "Paginació" -#: lib/action.php:1111 +#: lib/action.php:1133 msgid "After" msgstr "Posteriors" -#: lib/action.php:1119 +#: lib/action.php:1141 msgid "Before" msgstr "Anteriors" diff --git a/locale/cs/LC_MESSAGES/statusnet.po b/locale/cs/LC_MESSAGES/statusnet.po index 53fd42feb6..6fbec682bd 100644 --- a/locale/cs/LC_MESSAGES/statusnet.po +++ b/locale/cs/LC_MESSAGES/statusnet.po @@ -9,12 +9,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-15 19:16:21+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:37:13+0000\n" "Language-Team: Czech\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61101); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: cs\n" "X-Message-Group: out-statusnet\n" @@ -128,7 +128,7 @@ msgstr "" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -383,7 +383,7 @@ msgstr "" #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 #, fuzzy msgid "Group not found!" msgstr "Žádný požadavek nebyl nalezen!" @@ -1087,7 +1087,7 @@ msgid "No such application." msgstr "Žádné takové oznámení." #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "" @@ -4319,12 +4319,12 @@ msgstr "" msgid "Problem saving notice." msgstr "Problém při ukládání sdělení" -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "Chyba v DB při vkládání odpovědi: %s" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, php-format msgid "RT @%1$s %2$s" msgstr "" @@ -4531,29 +4531,43 @@ msgstr "" "dostupná pod [GNU Affero General Public License](http://www.fsf.org/" "licensing/licenses/agpl-3.0.html)." -#: lib/action.php:794 +#: lib/action.php:795 #, fuzzy msgid "Site content license" msgstr "Nové sdělení" -#: lib/action.php:803 -msgid "All " +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." msgstr "" #: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 +msgid "All " +msgstr "" + +#: lib/action.php:825 msgid "license." msgstr "" -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "" -#: lib/action.php:1111 +#: lib/action.php:1133 #, fuzzy msgid "After" msgstr "« Novější" -#: lib/action.php:1119 +#: lib/action.php:1141 #, fuzzy msgid "Before" msgstr "Starší »" diff --git a/locale/de/LC_MESSAGES/statusnet.po b/locale/de/LC_MESSAGES/statusnet.po index 3a06b9870f..e1ea37636e 100644 --- a/locale/de/LC_MESSAGES/statusnet.po +++ b/locale/de/LC_MESSAGES/statusnet.po @@ -12,12 +12,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-15 19:16:32+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:37:16+0000\n" "Language-Team: German\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61101); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: de\n" "X-Message-Group: out-statusnet\n" @@ -139,7 +139,7 @@ msgstr "Aktualisierungen von %1$s und Freunden auf %2$s!" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -390,7 +390,7 @@ msgstr "Alias kann nicht das gleiche wie der Spitznamen sein." #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 msgid "Group not found!" msgstr "Gruppe nicht gefunden!" @@ -1077,7 +1077,7 @@ msgid "No such application." msgstr "Unbekannte Nachricht." #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "Es gab ein Problem mit deinem Sessiontoken." @@ -4396,12 +4396,12 @@ msgstr "" msgid "Problem saving notice." msgstr "Problem bei Speichern der Nachricht." -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "Datenbankfehler beim Einfügen der Antwort: %s" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, fuzzy, php-format msgid "RT @%1$s %2$s" msgstr "%1$s (%2$s)" @@ -4602,28 +4602,42 @@ msgstr "" "(Version %s) betrieben, die unter der [GNU Affero General Public License]" "(http://www.fsf.org/licensing/licenses/agpl-3.0.html) erhältlich ist." -#: lib/action.php:794 +#: lib/action.php:795 msgid "Site content license" msgstr "StatusNet-Software-Lizenz" -#: lib/action.php:803 +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." +msgstr "" + +#: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 #, fuzzy msgid "All " msgstr "Alle " -#: lib/action.php:808 +#: lib/action.php:825 msgid "license." msgstr "Lizenz." -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "Seitenerstellung" -#: lib/action.php:1111 +#: lib/action.php:1133 msgid "After" msgstr "Später" -#: lib/action.php:1119 +#: lib/action.php:1141 msgid "Before" msgstr "Vorher" diff --git a/locale/el/LC_MESSAGES/statusnet.po b/locale/el/LC_MESSAGES/statusnet.po index 6d333e39aa..91ea543053 100644 --- a/locale/el/LC_MESSAGES/statusnet.po +++ b/locale/el/LC_MESSAGES/statusnet.po @@ -9,12 +9,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-15 19:16:35+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:37:20+0000\n" "Language-Team: Greek\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61101); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: el\n" "X-Message-Group: out-statusnet\n" @@ -126,7 +126,7 @@ msgstr "" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -380,7 +380,7 @@ msgstr "" #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 msgid "Group not found!" msgstr "Ομάδα δεν βρέθηκε!" @@ -1067,7 +1067,7 @@ msgid "No such application." msgstr "Δεν υπάρχει τέτοιο σελίδα." #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "" @@ -4247,12 +4247,12 @@ msgstr "" msgid "Problem saving notice." msgstr "" -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "Σφάλμα βάσης δεδομένων κατά την εισαγωγή απάντησης: %s" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, php-format msgid "RT @%1$s %2$s" msgstr "" @@ -4449,27 +4449,41 @@ msgid "" "org/licensing/licenses/agpl-3.0.html)." msgstr "" -#: lib/action.php:794 +#: lib/action.php:795 msgid "Site content license" msgstr "" -#: lib/action.php:803 -msgid "All " +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." msgstr "" #: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 +msgid "All " +msgstr "" + +#: lib/action.php:825 msgid "license." msgstr "" -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "" -#: lib/action.php:1111 +#: lib/action.php:1133 msgid "After" msgstr "" -#: lib/action.php:1119 +#: lib/action.php:1141 msgid "Before" msgstr "" diff --git a/locale/en_GB/LC_MESSAGES/statusnet.po b/locale/en_GB/LC_MESSAGES/statusnet.po index 6735bd23c0..11257ae752 100644 --- a/locale/en_GB/LC_MESSAGES/statusnet.po +++ b/locale/en_GB/LC_MESSAGES/statusnet.po @@ -10,12 +10,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-15 19:16:41+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:37:23+0000\n" "Language-Team: British English\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61101); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: en-gb\n" "X-Message-Group: out-statusnet\n" @@ -134,7 +134,7 @@ msgstr "Updates from %1$s and friends on %2$s!" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -388,7 +388,7 @@ msgstr "Alias can't be the same as nickname." #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 msgid "Group not found!" msgstr "Group not found!" @@ -1078,7 +1078,7 @@ msgid "No such application." msgstr "No such notice." #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "There was a problem with your session token." @@ -4377,12 +4377,12 @@ msgstr "You are banned from posting notices on this site." msgid "Problem saving notice." msgstr "Problem saving notice." -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "DB error inserting reply: %s" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, fuzzy, php-format msgid "RT @%1$s %2$s" msgstr "%1$s (%2$s)" @@ -4581,27 +4581,41 @@ msgstr "" "s, available under the [GNU Affero General Public Licence](http://www.fsf." "org/licensing/licenses/agpl-3.0.html)." -#: lib/action.php:794 +#: lib/action.php:795 msgid "Site content license" msgstr "Site content license" -#: lib/action.php:803 +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." +msgstr "" + +#: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 msgid "All " msgstr "All " -#: lib/action.php:808 +#: lib/action.php:825 msgid "license." msgstr "licence." -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "Pagination" -#: lib/action.php:1111 +#: lib/action.php:1133 msgid "After" msgstr "After" -#: lib/action.php:1119 +#: lib/action.php:1141 msgid "Before" msgstr "Before" diff --git a/locale/es/LC_MESSAGES/statusnet.po b/locale/es/LC_MESSAGES/statusnet.po index c035fc281e..3afbc4e980 100644 --- a/locale/es/LC_MESSAGES/statusnet.po +++ b/locale/es/LC_MESSAGES/statusnet.po @@ -12,12 +12,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-15 19:16:44+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:37:27+0000\n" "Language-Team: Spanish\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61101); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: es\n" "X-Message-Group: out-statusnet\n" @@ -129,7 +129,7 @@ msgstr "¡Actualizaciones de %1$s y amigos en %2$s!" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -383,7 +383,7 @@ msgstr "" #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 #, fuzzy msgid "Group not found!" msgstr "¡No se encontró el método de la API!" @@ -1082,7 +1082,7 @@ msgid "No such application." msgstr "No existe ese aviso." #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "Hubo problemas con tu clave de sesión." @@ -4426,12 +4426,12 @@ msgstr "Tienes prohibido publicar avisos en este sitio." msgid "Problem saving notice." msgstr "Hubo un problema al guardar el aviso." -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "Error de BD al insertar respuesta: %s" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, php-format msgid "RT @%1$s %2$s" msgstr "RT @%1$s %2$s" @@ -4630,27 +4630,41 @@ msgstr "" "disponible bajo la [GNU Affero General Public License](http://www.fsf.org/" "licensing/licenses/agpl-3.0.html)." -#: lib/action.php:794 +#: lib/action.php:795 msgid "Site content license" msgstr "Licencia de contenido del sitio" -#: lib/action.php:803 +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." +msgstr "" + +#: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 msgid "All " msgstr "Todo" -#: lib/action.php:808 +#: lib/action.php:825 msgid "license." msgstr "Licencia." -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "Paginación" -#: lib/action.php:1111 +#: lib/action.php:1133 msgid "After" msgstr "Después" -#: lib/action.php:1119 +#: lib/action.php:1141 msgid "Before" msgstr "Antes" diff --git a/locale/fa/LC_MESSAGES/statusnet.po b/locale/fa/LC_MESSAGES/statusnet.po index c5999c1e2c..2c826643aa 100644 --- a/locale/fa/LC_MESSAGES/statusnet.po +++ b/locale/fa/LC_MESSAGES/statusnet.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-15 19:16:52+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:37:33+0000\n" "Last-Translator: Ahmad Sufi Mahmudi\n" "Language-Team: Persian\n" "MIME-Version: 1.0\n" @@ -20,7 +20,7 @@ msgstr "" "X-Language-Code: fa\n" "X-Message-Group: out-statusnet\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: MediaWiki 1.16alpha (r61101); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" #: actions/all.php:63 actions/public.php:97 actions/replies.php:92 @@ -135,7 +135,7 @@ msgstr "به روز رسانی از %1$ و دوستان در %2$" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -384,7 +384,7 @@ msgstr "نام و نام مستعار شما نمی تواند یکی باشد . #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 msgid "Group not found!" msgstr "گروه یافت نشد!" @@ -1072,7 +1072,7 @@ msgid "No such application." msgstr "چنین پیامی وجود ندارد." #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "" @@ -4239,12 +4239,12 @@ msgstr "شما از فرستادن پست در این سایت مردود شدی msgid "Problem saving notice." msgstr "مشکل در ذخیره کردن آگهی." -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, php-format msgid "RT @%1$s %2$s" msgstr "" @@ -4436,27 +4436,41 @@ msgid "" "org/licensing/licenses/agpl-3.0.html)." msgstr "" -#: lib/action.php:794 +#: lib/action.php:795 msgid "Site content license" msgstr "مجوز محتویات سایت" -#: lib/action.php:803 +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." +msgstr "" + +#: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 msgid "All " msgstr "همه " -#: lib/action.php:808 +#: lib/action.php:825 msgid "license." msgstr "مجوز." -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "صفحه بندى" -#: lib/action.php:1111 +#: lib/action.php:1133 msgid "After" msgstr "بعد از" -#: lib/action.php:1119 +#: lib/action.php:1141 msgid "Before" msgstr "قبل از" diff --git a/locale/fi/LC_MESSAGES/statusnet.po b/locale/fi/LC_MESSAGES/statusnet.po index d225320094..d07fd61ca8 100644 --- a/locale/fi/LC_MESSAGES/statusnet.po +++ b/locale/fi/LC_MESSAGES/statusnet.po @@ -10,12 +10,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-15 19:16:48+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:37:30+0000\n" "Language-Team: Finnish\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61101); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: fi\n" "X-Message-Group: out-statusnet\n" @@ -133,7 +133,7 @@ msgstr "Käyttäjän %1$s ja kavereiden päivitykset palvelussa %2$s!" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -392,7 +392,7 @@ msgstr "Alias ei voi olla sama kuin ryhmätunnus." #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 msgid "Group not found!" msgstr "Ryhmää ei löytynyt!" @@ -1090,7 +1090,7 @@ msgid "No such application." msgstr "Päivitystä ei ole." #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "Istuntoavaimesi kanssa oli ongelma." @@ -4415,12 +4415,12 @@ msgstr "Päivityksesi tähän palveluun on estetty." msgid "Problem saving notice." msgstr "Ongelma päivityksen tallentamisessa." -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "Tietokantavirhe tallennettaessa vastausta: %s" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, fuzzy, php-format msgid "RT @%1$s %2$s" msgstr "%1$s (%2$s)" @@ -4621,28 +4621,42 @@ msgstr "" "versio %s, saatavilla lisenssillä [GNU Affero General Public License](http://" "www.fsf.org/licensing/licenses/agpl-3.0.html)." -#: lib/action.php:794 +#: lib/action.php:795 #, fuzzy msgid "Site content license" msgstr "StatusNet-ohjelmiston lisenssi" -#: lib/action.php:803 +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." +msgstr "" + +#: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 msgid "All " msgstr "Kaikki " -#: lib/action.php:808 +#: lib/action.php:825 msgid "license." msgstr "lisenssi." -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "Sivutus" -#: lib/action.php:1111 +#: lib/action.php:1133 msgid "After" msgstr "Myöhemmin" -#: lib/action.php:1119 +#: lib/action.php:1141 msgid "Before" msgstr "Aiemmin" diff --git a/locale/fr/LC_MESSAGES/statusnet.po b/locale/fr/LC_MESSAGES/statusnet.po index 44a0113294..41f62001f4 100644 --- a/locale/fr/LC_MESSAGES/statusnet.po +++ b/locale/fr/LC_MESSAGES/statusnet.po @@ -13,12 +13,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-16 17:52:07+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:37:36+0000\n" "Language-Team: French\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61138); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: fr\n" "X-Message-Group: out-statusnet\n" @@ -139,7 +139,7 @@ msgstr "Statuts de %1$s et ses amis dans %2$s!" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -392,7 +392,7 @@ msgstr "L’alias ne peut pas être le même que le pseudo." #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 msgid "Group not found!" msgstr "Groupe non trouvé !" @@ -1084,7 +1084,7 @@ msgid "No such application." msgstr "Avis non trouvé." #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "Un problème est survenu avec votre jeton de session." @@ -4441,12 +4441,12 @@ msgstr "Il vous est interdit de poster des avis sur ce site." msgid "Problem saving notice." msgstr "Problème lors de l’enregistrement de l’avis." -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "Erreur de base de donnée en insérant la réponse :%s" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, php-format msgid "RT @%1$s %2$s" msgstr "RT @%1$s %2$s" @@ -4643,27 +4643,41 @@ msgstr "" "version %s, disponible sous la licence [GNU Affero General Public License] " "(http://www.fsf.org/licensing/licenses/agpl-3.0.html)." -#: lib/action.php:794 +#: lib/action.php:795 msgid "Site content license" msgstr "Licence du contenu du site" -#: lib/action.php:803 +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." +msgstr "" + +#: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 msgid "All " msgstr "Tous " -#: lib/action.php:808 +#: lib/action.php:825 msgid "license." msgstr "licence." -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "Pagination" -#: lib/action.php:1111 +#: lib/action.php:1133 msgid "After" msgstr "Après" -#: lib/action.php:1119 +#: lib/action.php:1141 msgid "Before" msgstr "Avant" diff --git a/locale/ga/LC_MESSAGES/statusnet.po b/locale/ga/LC_MESSAGES/statusnet.po index 9c98b889dd..0f6c29dfa0 100644 --- a/locale/ga/LC_MESSAGES/statusnet.po +++ b/locale/ga/LC_MESSAGES/statusnet.po @@ -8,12 +8,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-15 19:16:59+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:37:39+0000\n" "Language-Team: Irish\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61101); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: ga\n" "X-Message-Group: out-statusnet\n" @@ -128,7 +128,7 @@ msgstr "Actualizacións dende %1$s e amigos en %2$s!" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -389,7 +389,7 @@ msgstr "" #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 #, fuzzy msgid "Group not found!" msgstr "Método da API non atopado" @@ -1107,7 +1107,7 @@ msgid "No such application." msgstr "Ningún chío." #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 #, fuzzy msgid "There was a problem with your session token." msgstr "Houbo un problema co teu token de sesión. Tentao de novo, anda..." @@ -4473,12 +4473,12 @@ msgstr "Tes restrinxido o envio de chíos neste sitio." msgid "Problem saving notice." msgstr "Aconteceu un erro ó gardar o chío." -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "Erro ó inserir a contestación na BD: %s" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, fuzzy, php-format msgid "RT @%1$s %2$s" msgstr "%1$s (%2$s)" @@ -4689,30 +4689,44 @@ msgstr "" "%s, dispoñible baixo licenza [GNU Affero General Public License](http://www." "fsf.org/licensing/licenses/agpl-3.0.html)." -#: lib/action.php:794 +#: lib/action.php:795 #, fuzzy msgid "Site content license" msgstr "Atopar no contido dos chíos" -#: lib/action.php:803 +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." +msgstr "" + +#: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 #, fuzzy msgid "All " msgstr "Todos" -#: lib/action.php:808 +#: lib/action.php:825 msgid "license." msgstr "" -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "" -#: lib/action.php:1111 +#: lib/action.php:1133 #, fuzzy msgid "After" msgstr "« Despois" -#: lib/action.php:1119 +#: lib/action.php:1141 #, fuzzy msgid "Before" msgstr "Antes »" diff --git a/locale/he/LC_MESSAGES/statusnet.po b/locale/he/LC_MESSAGES/statusnet.po index 0d4564da33..0367bace5a 100644 --- a/locale/he/LC_MESSAGES/statusnet.po +++ b/locale/he/LC_MESSAGES/statusnet.po @@ -7,12 +7,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-15 19:17:03+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:37:42+0000\n" "Language-Team: Hebrew\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61101); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: he\n" "X-Message-Group: out-statusnet\n" @@ -126,7 +126,7 @@ msgstr "" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -381,7 +381,7 @@ msgstr "" #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 #, fuzzy msgid "Group not found!" msgstr "לא נמצא" @@ -1093,7 +1093,7 @@ msgid "No such application." msgstr "אין הודעה כזו." #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "" @@ -4319,12 +4319,12 @@ msgstr "" msgid "Problem saving notice." msgstr "בעיה בשמירת ההודעה." -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "שגיאת מסד נתונים בהכנסת התגובה: %s" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, php-format msgid "RT @%1$s %2$s" msgstr "" @@ -4532,29 +4532,43 @@ msgstr "" "s, המופצת תחת רשיון [GNU Affero General Public License](http://www.fsf.org/" "licensing/licenses/agpl-3.0.html)" -#: lib/action.php:794 +#: lib/action.php:795 #, fuzzy msgid "Site content license" msgstr "הודעה חדשה" -#: lib/action.php:803 -msgid "All " +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." msgstr "" #: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 +msgid "All " +msgstr "" + +#: lib/action.php:825 msgid "license." msgstr "" -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "" -#: lib/action.php:1111 +#: lib/action.php:1133 #, fuzzy msgid "After" msgstr "<< אחרי" -#: lib/action.php:1119 +#: lib/action.php:1141 #, fuzzy msgid "Before" msgstr "לפני >>" diff --git a/locale/hsb/LC_MESSAGES/statusnet.po b/locale/hsb/LC_MESSAGES/statusnet.po index 0a2f05cb3a..2355fd8e94 100644 --- a/locale/hsb/LC_MESSAGES/statusnet.po +++ b/locale/hsb/LC_MESSAGES/statusnet.po @@ -9,12 +9,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-16 17:52:17+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:37:44+0000\n" "Language-Team: Dutch\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61138); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: hsb\n" "X-Message-Group: out-statusnet\n" @@ -127,7 +127,7 @@ msgstr "" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -372,7 +372,7 @@ msgstr "Alias njemóže samsny kaž přimjeno być." #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 msgid "Group not found!" msgstr "Skupina njenamakana!" @@ -1044,7 +1044,7 @@ msgid "No such application." msgstr "Aplikacija njeeksistuje." #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "" @@ -4113,12 +4113,12 @@ msgstr "" msgid "Problem saving notice." msgstr "" -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, php-format msgid "RT @%1$s %2$s" msgstr "" @@ -4310,27 +4310,41 @@ msgid "" "org/licensing/licenses/agpl-3.0.html)." msgstr "" -#: lib/action.php:794 +#: lib/action.php:795 msgid "Site content license" msgstr "" -#: lib/action.php:803 -msgid "All " +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." msgstr "" #: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 +msgid "All " +msgstr "" + +#: lib/action.php:825 msgid "license." msgstr "" -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "" -#: lib/action.php:1111 +#: lib/action.php:1133 msgid "After" msgstr "" -#: lib/action.php:1119 +#: lib/action.php:1141 msgid "Before" msgstr "" diff --git a/locale/ia/LC_MESSAGES/statusnet.po b/locale/ia/LC_MESSAGES/statusnet.po index 6e32e96802..b54150d955 100644 --- a/locale/ia/LC_MESSAGES/statusnet.po +++ b/locale/ia/LC_MESSAGES/statusnet.po @@ -8,12 +8,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-15 19:17:11+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:37:47+0000\n" "Language-Team: Interlingua\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61101); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: ia\n" "X-Message-Group: out-statusnet\n" @@ -133,7 +133,7 @@ msgstr "Actualisationes de %1$s e su amicos in %2$s!" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -385,7 +385,7 @@ msgstr "Le alias non pote esser identic al pseudonymo." #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 msgid "Group not found!" msgstr "Gruppo non trovate!" @@ -1076,7 +1076,7 @@ msgid "No such application." msgstr "Nota non trovate." #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "" @@ -4366,12 +4366,12 @@ msgstr "" msgid "Problem saving notice." msgstr "" -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, php-format msgid "RT @%1$s %2$s" msgstr "" @@ -4563,27 +4563,41 @@ msgid "" "org/licensing/licenses/agpl-3.0.html)." msgstr "" -#: lib/action.php:794 +#: lib/action.php:795 msgid "Site content license" msgstr "" -#: lib/action.php:803 -msgid "All " +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." msgstr "" #: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 +msgid "All " +msgstr "" + +#: lib/action.php:825 msgid "license." msgstr "" -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "" -#: lib/action.php:1111 +#: lib/action.php:1133 msgid "After" msgstr "" -#: lib/action.php:1119 +#: lib/action.php:1141 msgid "Before" msgstr "" diff --git a/locale/is/LC_MESSAGES/statusnet.po b/locale/is/LC_MESSAGES/statusnet.po index 6ef030c3fb..a12227a706 100644 --- a/locale/is/LC_MESSAGES/statusnet.po +++ b/locale/is/LC_MESSAGES/statusnet.po @@ -8,12 +8,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-15 19:17:14+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:37:50+0000\n" "Language-Team: Icelandic\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61101); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: is\n" "X-Message-Group: out-statusnet\n" @@ -128,7 +128,7 @@ msgstr "Færslur frá %1$s og vinum á %2$s!" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -383,7 +383,7 @@ msgstr "" #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 #, fuzzy msgid "Group not found!" msgstr "Aðferð í forritsskilum fannst ekki!" @@ -1082,7 +1082,7 @@ msgid "No such application." msgstr "Ekkert svoleiðis babl." #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "Það komu upp vandamál varðandi setutókann þinn." @@ -4367,12 +4367,12 @@ msgstr "Það hefur verið lagt bann við babli frá þér á þessari síðu." msgid "Problem saving notice." msgstr "Vandamál komu upp við að vista babl." -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "Gagnagrunnsvilla við innsetningu svars: %s" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, fuzzy, php-format msgid "RT @%1$s %2$s" msgstr "%1$s (%2$s)" @@ -4573,28 +4573,42 @@ msgstr "" "sem er gefinn út undir [GNU Affero almenningsleyfinu](http://www.fsf.org/" "licensing/licenses/agpl-3.0.html)." -#: lib/action.php:794 +#: lib/action.php:795 #, fuzzy msgid "Site content license" msgstr "Hugbúnaðarleyfi StatusNet" -#: lib/action.php:803 +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." +msgstr "" + +#: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 msgid "All " msgstr "Allt " -#: lib/action.php:808 +#: lib/action.php:825 msgid "license." msgstr "leyfi." -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "Uppröðun" -#: lib/action.php:1111 +#: lib/action.php:1133 msgid "After" msgstr "Eftir" -#: lib/action.php:1119 +#: lib/action.php:1141 msgid "Before" msgstr "Áður" diff --git a/locale/it/LC_MESSAGES/statusnet.po b/locale/it/LC_MESSAGES/statusnet.po index 032a363f0a..892526e984 100644 --- a/locale/it/LC_MESSAGES/statusnet.po +++ b/locale/it/LC_MESSAGES/statusnet.po @@ -9,12 +9,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-15 19:17:18+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:37:54+0000\n" "Language-Team: Italian\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61101); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: it\n" "X-Message-Group: out-statusnet\n" @@ -135,7 +135,7 @@ msgstr "Messaggi da %1$s e amici su %2$s!" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -386,7 +386,7 @@ msgstr "L'alias non può essere lo stesso del soprannome." #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 msgid "Group not found!" msgstr "Gruppo non trovato!" @@ -1077,7 +1077,7 @@ msgid "No such application." msgstr "Nessun messaggio." #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "Si è verificato un problema con il tuo token di sessione." @@ -4406,12 +4406,12 @@ msgstr "Ti è proibito inviare messaggi su questo sito." msgid "Problem saving notice." msgstr "Problema nel salvare il messaggio." -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "Errore del DB nell'inserire la risposta: %s" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, php-format msgid "RT @%1$s %2$s" msgstr "RT @%1$s %2$s" @@ -4608,27 +4608,41 @@ msgstr "" "s, disponibile nei termini della licenza [GNU Affero General Public License]" "(http://www.fsf.org/licensing/licenses/agpl-3.0.html)." -#: lib/action.php:794 +#: lib/action.php:795 msgid "Site content license" msgstr "Licenza del contenuto del sito" -#: lib/action.php:803 +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." +msgstr "" + +#: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 msgid "All " msgstr "Tutti " -#: lib/action.php:808 +#: lib/action.php:825 msgid "license." msgstr "licenza." -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "Paginazione" -#: lib/action.php:1111 +#: lib/action.php:1133 msgid "After" msgstr "Successivi" -#: lib/action.php:1119 +#: lib/action.php:1141 msgid "Before" msgstr "Precedenti" diff --git a/locale/ja/LC_MESSAGES/statusnet.po b/locale/ja/LC_MESSAGES/statusnet.po index 792ff4d39e..6260ef5acb 100644 --- a/locale/ja/LC_MESSAGES/statusnet.po +++ b/locale/ja/LC_MESSAGES/statusnet.po @@ -11,12 +11,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-18 23:16+0000\n" -"PO-Revision-Date: 2010-01-18 23:18:49+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:37:57+0000\n" "Language-Team: Japanese\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61218); Translate extension (2010-01-16)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: ja\n" "X-Message-Group: out-statusnet\n" @@ -134,7 +134,7 @@ msgstr "%2$s に %1$s と友人からの更新があります!" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -386,7 +386,7 @@ msgstr "別名はニックネームと同じではいけません。" #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 msgid "Group not found!" msgstr "グループが見つかりません!" @@ -876,7 +876,7 @@ msgid "" "You are about to permanently delete a notice. Once this is done, it cannot " "be undone." msgstr "" -"あなたは永久につぶやきを削除しようとしています。 これが完了するとそれを元に戻" +"あなたはつぶやきを永久に削除しようとしています。 これが完了するとそれを元に戻" "すことはできません。" #: actions/deletenotice.php:109 actions/deletenotice.php:141 @@ -1068,7 +1068,7 @@ msgid "No such application." msgstr "そのようなアプリケーションはありません。" #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "あなたのセッショントークンに関する問題がありました。" @@ -1184,7 +1184,7 @@ msgid "" "Awaiting confirmation on this address. Check your inbox (and spam box!) for " "a message with further instructions." msgstr "" -"このアドレスは確認待ちです。受信ボックス(とスパムボックス)に追加の指示が書" +"このアドレスは承認待ちです。受信ボックス(とスパムボックス)に追加の指示が書" "かれたメッセージが届いていないか確認してください。" #: actions/emailsettings.php:117 actions/imsettings.php:120 @@ -1234,17 +1234,17 @@ msgstr "メールで新規フォローの通知を私に送ってください。 #: actions/emailsettings.php:163 msgid "Send me email when someone adds my notice as a favorite." msgstr "" -"だれかがお気に入りとして私のつぶやきを加えたらメールを私に送ってください。" +"だれかがお気に入りとして私のつぶやきを加えたら、メールを私に送ってください。" #: actions/emailsettings.php:169 msgid "Send me email when someone sends me a private message." msgstr "" -"だれかがプライベート・メッセージを私に送るときにはメールを私に送ってくださ" +"だれかがプライベート・メッセージを私に送るときには、メールを私に送ってくださ" "い。" #: actions/emailsettings.php:174 msgid "Send me email when someone sends me an \"@-reply\"." -msgstr "だれかが\"@-返信\"を私を送るときにはメールを私に送ってください、" +msgstr "だれかが\"@-返信\"を私を送るときには、メールを私に送ってください、" #: actions/emailsettings.php:179 msgid "Allow friends to nudge me and send me an email." @@ -1287,21 +1287,21 @@ msgstr "このメールアドレスは既に他の人が使っています。" #: actions/emailsettings.php:353 actions/imsettings.php:317 #: actions/smssettings.php:337 msgid "Couldn't insert confirmation code." -msgstr "確認コードを追加できません" +msgstr "承認コードを追加できません" #: actions/emailsettings.php:359 msgid "" "A confirmation code was sent to the email address you added. Check your " "inbox (and spam box!) for the code and instructions on how to use it." msgstr "" -"確認用コードを入力された電子メールアドレスに送信しました。受信ボックス(とス" -"パムボックス)にコードとそれをどう使うのかという指示が届いていないか確認して" -"ください。" +"承認コードを入力された電子メールアドレスに送信しました。受信ボックス(とスパ" +"ムボックス)にコードとそれをどう使うのかという指示が届いていないか確認してく" +"ださい。" #: actions/emailsettings.php:379 actions/imsettings.php:351 #: actions/smssettings.php:370 msgid "No pending confirmation to cancel." -msgstr "認証待ちのものはありません。" +msgstr "承認待ちのものはありません。" #: actions/emailsettings.php:383 actions/imsettings.php:355 msgid "That is the wrong IM address." @@ -1310,7 +1310,7 @@ msgstr "その IM アドレスは不正です。" #: actions/emailsettings.php:395 actions/imsettings.php:367 #: actions/smssettings.php:386 msgid "Confirmation cancelled." -msgstr "確認作業が中止されました。" +msgstr "承認作業が中止されました。" #: actions/emailsettings.php:413 msgid "That is not your email address." @@ -1721,7 +1721,7 @@ msgid "" "Awaiting confirmation on this address. Check your Jabber/GTalk account for a " "message with further instructions. (Did you add %s to your buddy list?)" msgstr "" -"このアドレスは確認待ちです。Jabber か Gtalk のアカウントで追加の指示が書かれ" +"このアドレスは承認待ちです。Jabber か Gtalk のアカウントで追加の指示が書かれ" "たメッセージを確認してください。(%s を友人リストに追加しましたか?)" #: actions/imsettings.php:124 @@ -1781,8 +1781,8 @@ msgid "" "A confirmation code was sent to the IM address you added. You must approve %" "s for sending messages to you." msgstr "" -"確認用コードを入力された IM アドレスに送信しました。あなたにメッセージを送れ" -"るようにするには%sを承認してください。" +"承認コードを入力された IM アドレスに送信しました。あなたにメッセージを送れる" +"ようにするには%sを承認してください。" #: actions/imsettings.php:387 msgid "That is not your Jabber ID." @@ -3014,7 +3014,7 @@ msgid "" "(You should receive a message by email momentarily, with instructions on how " "to confirm your email address.)" msgstr "" -"(メールアドレスを確認する方法を読んで、すぐにメールによるメッセージを受け取る" +"(メールアドレスを承認する方法を読んで、すぐにメールによるメッセージを受け取る" "ようにしてください)" #: actions/remotesubscribe.php:98 @@ -4560,27 +4560,41 @@ msgstr "" "いています。 ライセンス [GNU Affero General Public License](http://www.fsf." "org/licensing/licenses/agpl-3.0.html)。" -#: lib/action.php:794 +#: lib/action.php:795 msgid "Site content license" msgstr "サイト内容ライセンス" -#: lib/action.php:803 +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." +msgstr "" + +#: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 msgid "All " msgstr "全て " -#: lib/action.php:808 +#: lib/action.php:825 msgid "license." msgstr "ライセンス。" -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "ページ化" -#: lib/action.php:1111 +#: lib/action.php:1133 msgid "After" msgstr "<<後" -#: lib/action.php:1119 +#: lib/action.php:1141 msgid "Before" msgstr "前>>" @@ -5240,7 +5254,7 @@ msgstr "" "\n" "だれかがこのメールアドレスを %s に入力しました。\n" "\n" -"もしエントリーを確認したいなら、以下のURLを使用してください:\n" +"もし登録を承認したいなら、以下のURLを使用してください:\n" "\n" "%s\n" "\n" diff --git a/locale/ko/LC_MESSAGES/statusnet.po b/locale/ko/LC_MESSAGES/statusnet.po index 9c5c453525..b8197af3ee 100644 --- a/locale/ko/LC_MESSAGES/statusnet.po +++ b/locale/ko/LC_MESSAGES/statusnet.po @@ -7,12 +7,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-15 19:17:27+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:38:00+0000\n" "Language-Team: Korean\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61101); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: ko\n" "X-Message-Group: out-statusnet\n" @@ -126,7 +126,7 @@ msgstr "%1$s 및 %2$s에 있는 친구들의 업데이트!" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -385,7 +385,7 @@ msgstr "" #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 #, fuzzy msgid "Group not found!" msgstr "API 메서드를 찾을 수 없습니다." @@ -1095,7 +1095,7 @@ msgid "No such application." msgstr "그러한 통지는 없습니다." #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "당신의 세션토큰관련 문제가 있습니다." @@ -4392,12 +4392,12 @@ msgstr "이 사이트에 게시글 포스팅으로부터 당신은 금지되었 msgid "Problem saving notice." msgstr "통지를 저장하는데 문제가 발생했습니다." -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "답신을 추가 할 때에 데이타베이스 에러 : %s" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, fuzzy, php-format msgid "RT @%1$s %2$s" msgstr "%1$s (%2$s)" @@ -4598,28 +4598,42 @@ msgstr "" "을 사용합니다. StatusNet는 [GNU Affero General Public License](http://www." "fsf.org/licensing/licenses/agpl-3.0.html) 라이선스에 따라 사용할 수 있습니다." -#: lib/action.php:794 +#: lib/action.php:795 #, fuzzy msgid "Site content license" msgstr "라코니카 소프트웨어 라이선스" -#: lib/action.php:803 +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." +msgstr "" + +#: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 msgid "All " msgstr "모든 것" -#: lib/action.php:808 +#: lib/action.php:825 msgid "license." msgstr "라이선스" -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "페이지수" -#: lib/action.php:1111 +#: lib/action.php:1133 msgid "After" msgstr "뒷 페이지" -#: lib/action.php:1119 +#: lib/action.php:1141 msgid "Before" msgstr "앞 페이지" diff --git a/locale/mk/LC_MESSAGES/statusnet.po b/locale/mk/LC_MESSAGES/statusnet.po index 30b7170566..95eaff9439 100644 --- a/locale/mk/LC_MESSAGES/statusnet.po +++ b/locale/mk/LC_MESSAGES/statusnet.po @@ -9,12 +9,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-16 17:52:38+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:38:03+0000\n" "Language-Team: Macedonian\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61138); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: mk\n" "X-Message-Group: out-statusnet\n" @@ -135,7 +135,7 @@ msgstr "Подновувања од %1$s и пријатели на %2$s!" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -387,7 +387,7 @@ msgstr "Алијасот не може да биде ист како прека #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 msgid "Group not found!" msgstr "Групата не е пронајдена!" @@ -1073,7 +1073,7 @@ msgid "No such application." msgstr "Нема таков програм." #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "Се појави проблем со Вашиот сесиски жетон." @@ -4394,12 +4394,12 @@ msgstr "Забрането Ви е да објавувате забелешки msgid "Problem saving notice." msgstr "Проблем во зачувувањето на белешката." -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "Одговор од внесот во базата: %s" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, php-format msgid "RT @%1$s %2$s" msgstr "RT @%1$s %2$s" @@ -4596,27 +4596,41 @@ msgstr "" "верзија %s, достапен пд [GNU Affero General Public License](http://www.fsf." "org/licensing/licenses/agpl-3.0.html)." -#: lib/action.php:794 +#: lib/action.php:795 msgid "Site content license" msgstr "Лиценца на содржините на веб-страницата" -#: lib/action.php:803 +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." +msgstr "" + +#: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 msgid "All " msgstr "Сите " -#: lib/action.php:808 +#: lib/action.php:825 msgid "license." msgstr "лиценца." -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "Прелом на страници" -#: lib/action.php:1111 +#: lib/action.php:1133 msgid "After" msgstr "По" -#: lib/action.php:1119 +#: lib/action.php:1141 msgid "Before" msgstr "Пред" diff --git a/locale/nb/LC_MESSAGES/statusnet.po b/locale/nb/LC_MESSAGES/statusnet.po index a0e92f8fdb..697fda7b00 100644 --- a/locale/nb/LC_MESSAGES/statusnet.po +++ b/locale/nb/LC_MESSAGES/statusnet.po @@ -8,12 +8,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-15 19:17:35+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:38:06+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.16alpha (r61101); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: no\n" "X-Message-Group: out-statusnet\n" @@ -132,7 +132,7 @@ msgstr "Oppdateringer fra %1$s og venner på %2$s!" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -388,7 +388,7 @@ msgstr "" #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 #, fuzzy msgid "Group not found!" msgstr "API-metode ikke funnet!" @@ -1087,7 +1087,7 @@ msgid "No such application." msgstr "Ingen slik side" #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "" @@ -4295,12 +4295,12 @@ msgstr "" msgid "Problem saving notice." msgstr "" -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, php-format msgid "RT @%1$s %2$s" msgstr "" @@ -4499,27 +4499,41 @@ msgid "" "org/licensing/licenses/agpl-3.0.html)." msgstr "" -#: lib/action.php:794 +#: lib/action.php:795 msgid "Site content license" msgstr "" -#: lib/action.php:803 -msgid "All " +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." msgstr "" #: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 +msgid "All " +msgstr "" + +#: lib/action.php:825 msgid "license." msgstr "" -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "" -#: lib/action.php:1111 +#: lib/action.php:1133 msgid "After" msgstr "" -#: lib/action.php:1119 +#: lib/action.php:1141 #, fuzzy msgid "Before" msgstr "Tidligere »" diff --git a/locale/nl/LC_MESSAGES/statusnet.po b/locale/nl/LC_MESSAGES/statusnet.po index ff28d0c757..935117671c 100644 --- a/locale/nl/LC_MESSAGES/statusnet.po +++ b/locale/nl/LC_MESSAGES/statusnet.po @@ -10,12 +10,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-16 17:52:50+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:38:12+0000\n" "Language-Team: Dutch\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61138); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: nl\n" "X-Message-Group: out-statusnet\n" @@ -136,7 +136,7 @@ msgstr "Updates van %1$s en vrienden op %2$s." #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -393,7 +393,7 @@ msgstr "Een alias kan niet hetzelfde zijn als de gebruikersnaam." #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 msgid "Group not found!" msgstr "De groep is niet aangetroffen!" @@ -1085,7 +1085,7 @@ msgid "No such application." msgstr "De applicatie bestaat niet." #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "Er is een probleem met uw sessietoken." @@ -4429,13 +4429,13 @@ msgstr "" msgid "Problem saving notice." msgstr "Er is een probleem opgetreden bij het opslaan van de mededeling." -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "" "Er is een databasefout opgetreden bij het invoegen van het antwoord: %s" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, php-format msgid "RT @%1$s %2$s" msgstr "RT @%1$s %2$s" @@ -4632,27 +4632,41 @@ msgstr "" "versie %s, beschikbaar onder de [GNU Affero General Public License](http://" "www.fsf.org/licensing/licenses/agpl-3.0.html)." -#: lib/action.php:794 +#: lib/action.php:795 msgid "Site content license" msgstr "Licentie voor siteinhoud" -#: lib/action.php:803 +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." +msgstr "" + +#: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 msgid "All " msgstr "Alle " -#: lib/action.php:808 +#: lib/action.php:825 msgid "license." msgstr "licentie." -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "Paginering" -#: lib/action.php:1111 +#: lib/action.php:1133 msgid "After" msgstr "Later" -#: lib/action.php:1119 +#: lib/action.php:1141 msgid "Before" msgstr "Eerder" diff --git a/locale/nn/LC_MESSAGES/statusnet.po b/locale/nn/LC_MESSAGES/statusnet.po index 6ea81a38ee..5a9d928fdb 100644 --- a/locale/nn/LC_MESSAGES/statusnet.po +++ b/locale/nn/LC_MESSAGES/statusnet.po @@ -7,12 +7,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-15 19:17:38+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:38:09+0000\n" "Language-Team: Norwegian Nynorsk\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61101); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: nn\n" "X-Message-Group: out-statusnet\n" @@ -126,7 +126,7 @@ msgstr "Oppdateringar frå %1$s og vener på %2$s!" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -383,7 +383,7 @@ msgstr "" #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 #, fuzzy msgid "Group not found!" msgstr "Fann ikkje API-metode." @@ -1094,7 +1094,7 @@ msgid "No such application." msgstr "Denne notisen finst ikkje." #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "Det var eit problem med sesjons billetten din." @@ -4409,12 +4409,12 @@ msgstr "Du kan ikkje lengre legge inn notisar på denne sida." msgid "Problem saving notice." msgstr "Eit problem oppstod ved lagring av notis." -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "Databasefeil, kan ikkje lagra svar: %s" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, fuzzy, php-format msgid "RT @%1$s %2$s" msgstr "%1$s (%2$s)" @@ -4615,28 +4615,42 @@ msgstr "" "%s, tilgjengeleg under [GNU Affero General Public License](http://www.fsf." "org/licensing/licenses/agpl-3.0.html)." -#: lib/action.php:794 +#: lib/action.php:795 #, fuzzy msgid "Site content license" msgstr "StatusNets programvarelisens" -#: lib/action.php:803 +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." +msgstr "" + +#: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 msgid "All " msgstr "Alle" -#: lib/action.php:808 +#: lib/action.php:825 msgid "license." msgstr "lisens." -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "Paginering" -#: lib/action.php:1111 +#: lib/action.php:1133 msgid "After" msgstr "« Etter" -#: lib/action.php:1119 +#: lib/action.php:1141 msgid "Before" msgstr "Før »" diff --git a/locale/pl/LC_MESSAGES/statusnet.po b/locale/pl/LC_MESSAGES/statusnet.po index 17f334cb40..b42a542b51 100644 --- a/locale/pl/LC_MESSAGES/statusnet.po +++ b/locale/pl/LC_MESSAGES/statusnet.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-16 17:52:53+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:38:15+0000\n" "Last-Translator: Piotr Drąg \n" "Language-Team: Polish \n" "MIME-Version: 1.0\n" @@ -19,7 +19,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.16alpha (r61138); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: pl\n" "X-Message-Group: out-statusnet\n" @@ -139,7 +139,7 @@ msgstr "Aktualizacje z %1$s i przyjaciół na %2$s." #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -390,7 +390,7 @@ msgstr "Alias nie może być taki sam jak pseudonim." #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 msgid "Group not found!" msgstr "Nie odnaleziono grupy." @@ -1068,7 +1068,7 @@ msgid "No such application." msgstr "Nie ma takiej aplikacji." #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "Wystąpił problem z tokenem sesji." @@ -4367,12 +4367,12 @@ msgstr "Zabroniono ci wysyłania wpisów na tej stronie." msgid "Problem saving notice." msgstr "Problem podczas zapisywania wpisu." -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "Błąd bazy danych podczas wprowadzania odpowiedzi: %s" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, php-format msgid "RT @%1$s %2$s" msgstr "RT @%1$s %2$s" @@ -4569,27 +4569,41 @@ msgstr "" "status.net/) w wersji %s, dostępnego na [Powszechnej Licencji Publicznej GNU " "Affero](http://www.fsf.org/licensing/licenses/agpl-3.0.html)." -#: lib/action.php:794 +#: lib/action.php:795 msgid "Site content license" msgstr "Licencja zawartości strony" -#: lib/action.php:803 +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." +msgstr "" + +#: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 msgid "All " msgstr "Wszystko " -#: lib/action.php:808 +#: lib/action.php:825 msgid "license." msgstr "licencja." -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "Paginacja" -#: lib/action.php:1111 +#: lib/action.php:1133 msgid "After" msgstr "Później" -#: lib/action.php:1119 +#: lib/action.php:1141 msgid "Before" msgstr "Wcześniej" diff --git a/locale/pt/LC_MESSAGES/statusnet.po b/locale/pt/LC_MESSAGES/statusnet.po index a7e2b9e33e..9b136debd7 100644 --- a/locale/pt/LC_MESSAGES/statusnet.po +++ b/locale/pt/LC_MESSAGES/statusnet.po @@ -9,12 +9,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-15 19:17:49+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:38:17+0000\n" "Language-Team: Portuguese\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61101); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: pt\n" "X-Message-Group: out-statusnet\n" @@ -133,7 +133,7 @@ msgstr "Actualizações de %1$s e amigos no %2$s!" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -383,7 +383,7 @@ msgstr "Os sinónimos não podem ser iguais ao nome do utilizador." #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 msgid "Group not found!" msgstr "Grupo não foi encontrado!" @@ -1071,7 +1071,7 @@ msgid "No such application." msgstr "Nota não encontrada." #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "Ocorreu um problema com a sua sessão." @@ -4400,12 +4400,12 @@ msgstr "Está proibido de publicar notas neste site." msgid "Problem saving notice." msgstr "Problema na gravação da nota." -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "Ocorreu um erro na base de dados ao inserir a resposta: %s" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, php-format msgid "RT @%1$s %2$s" msgstr "RT @%1$s %2$s" @@ -4602,27 +4602,41 @@ msgstr "" "disponibilizado nos termos da [GNU Affero General Public License](http://www." "fsf.org/licensing/licenses/agpl-3.0.html)." -#: lib/action.php:794 +#: lib/action.php:795 msgid "Site content license" msgstr "Licença de conteúdos do site" -#: lib/action.php:803 +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." +msgstr "" + +#: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 msgid "All " msgstr "Tudo " -#: lib/action.php:808 +#: lib/action.php:825 msgid "license." msgstr "licença." -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "Paginação" -#: lib/action.php:1111 +#: lib/action.php:1133 msgid "After" msgstr "Posteriores" -#: lib/action.php:1119 +#: lib/action.php:1141 msgid "Before" msgstr "Anteriores" diff --git a/locale/pt_BR/LC_MESSAGES/statusnet.po b/locale/pt_BR/LC_MESSAGES/statusnet.po index 3b07494f25..d28a14e684 100644 --- a/locale/pt_BR/LC_MESSAGES/statusnet.po +++ b/locale/pt_BR/LC_MESSAGES/statusnet.po @@ -10,12 +10,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-18 23:16+0000\n" -"PO-Revision-Date: 2010-01-18 23:19:44+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:38:21+0000\n" "Language-Team: Brazilian Portuguese\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61218); Translate extension (2010-01-16)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: pt-br\n" "X-Message-Group: out-statusnet\n" @@ -136,7 +136,7 @@ msgstr "Atualizações de %1$s e amigos no %2$s!" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -389,7 +389,7 @@ msgstr "O apelido não pode ser igual à identificação." #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 msgid "Group not found!" msgstr "O grupo não foi encontrado!" @@ -1075,7 +1075,7 @@ msgid "No such application." msgstr "Essa aplicação não existe." #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "Ocorreu um problema com o seu token de sessão." @@ -4599,27 +4599,41 @@ msgstr "" "versão %s, disponível sob a [GNU Affero General Public License] (http://www." "fsf.org/licensing/licenses/agpl-3.0.html)." -#: lib/action.php:794 +#: lib/action.php:795 msgid "Site content license" msgstr "Licença do conteúdo do site" -#: lib/action.php:803 +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." +msgstr "" + +#: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 msgid "All " msgstr "Todas " -#: lib/action.php:808 +#: lib/action.php:825 msgid "license." msgstr "licença." -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "Paginação" -#: lib/action.php:1111 +#: lib/action.php:1133 msgid "After" msgstr "Próximo" -#: lib/action.php:1119 +#: lib/action.php:1141 msgid "Before" msgstr "Anterior" diff --git a/locale/ru/LC_MESSAGES/statusnet.po b/locale/ru/LC_MESSAGES/statusnet.po index 505325bae6..d95566fdf9 100644 --- a/locale/ru/LC_MESSAGES/statusnet.po +++ b/locale/ru/LC_MESSAGES/statusnet.po @@ -11,12 +11,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-18 23:16+0000\n" -"PO-Revision-Date: 2010-01-18 23:19:49+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:38:23+0000\n" "Language-Team: Russian\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61218); Translate extension (2010-01-16)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: ru\n" "X-Message-Group: out-statusnet\n" @@ -136,7 +136,7 @@ msgstr "Обновлено от %1$s и его друзей на %2$s!" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -390,7 +390,7 @@ msgstr "Алиас не может совпадать с именем." #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 msgid "Group not found!" msgstr "Группа не найдена!" @@ -1075,7 +1075,7 @@ msgid "No such application." msgstr "Нет такой записи." #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "Проблема с Вашей сессией. Попробуйте ещё раз, пожалуйста." @@ -4609,27 +4609,41 @@ msgstr "" "лицензией [GNU Affero General Public License](http://www.fsf.org/licensing/" "licenses/agpl-3.0.html)." -#: lib/action.php:794 +#: lib/action.php:795 msgid "Site content license" msgstr "Лицензия содержимого сайта" -#: lib/action.php:803 +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." +msgstr "" + +#: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 msgid "All " msgstr "All " -#: lib/action.php:808 +#: lib/action.php:825 msgid "license." msgstr "license." -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "Разбиение на страницы" -#: lib/action.php:1111 +#: lib/action.php:1133 msgid "After" msgstr "Сюда" -#: lib/action.php:1119 +#: lib/action.php:1141 msgid "Before" msgstr "Туда" diff --git a/locale/statusnet.po b/locale/statusnet.po index 9c28de8029..fedcf6e7bc 100644 --- a/locale/statusnet.po +++ b/locale/statusnet.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-19 23:52+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -123,7 +123,7 @@ msgstr "" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -368,7 +368,7 @@ msgstr "" #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 msgid "Group not found!" msgstr "" @@ -1038,7 +1038,7 @@ msgid "No such application." msgstr "" #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "" @@ -4299,27 +4299,41 @@ msgid "" "org/licensing/licenses/agpl-3.0.html)." msgstr "" -#: lib/action.php:794 +#: lib/action.php:795 msgid "Site content license" msgstr "" -#: lib/action.php:803 -msgid "All " +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." msgstr "" #: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 +msgid "All " +msgstr "" + +#: lib/action.php:825 msgid "license." msgstr "" -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "" -#: lib/action.php:1111 +#: lib/action.php:1133 msgid "After" msgstr "" -#: lib/action.php:1119 +#: lib/action.php:1141 msgid "Before" msgstr "" diff --git a/locale/sv/LC_MESSAGES/statusnet.po b/locale/sv/LC_MESSAGES/statusnet.po index d7e0f19c9b..6046d5fe2a 100644 --- a/locale/sv/LC_MESSAGES/statusnet.po +++ b/locale/sv/LC_MESSAGES/statusnet.po @@ -9,12 +9,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-18 23:16+0000\n" -"PO-Revision-Date: 2010-01-19 23:55:02+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:38:31+0000\n" "Language-Team: Swedish\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61275); Translate extension (2010-01-16)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: sv\n" "X-Message-Group: out-statusnet\n" @@ -133,7 +133,7 @@ msgstr "Uppdateringar från %1$s och vänner på %2$s!" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -381,7 +381,7 @@ msgstr "Alias kan inte vara samma som smeknamn." #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 msgid "Group not found!" msgstr "Grupp hittades inte!" @@ -1062,7 +1062,7 @@ msgid "No such application." msgstr "Ingen sådan applikation." #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "Det var ett problem med din sessions-token." @@ -4526,27 +4526,41 @@ msgstr "" "version %s, tillgänglig under [GNU Affero General Public License](http://www." "fsf.org/licensing/licenses/agpl-3.0.html)." -#: lib/action.php:794 +#: lib/action.php:795 msgid "Site content license" msgstr "Licens för webbplatsinnehåll" -#: lib/action.php:803 +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." +msgstr "" + +#: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 msgid "All " msgstr "Alla " -#: lib/action.php:808 +#: lib/action.php:825 msgid "license." msgstr "licens." -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "Numrering av sidor" -#: lib/action.php:1111 +#: lib/action.php:1133 msgid "After" msgstr "Senare" -#: lib/action.php:1119 +#: lib/action.php:1141 msgid "Before" msgstr "Tidigare" diff --git a/locale/te/LC_MESSAGES/statusnet.po b/locale/te/LC_MESSAGES/statusnet.po index 84b9402c1b..4b313d88f0 100644 --- a/locale/te/LC_MESSAGES/statusnet.po +++ b/locale/te/LC_MESSAGES/statusnet.po @@ -8,12 +8,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-16 17:53:10+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:38:34+0000\n" "Language-Team: Telugu\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61138); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: te\n" "X-Message-Group: out-statusnet\n" @@ -125,7 +125,7 @@ msgstr "" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -377,7 +377,7 @@ msgstr "మారుపేరు పేరుతో సమానంగా ఉం #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 msgid "Group not found!" msgstr "గుంపు దొరకలేదు!" @@ -1059,7 +1059,7 @@ msgid "No such application." msgstr "అటువంటి సందేశమేమీ లేదు." #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "" @@ -4197,12 +4197,12 @@ msgstr "ఈ సైటులో నోటీసులు రాయడం ను msgid "Problem saving notice." msgstr "సందేశాన్ని భద్రపరచడంలో పొరపాటు." -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, fuzzy, php-format msgid "RT @%1$s %2$s" msgstr "%1$s (%2$s)" @@ -4405,28 +4405,42 @@ msgstr "" "html) కింద లభ్యమయ్యే [స్టేటస్‌నెట్](http://status.net/) మైక్రోబ్లాగింగ్ ఉపకరణం సంచిక %s " "పై నడుస్తుంది." -#: lib/action.php:794 +#: lib/action.php:795 #, fuzzy msgid "Site content license" msgstr "కొత్త సందేశం" -#: lib/action.php:803 +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." +msgstr "" + +#: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 msgid "All " msgstr "అన్నీ " -#: lib/action.php:808 +#: lib/action.php:825 msgid "license." msgstr "" -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "పేజీకరణ" -#: lib/action.php:1111 +#: lib/action.php:1133 msgid "After" msgstr "తర్వాత" -#: lib/action.php:1119 +#: lib/action.php:1141 msgid "Before" msgstr "ఇంతక్రితం" diff --git a/locale/tr/LC_MESSAGES/statusnet.po b/locale/tr/LC_MESSAGES/statusnet.po index 99c4243880..bcec74af8b 100644 --- a/locale/tr/LC_MESSAGES/statusnet.po +++ b/locale/tr/LC_MESSAGES/statusnet.po @@ -8,12 +8,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-15 19:18:07+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:38:37+0000\n" "Language-Team: Turkish\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61101); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: tr\n" "X-Message-Group: out-statusnet\n" @@ -127,7 +127,7 @@ msgstr "" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -385,7 +385,7 @@ msgstr "" #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 #, fuzzy msgid "Group not found!" msgstr "İstek bulunamadı!" @@ -1096,7 +1096,7 @@ msgid "No such application." msgstr "Böyle bir durum mesajı yok." #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "" @@ -4327,12 +4327,12 @@ msgstr "" msgid "Problem saving notice." msgstr "Durum mesajını kaydederken hata oluştu." -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "Cevap eklenirken veritabanı hatası: %s" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, php-format msgid "RT @%1$s %2$s" msgstr "" @@ -4540,29 +4540,43 @@ msgstr "" "licenses/agpl-3.0.html) lisansı ile korunan [StatusNet](http://status.net/) " "microbloglama yazılımının %s. versiyonunu kullanmaktadır." -#: lib/action.php:794 +#: lib/action.php:795 #, fuzzy msgid "Site content license" msgstr "Yeni durum mesajı" -#: lib/action.php:803 -msgid "All " +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." msgstr "" #: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 +msgid "All " +msgstr "" + +#: lib/action.php:825 msgid "license." msgstr "" -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "" -#: lib/action.php:1111 +#: lib/action.php:1133 #, fuzzy msgid "After" msgstr "« Sonra" -#: lib/action.php:1119 +#: lib/action.php:1141 #, fuzzy msgid "Before" msgstr "Önce »" diff --git a/locale/uk/LC_MESSAGES/statusnet.po b/locale/uk/LC_MESSAGES/statusnet.po index 4d8de517c5..886b60cc30 100644 --- a/locale/uk/LC_MESSAGES/statusnet.po +++ b/locale/uk/LC_MESSAGES/statusnet.po @@ -10,12 +10,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-16 17:53:16+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:38:40+0000\n" "Language-Team: Ukrainian\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61138); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: uk\n" "X-Message-Group: out-statusnet\n" @@ -134,7 +134,7 @@ msgstr "Оновлення від %1$s та друзів на %2$s!" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -385,7 +385,7 @@ msgstr "Додаткове ім’я не може бути таким сами #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 msgid "Group not found!" msgstr "Групу не знайдено!" @@ -1067,7 +1067,7 @@ msgid "No such application." msgstr "Такого додатку немає." #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "Виникли певні проблеми з токеном поточної сесії." @@ -4371,12 +4371,12 @@ msgstr "Вам заборонено надсилати дописи до цьо msgid "Problem saving notice." msgstr "Проблема при збереженні допису." -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "Помилка бази даних при додаванні відповіді: %s" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, php-format msgid "RT @%1$s %2$s" msgstr "RT @%1$s %2$s" @@ -4573,27 +4573,41 @@ msgstr "" "для мікроблоґів, версія %s, доступному під [GNU Affero General Public " "License](http://www.fsf.org/licensing/licenses/agpl-3.0.html)." -#: lib/action.php:794 +#: lib/action.php:795 msgid "Site content license" msgstr "Ліцензія змісту сайту" -#: lib/action.php:803 +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." +msgstr "" + +#: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 msgid "All " msgstr "Всі " -#: lib/action.php:808 +#: lib/action.php:825 msgid "license." msgstr "ліцензія." -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "Нумерація сторінок" -#: lib/action.php:1111 +#: lib/action.php:1133 msgid "After" msgstr "Вперед" -#: lib/action.php:1119 +#: lib/action.php:1141 msgid "Before" msgstr "Назад" diff --git a/locale/vi/LC_MESSAGES/statusnet.po b/locale/vi/LC_MESSAGES/statusnet.po index 1d889777de..4b977cee41 100644 --- a/locale/vi/LC_MESSAGES/statusnet.po +++ b/locale/vi/LC_MESSAGES/statusnet.po @@ -7,12 +7,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-15 19:18:14+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:38:43+0000\n" "Language-Team: Vietnamese\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61101); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: vi\n" "X-Message-Group: out-statusnet\n" @@ -126,7 +126,7 @@ msgstr "" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -387,7 +387,7 @@ msgstr "" #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 #, fuzzy msgid "Group not found!" msgstr "Phương thức API không tìm thấy!" @@ -1111,7 +1111,7 @@ msgid "No such application." msgstr "Không có tin nhắn nào." #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 #, fuzzy msgid "There was a problem with your session token." msgstr "Có lỗi xảy ra khi thao tác. Hãy thử lại lần nữa." @@ -4478,12 +4478,12 @@ msgstr "" msgid "Problem saving notice." msgstr "Có lỗi xảy ra khi lưu tin nhắn." -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "Lỗi cơ sở dữ liệu khi chèn trả lời: %s" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, fuzzy, php-format msgid "RT @%1$s %2$s" msgstr "%s (%s)" @@ -4696,29 +4696,43 @@ msgstr "" "quyền [GNU Affero General Public License](http://www.fsf.org/licensing/" "licenses/agpl-3.0.html)." -#: lib/action.php:794 +#: lib/action.php:795 #, fuzzy msgid "Site content license" msgstr "Tìm theo nội dung của tin nhắn" -#: lib/action.php:803 -msgid "All " +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." msgstr "" #: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 +msgid "All " +msgstr "" + +#: lib/action.php:825 msgid "license." msgstr "" -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "" -#: lib/action.php:1111 +#: lib/action.php:1133 #, fuzzy msgid "After" msgstr "Sau" -#: lib/action.php:1119 +#: lib/action.php:1141 #, fuzzy msgid "Before" msgstr "Trước" diff --git a/locale/zh_CN/LC_MESSAGES/statusnet.po b/locale/zh_CN/LC_MESSAGES/statusnet.po index ec2e005d10..aec8ae047a 100644 --- a/locale/zh_CN/LC_MESSAGES/statusnet.po +++ b/locale/zh_CN/LC_MESSAGES/statusnet.po @@ -10,12 +10,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-15 19:18:17+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:38:46+0000\n" "Language-Team: Simplified Chinese\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61101); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: zh-hans\n" "X-Message-Group: out-statusnet\n" @@ -128,7 +128,7 @@ msgstr "来自%2$s 上 %1$s 和好友的更新!" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -385,7 +385,7 @@ msgstr "" #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 #, fuzzy msgid "Group not found!" msgstr "API 方法未实现!" @@ -1100,7 +1100,7 @@ msgid "No such application." msgstr "没有这份通告。" #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 #, fuzzy msgid "There was a problem with your session token." msgstr "会话标识有问题,请重试。" @@ -4405,12 +4405,12 @@ msgstr "在这个网站你被禁止发布消息。" msgid "Problem saving notice." msgstr "保存通告时出错。" -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "添加回复时数据库出错:%s" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, fuzzy, php-format msgid "RT @%1$s %2$s" msgstr "%1$s (%2$s)" @@ -4618,29 +4618,43 @@ msgstr "" "General Public License](http://www.fsf.org/licensing/licenses/agpl-3.0.html)" "授权。" -#: lib/action.php:794 +#: lib/action.php:795 #, fuzzy msgid "Site content license" msgstr "StatusNet软件注册证" -#: lib/action.php:803 +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." +msgstr "" + +#: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 msgid "All " msgstr "全部" -#: lib/action.php:808 +#: lib/action.php:825 msgid "license." msgstr "注册证" -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "分页" -#: lib/action.php:1111 +#: lib/action.php:1133 #, fuzzy msgid "After" msgstr "« 之后" -#: lib/action.php:1119 +#: lib/action.php:1141 #, fuzzy msgid "Before" msgstr "之前 »" diff --git a/locale/zh_TW/LC_MESSAGES/statusnet.po b/locale/zh_TW/LC_MESSAGES/statusnet.po index 2fdb74d716..cbcbf12489 100644 --- a/locale/zh_TW/LC_MESSAGES/statusnet.po +++ b/locale/zh_TW/LC_MESSAGES/statusnet.po @@ -7,12 +7,12 @@ msgid "" msgstr "" "Project-Id-Version: StatusNet\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-01-15 19:15+0000\n" -"PO-Revision-Date: 2010-01-15 19:18:21+0000\n" +"POT-Creation-Date: 2010-01-21 22:36+0000\n" +"PO-Revision-Date: 2010-01-21 22:38:49+0000\n" "Language-Team: Traditional Chinese\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: MediaWiki 1.16alpha (r61101); Translate extension (2010-01-04)\n" +"X-Generator: MediaWiki 1.16alpha (r61339); Translate extension (2010-01-16)\n" "X-Translation-Project: translatewiki.net at http://translatewiki.net\n" "X-Language-Code: zh-hant\n" "X-Message-Group: out-statusnet\n" @@ -126,7 +126,7 @@ msgstr "" #: actions/apigroupcreate.php:136 actions/apigroupismember.php:114 #: actions/apigroupjoin.php:155 actions/apigroupleave.php:141 #: actions/apigrouplist.php:132 actions/apigrouplistall.php:120 -#: actions/apigroupmembership.php:106 actions/apigroupshow.php:105 +#: actions/apigroupmembership.php:106 actions/apigroupshow.php:115 #: actions/apihelptest.php:88 actions/apistatusesdestroy.php:102 #: actions/apistatusesretweets.php:112 actions/apistatusesshow.php:108 #: actions/apistatusnetconfig.php:133 actions/apistatusnetversion.php:93 @@ -380,7 +380,7 @@ msgstr "" #: actions/apigroupismember.php:95 actions/apigroupjoin.php:104 #: actions/apigroupleave.php:104 actions/apigroupmembership.php:91 -#: actions/apigroupshow.php:90 actions/apitimelinegroup.php:91 +#: actions/apigroupshow.php:82 actions/apitimelinegroup.php:91 #, fuzzy msgid "Group not found!" msgstr "目前無請求" @@ -1086,7 +1086,7 @@ msgid "No such application." msgstr "無此通知" #: actions/editapplication.php:127 actions/newapplication.php:110 -#: actions/showapplication.php:118 lib/action.php:1167 +#: actions/showapplication.php:118 lib/action.php:1189 msgid "There was a problem with your session token." msgstr "" @@ -4249,12 +4249,12 @@ msgstr "" msgid "Problem saving notice." msgstr "" -#: classes/Notice.php:1052 +#: classes/Notice.php:1059 #, php-format msgid "DB error inserting reply: %s" msgstr "增加回覆時,資料庫發生錯誤: %s" -#: classes/Notice.php:1423 +#: classes/Notice.php:1441 #, php-format msgid "RT @%1$s %2$s" msgstr "" @@ -4457,28 +4457,42 @@ msgid "" "org/licensing/licenses/agpl-3.0.html)." msgstr "" -#: lib/action.php:794 +#: lib/action.php:795 #, fuzzy msgid "Site content license" msgstr "新訊息" -#: lib/action.php:803 -msgid "All " +#: lib/action.php:800 +#, php-format +msgid "Content and data of %1$s are private and confidential." +msgstr "" + +#: lib/action.php:805 +#, php-format +msgid "Content and data copyright by %1$s. All rights reserved." msgstr "" #: lib/action.php:808 +msgid "Content and data copyright by contributors. All rights reserved." +msgstr "" + +#: lib/action.php:820 +msgid "All " +msgstr "" + +#: lib/action.php:825 msgid "license." msgstr "" -#: lib/action.php:1102 +#: lib/action.php:1124 msgid "Pagination" msgstr "" -#: lib/action.php:1111 +#: lib/action.php:1133 msgid "After" msgstr "" -#: lib/action.php:1119 +#: lib/action.php:1141 #, fuzzy msgid "Before" msgstr "之前的內容»" From 4b0f953ccf7435d6ebe4a674953f62af36cc978b Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Fri, 22 Jan 2010 00:27:08 +0000 Subject: [PATCH 35/53] Quick hack to avoid breaking with geonames off when there's some old cookie state. This code's a little rough and tumble; any breakage halts JS execution and leaves the spinner going and no message submitted. --- js/util.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/js/util.js b/js/util.js index 88016bd6d0..a749c5d9f4 100644 --- a/js/util.js +++ b/js/util.js @@ -205,8 +205,10 @@ var SN = { // StatusNet cookieValue = JSON.parse(cookieValue); NLat = $('#'+SN.C.S.NoticeLat).val(cookieValue.NLat).val(); NLon = $('#'+SN.C.S.NoticeLon).val(cookieValue.NLon).val(); - NLNS = $('#'+SN.C.S.NoticeLocationNs).val(cookieValue.NLNS).val(); - NLID = $('#'+SN.C.S.NoticeLocationId).val(cookieValue.NLID).val(); + if ($('#'+SN.C.S.NoticeLocationNs).val(cookieValue.NLNS)) { + NLNS = $('#'+SN.C.S.NoticeLocationNs).val(cookieValue.NLNS).val(); + NLID = $('#'+SN.C.S.NoticeLocationId).val(cookieValue.NLID).val(); + } } if (cookieValue == 'disabled') { NDG = $('#'+SN.C.S.NoticeDataGeo).attr('checked', false).attr('checked'); @@ -301,8 +303,10 @@ var SN = { // StatusNet $('#'+SN.C.S.NoticeLat).val(NLat); $('#'+SN.C.S.NoticeLon).val(NLon); - $('#'+SN.C.S.NoticeLocationNs).val(NLNS); - $('#'+SN.C.S.NoticeLocationId).val(NLID); + if ($('#'+SN.C.S.NoticeLocationNs)) { + $('#'+SN.C.S.NoticeLocationNs).val(NLNS); + $('#'+SN.C.S.NoticeLocationId).val(NLID); + } $('#'+SN.C.S.NoticeDataGeo).attr('checked', NDG); } }); From 0bb23e6fd724a12bba6766949cd3294b288d8a43 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Thu, 21 Jan 2010 16:34:26 -0800 Subject: [PATCH 36/53] drop debug line from xmppdaemon.php, we're done debugging that --- scripts/xmppdaemon.php | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/xmppdaemon.php b/scripts/xmppdaemon.php index 0c118c53d6..cef9c4bd07 100755 --- a/scripts/xmppdaemon.php +++ b/scripts/xmppdaemon.php @@ -148,7 +148,6 @@ class XMPPDaemon extends Daemon function handle_message(&$pl) { - $this->log(LOG_DEBUG, "Received message: " . str_replace("\n", " ", var_export($pl, true))); $from = jabber_normalize_jid($pl['from']); if ($pl['type'] != 'chat') { From 26fdf0c9d210d79c4e279fafd35eb25302911da3 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Thu, 21 Jan 2010 16:42:50 -0800 Subject: [PATCH 37/53] XMPP queued output & initial retooling of DB queue manager to support non-Notice objects. Queue handlers for XMPP individual & firehose output now send their XML stanzas to another output queue instead of connecting directly to the chat server. This lets us have as many general processing threads as we need, while all actual XMPP input and output go through a single daemon with a single connection open. This avoids problems with multiple connected resources: * multiple windows shown in some chat clients (psi, gajim, kopete) * extra load on server * incoming message delivery forwarding issues Database changes: * queue_item drops 'notice_id' in favor of a 'frame' blob. This is based on Craig Andrews' work branch to generalize queues to take any object, but conservatively leaving out the serialization for now. Table updater (preserves any existing queued items) in db/rc3to09.sql Code changes to watch out for: * Queue handlers should now define a handle() method instead of handle_notice() * QueueDaemon and XmppDaemon now share common i/o (IoMaster) and respawning thread management (RespawningDaemon) infrastructure. * The polling XmppConfirmManager has been dropped, as the message is queued directly when saving IM settings. * Enable $config['queue']['debug_memory'] to output current memory usage at each run through the event loop to watch for memory leaks To do: * Adapt XMPP i/o to component connection mode for multi-site support. * XMPP input can also be broken out to a queue, which would allow the actual notice save etc to be handled by general queue threads. * Make sure there are no problems with simply pushing serialized Notice objects to queues. * Find a way to improve interactive performance of the database-backed queue handler; polling is pretty painful to XMPP. * Possibly redo the way QueueHandlers are injected into a QueueManager. The grouping used to split out the XMPP output queue is a bit awkward. --- actions/imsettings.php | 10 +- classes/Queue_item.php | 30 +- classes/statusnet.ini | 6 +- db/08to09.sql | 16 + db/rc3to09.sql | 16 + db/statusnet.sql | 5 +- lib/dbqueuemanager.php | 138 ++----- lib/default.php | 1 + lib/iomaster.php | 39 +- lib/jabber.php | 43 ++- lib/jabberqueuehandler.php | 4 +- lib/ombqueuehandler.php | 2 +- lib/pingqueuehandler.php | 2 +- lib/pluginqueuehandler.php | 2 +- lib/publicqueuehandler.php | 6 +- lib/queued_xmpp.php | 117 ++++++ lib/queuehandler.php | 95 +---- lib/queuemanager.php | 125 +++++-- lib/smsqueuehandler.php | 2 +- lib/spawningdaemon.php | 159 ++++++++ lib/stompqueuemanager.php | 56 +-- lib/util.php | 3 +- lib/xmppconfirmmanager.php | 168 --------- lib/xmppmanager.php | 298 ++++++++++++--- lib/xmppoutqueuehandler.php | 55 +++ plugins/Enjit/enjitqueuehandler.php | 9 +- plugins/Facebook/facebookqueuehandler.php | 2 +- plugins/RSSCloud/RSSCloudPlugin.php | 41 +- plugins/RSSCloud/RSSCloudQueueHandler.php | 50 +-- plugins/TwitterBridge/twitterqueuehandler.php | 2 +- scripts/handlequeued.php | 2 +- scripts/queuedaemon.php | 149 ++------ scripts/xmppdaemon.php | 353 ++---------------- 33 files changed, 951 insertions(+), 1055 deletions(-) create mode 100644 db/rc3to09.sql create mode 100644 lib/queued_xmpp.php create mode 100644 lib/spawningdaemon.php delete mode 100644 lib/xmppconfirmmanager.php create mode 100644 lib/xmppoutqueuehandler.php mode change 100755 => 100644 plugins/RSSCloud/RSSCloudQueueHandler.php diff --git a/actions/imsettings.php b/actions/imsettings.php index 751c6117cd..af4915843d 100644 --- a/actions/imsettings.php +++ b/actions/imsettings.php @@ -309,6 +309,8 @@ class ImsettingsAction extends ConnectSettingsAction $confirm->address_type = 'jabber'; $confirm->user_id = $user->id; $confirm->code = common_confirmation_code(64); + $confirm->sent = common_sql_now(); + $confirm->claimed = common_sql_now(); $result = $confirm->insert(); @@ -318,11 +320,9 @@ class ImsettingsAction extends ConnectSettingsAction return; } - if (!common_config('queue', 'enabled')) { - jabber_confirm_address($confirm->code, - $user->nickname, - $jabber); - } + jabber_confirm_address($confirm->code, + $user->nickname, + $jabber); $msg = sprintf(_('A confirmation code was sent '. 'to the IM address you added. '. diff --git a/classes/Queue_item.php b/classes/Queue_item.php index cf805a6060..f83c2cef18 100644 --- a/classes/Queue_item.php +++ b/classes/Queue_item.php @@ -10,8 +10,8 @@ class Queue_item extends Memcached_DataObject /* the code below is auto generated do not remove the above tag */ public $__table = 'queue_item'; // table name - public $notice_id; // int(4) primary_key not_null - public $transport; // varchar(8) primary_key not_null + public $id; // int(4) primary_key not_null + public $frame; // blob not_null public $created; // datetime() not_null public $claimed; // datetime() @@ -22,14 +22,21 @@ class Queue_item extends Memcached_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE - function sequenceKey() - { return array(false, false); } - - static function top($transport=null) { + /** + * @param mixed $transports name of a single queue or array of queues to pull from + * If not specified, checks all queues in the system. + */ + static function top($transports=null) { $qi = new Queue_item(); - if ($transport) { - $qi->transport = $transport; + if ($transports) { + if (is_array($transports)) { + // @fixme use safer escaping + $list = implode("','", array_map('addslashes', $transports)); + $qi->whereAdd("transport in ('$list')"); + } else { + $qi->transport = $transports; + } } $qi->orderBy('created'); $qi->whereAdd('claimed is null'); @@ -42,7 +49,7 @@ class Queue_item extends Memcached_DataObject # XXX: potential race condition # can we force it to only update if claimed is still null # (or old)? - common_log(LOG_INFO, 'claiming queue item = ' . $qi->notice_id . + common_log(LOG_INFO, 'claiming queue item id = ' . $qi->id . ' for transport ' . $qi->transport); $orig = clone($qi); $qi->claimed = common_sql_now(); @@ -57,9 +64,4 @@ class Queue_item extends Memcached_DataObject $qi = null; return null; } - - function pkeyGet($kv) - { - return Memcached_DataObject::pkeyGet('Queue_item', $kv); - } } diff --git a/classes/statusnet.ini b/classes/statusnet.ini index 44088cf6b0..6203650a69 100644 --- a/classes/statusnet.ini +++ b/classes/statusnet.ini @@ -428,14 +428,14 @@ tagged = K tag = K [queue_item] -notice_id = 129 +id = 129 +frame = 66 transport = 130 created = 142 claimed = 14 [queue_item__keys] -notice_id = K -transport = K +id = K [related_group] group_id = 129 diff --git a/db/08to09.sql b/db/08to09.sql index d9c25bc723..b10e47dbcb 100644 --- a/db/08to09.sql +++ b/db/08to09.sql @@ -94,3 +94,19 @@ create table user_location_prefs ( constraint primary key (user_id) ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; +create table queue_item_new ( + id integer auto_increment primary key comment 'unique identifier', + frame blob not null comment 'data: object reference or opaque string', + transport varchar(8) not null comment 'queue for what? "email", "jabber", "sms", "irc", ...', + created datetime not null comment 'date this record was created', + claimed datetime comment 'date this item was claimed', + + index queue_item_created_idx (created) + +) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; + +insert into queue_item_new (frame,transport,created,claimed) + select notice_id,transport,created,claimed from queue_item; +alter table queue_item rename to queue_item_old; +alter table queue_item_new rename to queue_item; + diff --git a/db/rc3to09.sql b/db/rc3to09.sql new file mode 100644 index 0000000000..02dc7a6e2e --- /dev/null +++ b/db/rc3to09.sql @@ -0,0 +1,16 @@ +create table queue_item_new ( + id integer auto_increment primary key comment 'unique identifier', + frame blob not null comment 'data: object reference or opaque string', + transport varchar(8) not null comment 'queue for what? "email", "jabber", "sms", "irc", ...', + created datetime not null comment 'date this record was created', + claimed datetime comment 'date this item was claimed', + + index queue_item_created_idx (created) + +) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; + +insert into queue_item_new (frame,transport,created,claimed) + select notice_id,transport,created,claimed from queue_item; +alter table queue_item rename to queue_item_old; +alter table queue_item_new rename to queue_item; + diff --git a/db/statusnet.sql b/db/statusnet.sql index 2a9ab74c77..17de4fd0d4 100644 --- a/db/statusnet.sql +++ b/db/statusnet.sql @@ -274,13 +274,12 @@ create table remember_me ( ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; create table queue_item ( - - notice_id integer not null comment 'notice queued' references notice (id), + id integer auto_increment primary key comment 'unique identifier', + frame blob not null comment 'data: object reference or opaque string', transport varchar(8) not null comment 'queue for what? "email", "jabber", "sms", "irc", ...', created datetime not null comment 'date this record was created', claimed datetime comment 'date this item was claimed', - constraint primary key (notice_id, transport), index queue_item_created_idx (created) ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; diff --git a/lib/dbqueuemanager.php b/lib/dbqueuemanager.php index 889365b649..c6350fc669 100644 --- a/lib/dbqueuemanager.php +++ b/lib/dbqueuemanager.php @@ -31,19 +31,17 @@ class DBQueueManager extends QueueManager { /** - * Saves a notice object reference into the queue item table. + * Saves an object reference into the queue item table. * @return boolean true on success * @throws ServerException on failure */ public function enqueue($object, $queue) { - $notice = $object; - $qi = new Queue_item(); - $qi->notice_id = $notice->id; + $qi->frame = $this->encode($object); $qi->transport = $queue; - $qi->created = $notice->created; + $qi->created = common_sql_now(); $result = $qi->insert(); if (!$result) { @@ -57,146 +55,92 @@ class DBQueueManager extends QueueManager } /** - * Poll every minute for new events during idle periods. + * Poll every 10 seconds for new events during idle periods. * We'll look in more often when there's data available. * * @return int seconds */ public function pollInterval() { - return 60; + return 10; } /** * Run a polling cycle during idle processing in the input loop. - * @return boolean true if we had a hit + * @return boolean true if we should poll again for more data immediately */ public function poll() { $this->_log(LOG_DEBUG, 'Checking for notices...'); - $item = $this->_nextItem(); - if ($item === false) { + $qi = Queue_item::top($this->getQueues()); + if (empty($qi)) { $this->_log(LOG_DEBUG, 'No notices waiting; idling.'); return false; } - if ($item === true) { - // We dequeued an entry for a deleted or invalid notice. - // Consider it a hit for poll rate purposes. - return true; - } - list($queue, $notice) = $item; - $this->_log(LOG_INFO, 'Got notice '. $notice->id . ' for transport ' . $queue); + $queue = $qi->transport; + $item = $this->decode($qi->frame); - // Yay! Got one! - $handler = $this->getHandler($queue); - if ($handler) { - if ($handler->handle_notice($notice)) { - $this->_log(LOG_INFO, "[$queue:notice $notice->id] Successfully handled notice"); - $this->_done($notice, $queue); + if ($item) { + $rep = $this->logrep($item); + $this->_log(LOG_INFO, "Got $rep for transport $queue"); + + $handler = $this->getHandler($queue); + if ($handler) { + if ($handler->handle($item)) { + $this->_log(LOG_INFO, "[$queue:$rep] Successfully handled item"); + $this->_done($qi); + } else { + $this->_log(LOG_INFO, "[$queue:$rep] Failed to handle item"); + $this->_fail($qi); + } } else { - $this->_log(LOG_INFO, "[$queue:notice $notice->id] Failed to handle notice"); - $this->_fail($notice, $queue); + $this->_log(LOG_INFO, "[$queue:$rep] No handler for queue $queue; discarding."); + $this->_done($qi); } } else { - $this->_log(LOG_INFO, "[$queue:notice $notice->id] No handler for queue $queue; discarding."); - $this->_done($notice, $queue); + $this->_log(LOG_INFO, "[$queue] Got empty/deleted item, discarding"); + $this->_fail($qi); } return true; } - /** - * Pop the oldest unclaimed item off the queue set and claim it. - * - * @return mixed false if no items; true if bogus hit; otherwise array(string, Notice) - * giving the queue transport name. - */ - protected function _nextItem() - { - $start = time(); - $result = null; - - $qi = Queue_item::top(); - if (empty($qi)) { - return false; - } - - $queue = $qi->transport; - $notice = Notice::staticGet('id', $qi->notice_id); - if (empty($notice)) { - $this->_log(LOG_INFO, "[$queue:notice $notice->id] dequeued non-existent notice"); - $qi->delete(); - return true; - } - - $result = $notice; - return array($queue, $notice); - } - /** * Delete our claimed item from the queue after successful processing. * - * @param Notice $object - * @param string $queue + * @param QueueItem $qi */ - protected function _done($object, $queue) + protected function _done($qi) { - // XXX: right now, we only handle notices + $queue = $qi->transport; - $notice = $object; - - $qi = Queue_item::pkeyGet(array('notice_id' => $notice->id, - 'transport' => $queue)); - - if (empty($qi)) { - $this->_log(LOG_INFO, "[$queue:notice $notice->id] Cannot find queue item"); - } else { - if (empty($qi->claimed)) { - $this->_log(LOG_WARNING, "[$queue:notice $notice->id] Reluctantly releasing unclaimed queue item"); - } - $qi->delete(); - $qi->free(); + if (empty($qi->claimed)) { + $this->_log(LOG_WARNING, "Reluctantly releasing unclaimed queue item $qi->id from $qi->queue"); } + $qi->delete(); - $this->_log(LOG_INFO, "[$queue:notice $notice->id] done with item"); $this->stats('handled', $queue); - - $notice->free(); } /** * Free our claimed queue item for later reprocessing in case of * temporary failure. * - * @param Notice $object - * @param string $queue + * @param QueueItem $qi */ - protected function _fail($object, $queue) + protected function _fail($qi) { - // XXX: right now, we only handle notices + $queue = $qi->transport; - $notice = $object; - - $qi = Queue_item::pkeyGet(array('notice_id' => $notice->id, - 'transport' => $queue)); - - if (empty($qi)) { - $this->_log(LOG_INFO, "[$queue:notice $notice->id] Cannot find queue item"); + if (empty($qi->claimed)) { + $this->_log(LOG_WARNING, "[$queue:item $qi->id] Ignoring failure for unclaimed queue item"); } else { - if (empty($qi->claimed)) { - $this->_log(LOG_WARNING, "[$queue:notice $notice->id] Ignoring failure for unclaimed queue item"); - } else { - $orig = clone($qi); - $qi->claimed = null; - $qi->update($orig); - $qi = null; - } + $orig = clone($qi); + $qi->claimed = null; + $qi->update($orig); } - $this->_log(LOG_INFO, "[$queue:notice $notice->id] done with queue item"); $this->stats('error', $queue); - - $notice->free(); } protected function _log($level, $msg) diff --git a/lib/default.php b/lib/default.php index 764d309dfd..d258bbaf48 100644 --- a/lib/default.php +++ b/lib/default.php @@ -83,6 +83,7 @@ $default = 'stomp_password' => null, 'monitor' => null, // URL to monitor ping endpoint (work in progress) 'softlimit' => '90%', // total size or % of memory_limit at which to restart queue threads gracefully + 'debug_memory' => false, // true to spit memory usage to log ), 'license' => array('type' => 'cc', # can be 'cc', 'allrightsreserved', 'private' diff --git a/lib/iomaster.php b/lib/iomaster.php index ce77b53b2e..004e92b3ee 100644 --- a/lib/iomaster.php +++ b/lib/iomaster.php @@ -27,7 +27,7 @@ * @link http://status.net/ */ -class IoMaster +abstract class IoMaster { public $id; @@ -66,23 +66,18 @@ class IoMaster if ($site != common_config('site', 'server')) { StatusNet::init($site); } - - $classes = array(); - if (Event::handle('StartIoManagerClasses', array(&$classes))) { - $classes[] = 'QueueManager'; - if (common_config('xmpp', 'enabled') && !defined('XMPP_EMERGENCY_FLAG')) { - $classes[] = 'XmppManager'; // handles pings/reconnects - $classes[] = 'XmppConfirmManager'; // polls for outgoing confirmations - } - } - Event::handle('EndIoManagerClasses', array(&$classes)); - - foreach ($classes as $class) { - $this->instantiate($class); - } + $this->initManagers(); } } + /** + * Initialize IoManagers for the currently configured site + * which are appropriate to this instance. + * + * Pass class names into $this->instantiate() + */ + abstract function initManagers(); + /** * Pull all local sites from status_network table. * @return array of hostnames @@ -170,7 +165,7 @@ class IoMaster $write = array(); $except = array(); $this->logState('listening'); - common_log(LOG_INFO, "Waiting up to $timeout seconds for socket data..."); + common_log(LOG_DEBUG, "Waiting up to $timeout seconds for socket data..."); $ready = stream_select($read, $write, $except, $timeout, 0); if ($ready === false) { @@ -190,7 +185,7 @@ class IoMaster if ($timeout > 0 && empty($sockets)) { // If we had no listeners, sleep until the pollers' next requested wakeup. - common_log(LOG_INFO, "Sleeping $timeout seconds until next poll cycle..."); + common_log(LOG_DEBUG, "Sleeping $timeout seconds until next poll cycle..."); $this->logState('sleep'); sleep($timeout); } @@ -207,6 +202,8 @@ class IoMaster if ($usage > $memoryLimit) { common_log(LOG_INFO, "Queue thread hit soft memory limit ($usage > $memoryLimit); gracefully restarting."); break; + } else if (common_config('queue', 'debug_memory')) { + common_log(LOG_DEBUG, "Memory usage $usage"); } } } @@ -223,8 +220,7 @@ class IoMaster { $softLimit = trim(common_config('queue', 'softlimit')); if (substr($softLimit, -1) == '%') { - $limit = trim(ini_get('memory_limit')); - $limit = $this->parseMemoryLimit($limit); + $limit = $this->parseMemoryLimit(ini_get('memory_limit')); if ($limit > 0) { return intval(substr($softLimit, 0, -1) * $limit / 100); } else { @@ -242,9 +238,10 @@ class IoMaster * @param string $mem * @return int */ - protected function parseMemoryLimit($mem) + public function parseMemoryLimit($mem) { // http://www.php.net/manual/en/faq.using.php#faq.using.shorthandbytes + $mem = strtolower(trim($mem)); $size = array('k' => 1024, 'm' => 1024*1024, 'g' => 1024*1024*1024); @@ -253,7 +250,7 @@ class IoMaster } else if (is_numeric($mem)) { return intval($mem); } else { - $mult = strtolower(substr($mem, -1)); + $mult = substr($mem, -1); if (isset($size[$mult])) { return substr($mem, 0, -1) * $size[$mult]; } else { diff --git a/lib/jabber.php b/lib/jabber.php index 4cdfa67465..b6b23521bd 100644 --- a/lib/jabber.php +++ b/lib/jabber.php @@ -85,6 +85,27 @@ class Sharing_XMPP extends XMPPHP_XMPP } } +/** + * Build an XMPP proxy connection that'll save outgoing messages + * to the 'xmppout' queue to be picked up by xmppdaemon later. + */ +function jabber_proxy() +{ + $proxy = new Queued_XMPP(common_config('xmpp', 'host') ? + common_config('xmpp', 'host') : + common_config('xmpp', 'server'), + common_config('xmpp', 'port'), + common_config('xmpp', 'user'), + common_config('xmpp', 'password'), + common_config('xmpp', 'resource') . 'daemon', + common_config('xmpp', 'server'), + common_config('xmpp', 'debug') ? + true : false, + common_config('xmpp', 'debug') ? + XMPPHP_Log::LEVEL_VERBOSE : null); + return $proxy; +} + /** * Lazy-connect the configured Jabber account to the configured server; * if already opened, the same connection will be returned. @@ -143,7 +164,7 @@ function jabber_connect($resource=null) } /** - * send a single notice to a given Jabber address + * Queue send for a single notice to a given Jabber address * * @param string $to JID to send the notice to * @param Notice $notice notice to send @@ -153,10 +174,7 @@ function jabber_connect($resource=null) function jabber_send_notice($to, $notice) { - $conn = jabber_connect(); - if (!$conn) { - return false; - } + $conn = jabber_proxy(); $profile = Profile::staticGet($notice->profile_id); if (!$profile) { common_log(LOG_WARNING, 'Refusing to send notice with ' . @@ -221,10 +239,7 @@ function jabber_format_entry($profile, $notice) function jabber_send_message($to, $body, $type='chat', $subject=null) { - $conn = jabber_connect(); - if (!$conn) { - return false; - } + $conn = jabber_proxy(); $conn->message($to, $body, $type, $subject); return true; } @@ -319,7 +334,7 @@ function jabber_special_presence($type, $to=null, $show=null, $status=null) } /** - * broadcast a notice to all subscribers and reply recipients + * Queue broadcast of a notice to all subscribers and reply recipients * * This function will send a notice to all subscribers on the local server * who have Jabber addresses, and have Jabber notification enabled, and @@ -354,7 +369,7 @@ function jabber_broadcast_notice($notice) $sent_to = array(); - $conn = jabber_connect(); + $conn = jabber_proxy(); $ni = $notice->whoGets(); @@ -389,14 +404,13 @@ function jabber_broadcast_notice($notice) 'Sending notice ' . $notice->id . ' to ' . $user->jabber, __FILE__); $conn->message($user->jabber, $msg, 'chat', null, $entry); - $conn->processTime(0); } return true; } /** - * send a notice to all public listeners + * Queue send of a notice to all public listeners * * For notices that are generated on the local system (by users), we can optionally * forward them to remote listeners by XMPP. @@ -429,7 +443,7 @@ function jabber_public_notice($notice) $msg = jabber_format_notice($profile, $notice); $entry = jabber_format_entry($profile, $notice); - $conn = jabber_connect(); + $conn = jabber_proxy(); foreach ($public as $address) { common_log(LOG_INFO, @@ -437,7 +451,6 @@ function jabber_public_notice($notice) ' to public listener ' . $address, __FILE__); $conn->message($address, $msg, 'chat', null, $entry); - $conn->processTime(0); } $profile->free(); } diff --git a/lib/jabberqueuehandler.php b/lib/jabberqueuehandler.php index b1518866d7..83471f2df7 100644 --- a/lib/jabberqueuehandler.php +++ b/lib/jabberqueuehandler.php @@ -34,14 +34,14 @@ class JabberQueueHandler extends QueueHandler return 'jabber'; } - function handle_notice($notice) + function handle($notice) { require_once(INSTALLDIR.'/lib/jabber.php'); try { return jabber_broadcast_notice($notice); } catch (XMPPHP_Exception $e) { $this->log(LOG_ERR, "Got an XMPPHP_Exception: " . $e->getMessage()); - exit(1); + return false; } } } diff --git a/lib/ombqueuehandler.php b/lib/ombqueuehandler.php index 3ffc1313bc..24896c784c 100644 --- a/lib/ombqueuehandler.php +++ b/lib/ombqueuehandler.php @@ -36,7 +36,7 @@ class OmbQueueHandler extends QueueHandler * @fixme doesn't currently report failure back to the queue manager * because omb_broadcast_notice() doesn't report it to us */ - function handle_notice($notice) + function handle($notice) { if ($this->is_remote($notice)) { $this->log(LOG_DEBUG, 'Ignoring remote notice ' . $notice->id); diff --git a/lib/pingqueuehandler.php b/lib/pingqueuehandler.php index 8bb2180786..4e4d74cb1a 100644 --- a/lib/pingqueuehandler.php +++ b/lib/pingqueuehandler.php @@ -30,7 +30,7 @@ class PingQueueHandler extends QueueHandler { return 'ping'; } - function handle_notice($notice) { + function handle($notice) { require_once INSTALLDIR . '/lib/ping.php'; return ping_broadcast_notice($notice); } diff --git a/lib/pluginqueuehandler.php b/lib/pluginqueuehandler.php index 24d5046997..9653ccad42 100644 --- a/lib/pluginqueuehandler.php +++ b/lib/pluginqueuehandler.php @@ -42,7 +42,7 @@ class PluginQueueHandler extends QueueHandler return 'plugin'; } - function handle_notice($notice) + function handle($notice) { Event::handle('HandleQueuedNotice', array(&$notice)); return true; diff --git a/lib/publicqueuehandler.php b/lib/publicqueuehandler.php index 9ea9ee73a3..c9edb8d5d7 100644 --- a/lib/publicqueuehandler.php +++ b/lib/publicqueuehandler.php @@ -23,7 +23,6 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { /** * Queue handler for pushing new notices to public XMPP subscribers. - * @fixme correct this exception handling */ class PublicQueueHandler extends QueueHandler { @@ -33,15 +32,14 @@ class PublicQueueHandler extends QueueHandler return 'public'; } - function handle_notice($notice) + function handle($notice) { require_once(INSTALLDIR.'/lib/jabber.php'); try { return jabber_public_notice($notice); } catch (XMPPHP_Exception $e) { $this->log(LOG_ERR, "Got an XMPPHP_Exception: " . $e->getMessage()); - die($e->getMessage()); + return false; } - return true; } } diff --git a/lib/queued_xmpp.php b/lib/queued_xmpp.php new file mode 100644 index 0000000000..4b890c4ca4 --- /dev/null +++ b/lib/queued_xmpp.php @@ -0,0 +1,117 @@ +. + * + * @category Network + * @package StatusNet + * @author Brion Vibber + * @copyright 2010 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET') && !defined('LACONICA')) { + exit(1); +} + +require_once INSTALLDIR . '/lib/jabber.php'; + +class Queued_XMPP extends XMPPHP_XMPP +{ + /** + * Constructor + * + * @param string $host + * @param integer $port + * @param string $user + * @param string $password + * @param string $resource + * @param string $server + * @param boolean $printlog + * @param string $loglevel + */ + public function __construct($host, $port, $user, $password, $resource, $server = null, $printlog = false, $loglevel = null) + { + parent::__construct($host, $port, $user, $password, $resource, $server, $printlog, $loglevel); + // Normally the fulljid isn't filled out until resource binding time; + // we need to save it here since we're not talking to a real server. + $this->fulljid = "{$this->basejid}/{$this->resource}"; + } + + /** + * Send a formatted message to the outgoing queue for later forwarding + * to a real XMPP connection. + * + * @param string $msg + */ + public function send($msg, $timeout=NULL) + { + $qm = QueueManager::get(); + $qm->enqueue(strval($msg), 'xmppout'); + } + + /** + * Since we'll be getting input through a queue system's run loop, + * we'll process one standalone message at a time rather than our + * own XMPP message pump. + * + * @param string $message + */ + public function processMessage($message) { + $frame = array_shift($this->frames); + xml_parse($this->parser, $frame->body, false); + } + + //@{ + /** + * Stream i/o functions disabled; push input through processMessage() + */ + public function connect($timeout = 30, $persistent = false, $sendinit = true) + { + throw new Exception("Can't connect to server from XMPP queue proxy."); + } + + public function disconnect() + { + throw new Exception("Can't connect to server from XMPP queue proxy."); + } + + public function process() + { + throw new Exception("Can't read stream from XMPP queue proxy."); + } + + public function processUntil($event, $timeout=-1) + { + throw new Exception("Can't read stream from XMPP queue proxy."); + } + + public function read() + { + throw new Exception("Can't read stream from XMPP queue proxy."); + } + + public function readyToProcess() + { + throw new Exception("Can't read stream from XMPP queue proxy."); + } + //@} +} + diff --git a/lib/queuehandler.php b/lib/queuehandler.php index 613be6e330..2909cd83b1 100644 --- a/lib/queuehandler.php +++ b/lib/queuehandler.php @@ -22,51 +22,20 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } /** * Base class for queue handlers. * - * As extensions of the Daemon class, each queue handler has the ability - * to launch itself in the background, at which point it'll pass control - * to the configured QueueManager class to poll for updates. + * As of 0.9, queue handlers are short-lived for items as they are + * dequeued by a QueueManager running in an IoMaster in a daemon + * such as queuedaemon.php. + * + * Extensions requiring long-running maintenance or polling should + * register an IoManager. * * Subclasses must override at least the following methods: * - transport - * - handle_notice + * - handle */ -#class QueueHandler extends Daemon class QueueHandler { -# function __construct($id=null, $daemonize=true) -# { -# parent::__construct($daemonize); -# -# if ($id) { -# $this->set_id($id); -# } -# } - - /** - * How many seconds a polling-based queue manager should wait between - * checks for new items to handle. - * - * Defaults to 60 seconds; override to speed up or slow down. - * - * @fixme not really compatible with global queue manager - * @return int timeout in seconds - */ -# function timeout() -# { -# return 60; -# } - -# function class_name() -# { -# return ucfirst($this->transport()) . 'Handler'; -# } - -# function name() -# { -# return strtolower($this->class_name().'.'.$this->get_id()); -# } - /** * Return transport keyword which identifies items this queue handler * services; must be defined for all subclasses. @@ -83,61 +52,17 @@ class QueueHandler /** * Here's the meat of your queue handler -- you're handed a Notice - * object, which you may do as you will with. + * or other object, which you may do as you will with. * * If this function indicates failure, a warning will be logged * and the item is placed back in the queue to be re-run. * - * @param Notice $notice + * @param mixed $object * @return boolean true on success, false on failure */ - function handle_notice($notice) + function handle($object) { return true; } - - /** - * Setup and start of run loop for this queue handler as a daemon. - * Most of the heavy lifting is passed on to the QueueManager's service() - * method, which passes control back to our handle_notice() method for - * each notice that comes in on the queue. - * - * Most of the time this won't need to be overridden in a subclass. - * - * @return boolean true on success, false on failure - */ - function run() - { - if (!$this->start()) { - $this->log(LOG_WARNING, 'failed to start'); - return false; - } - - $this->log(LOG_INFO, 'checking for queued notices'); - - $queue = $this->transport(); - $timeout = $this->timeout(); - - $qm = QueueManager::get(); - - $qm->service($queue, $this); - - $this->log(LOG_INFO, 'finished servicing the queue'); - - if (!$this->finish()) { - $this->log(LOG_WARNING, 'failed to clean up'); - return false; - } - - $this->log(LOG_INFO, 'terminating normally'); - - return true; - } - - - function log($level, $msg) - { - common_log($level, $this->class_name() . ' ('. $this->get_id() .'): '.$msg); - } } diff --git a/lib/queuemanager.php b/lib/queuemanager.php index 291174d3c4..4eb39bfa8c 100644 --- a/lib/queuemanager.php +++ b/lib/queuemanager.php @@ -39,6 +39,10 @@ abstract class QueueManager extends IoManager { static $qm = null; + public $master = null; + public $handlers = array(); + public $groups = array(); + /** * Factory function to pull the appropriate QueueManager object * for this site's configuration. It can then be used to queue @@ -109,6 +113,64 @@ abstract class QueueManager extends IoManager */ abstract function enqueue($object, $queue); + /** + * Build a representation for an object for logging + * @param mixed + * @return string + */ + function logrep($object) { + if (is_object($object)) { + $class = get_class($object); + if (isset($object->id)) { + return "$class $object->id"; + } + return $class; + } + if (is_string($object)) { + $len = strlen($object); + $fragment = mb_substr($object, 0, 32); + if (mb_strlen($object) > 32) { + $fragment .= '...'; + } + return "string '$fragment' ($len bytes)"; + } + return strval($object); + } + + /** + * Encode an object for queued storage. + * Next gen may use serialization. + * + * @param mixed $object + * @return string + */ + protected function encode($object) + { + if ($object instanceof Notice) { + return $object->id; + } else if (is_string($object)) { + return $object; + } else { + throw new ServerException("Can't queue this type", 500); + } + } + + /** + * Decode an object from queued storage. + * Accepts back-compat notice reference entries and strings for now. + * + * @param string + * @return mixed + */ + protected function decode($frame) + { + if (is_numeric($frame)) { + return Notice::staticGet(intval($frame)); + } else { + return $frame; + } + } + /** * Instantiate the appropriate QueueHandler class for the given queue. * @@ -131,13 +193,15 @@ abstract class QueueManager extends IoManager } /** - * Get a list of all registered queue transport names. + * Get a list of registered queue transport names to be used + * for this daemon. * * @return array of strings */ function getQueues() { - return array_keys($this->handlers); + $group = $this->activeGroup(); + return array_keys($this->groups[$group]); } /** @@ -148,33 +212,29 @@ abstract class QueueManager extends IoManager */ function initialize() { + // @fixme we'll want to be able to listen to particular queues... if (Event::handle('StartInitializeQueueManager', array($this))) { - if (!defined('XMPP_ONLY_FLAG')) { // hack! - $this->connect('plugin', 'PluginQueueHandler'); - $this->connect('omb', 'OmbQueueHandler'); - $this->connect('ping', 'PingQueueHandler'); - if (common_config('sms', 'enabled')) { - $this->connect('sms', 'SmsQueueHandler'); - } + $this->connect('plugin', 'PluginQueueHandler'); + $this->connect('omb', 'OmbQueueHandler'); + $this->connect('ping', 'PingQueueHandler'); + if (common_config('sms', 'enabled')) { + $this->connect('sms', 'SmsQueueHandler'); } // XMPP output handlers... - if (common_config('xmpp', 'enabled') && !defined('XMPP_EMERGENCY_FLAG')) { - $this->connect('jabber', 'JabberQueueHandler'); - $this->connect('public', 'PublicQueueHandler'); - - // @fixme this should move up a level or should get an actual queue - $this->connect('confirm', 'XmppConfirmHandler'); - } + $this->connect('jabber', 'JabberQueueHandler'); + $this->connect('public', 'PublicQueueHandler'); + + // @fixme this should get an actual queue + //$this->connect('confirm', 'XmppConfirmHandler'); + + // For compat with old plugins not registering their own handlers. + $this->connect('plugin', 'PluginQueueHandler'); + + $this->connect('xmppout', 'XmppOutQueueHandler', 'xmppdaemon'); - if (!defined('XMPP_ONLY_FLAG')) { // hack! - // For compat with old plugins not registering their own handlers. - $this->connect('plugin', 'PluginQueueHandler'); - } - } - if (!defined('XMPP_ONLY_FLAG')) { // hack! - Event::handle('EndInitializeQueueManager', array($this)); } + Event::handle('EndInitializeQueueManager', array($this)); } /** @@ -183,10 +243,27 @@ abstract class QueueManager extends IoManager * * @param string $transport * @param string $class + * @param string $group */ - public function connect($transport, $class) + public function connect($transport, $class, $group='queuedaemon') { $this->handlers[$transport] = $class; + $this->groups[$group][$transport] = $class; + } + + /** + * @return string queue group to use for this request + */ + function activeGroup() + { + $group = 'queuedaemon'; + if ($this->master) { + // hack hack + if ($this->master instanceof XmppMaster) { + return 'xmppdaemon'; + } + } + return $group; } /** diff --git a/lib/smsqueuehandler.php b/lib/smsqueuehandler.php index 48a96409d0..6085d2b4ac 100644 --- a/lib/smsqueuehandler.php +++ b/lib/smsqueuehandler.php @@ -31,7 +31,7 @@ class SmsQueueHandler extends QueueHandler return 'sms'; } - function handle_notice($notice) + function handle($notice) { require_once(INSTALLDIR.'/lib/mail.php'); return mail_broadcast_notice_sms($notice); diff --git a/lib/spawningdaemon.php b/lib/spawningdaemon.php new file mode 100644 index 0000000000..8baefe88e8 --- /dev/null +++ b/lib/spawningdaemon.php @@ -0,0 +1,159 @@ +. + */ + +/** + * Base class for daemon that can launch one or more processing threads, + * respawning them if they exit. + * + * This is mainly intended for indefinite workloads such as monitoring + * a queue or maintaining an IM channel. + * + * Child classes should implement the + * + * We can then pass individual items through the QueueHandler subclasses + * they belong to. We additionally can handle queues for multiple sites. + * + * @package QueueHandler + * @author Brion Vibber + */ +abstract class SpawningDaemon extends Daemon +{ + protected $threads=1; + + function __construct($id=null, $daemonize=true, $threads=1) + { + parent::__construct($daemonize); + + if ($id) { + $this->set_id($id); + } + $this->threads = $threads; + } + + /** + * Perform some actual work! + * + * @return boolean true on success, false on failure + */ + public abstract function runThread(); + + /** + * Spawn one or more background processes and let them start running. + * Each individual process will execute whatever's in the runThread() + * method, which should be overridden. + * + * Child processes will be automatically respawned when they exit. + * + * @todo possibly allow for not respawning on "normal" exits... + * though ParallelizingDaemon is probably better for workloads + * that have forseeable endpoints. + */ + function run() + { + $children = array(); + for ($i = 1; $i <= $this->threads; $i++) { + $pid = pcntl_fork(); + if ($pid < 0) { + $this->log(LOG_ERROR, "Couldn't fork for thread $i; aborting\n"); + exit(1); + } else if ($pid == 0) { + $this->initAndRunChild($i); + } else { + $this->log(LOG_INFO, "Spawned thread $i as pid $pid"); + $children[$i] = $pid; + } + } + + $this->log(LOG_INFO, "Waiting for children to complete."); + while (count($children) > 0) { + $status = null; + $pid = pcntl_wait($status); + if ($pid > 0) { + $i = array_search($pid, $children); + if ($i === false) { + $this->log(LOG_ERR, "Unrecognized child pid $pid exited!"); + continue; + } + unset($children[$i]); + $this->log(LOG_INFO, "Thread $i pid $pid exited."); + + $pid = pcntl_fork(); + if ($pid < 0) { + $this->log(LOG_ERROR, "Couldn't fork to respawn thread $i; aborting thread.\n"); + } else if ($pid == 0) { + $this->initAndRunChild($i); + } else { + $this->log(LOG_INFO, "Respawned thread $i as pid $pid"); + $children[$i] = $pid; + } + } + } + $this->log(LOG_INFO, "All child processes complete."); + return true; + } + + /** + * Initialize things for a fresh thread, call runThread(), and + * exit at completion with appropriate return value. + */ + protected function initAndRunChild($thread) + { + $this->set_id($this->get_id() . "." . $thread); + $this->resetDb(); + $ok = $this->runThread(); + exit($ok ? 0 : 1); + } + + /** + * Reconnect to the database for each child process, + * or they'll get very confused trying to use the + * same socket. + */ + protected function resetDb() + { + // @fixme do we need to explicitly open the db too + // or is this implied? + global $_DB_DATAOBJECT; + unset($_DB_DATAOBJECT['CONNECTIONS']); + + // Reconnect main memcached, or threads will stomp on + // each other and corrupt their requests. + $cache = common_memcache(); + if ($cache) { + $cache->reconnect(); + } + + // Also reconnect memcached for status_network table. + if (!empty(Status_network::$cache)) { + Status_network::$cache->close(); + Status_network::$cache = null; + } + } + + function log($level, $msg) + { + common_log($level, get_class($this) . ' ('. $this->get_id() .'): '.$msg); + } + + function name() + { + return strtolower(get_class($this).'.'.$this->get_id()); + } +} + diff --git a/lib/stompqueuemanager.php b/lib/stompqueuemanager.php index 00590fdb69..f057bd9e41 100644 --- a/lib/stompqueuemanager.php +++ b/lib/stompqueuemanager.php @@ -39,7 +39,6 @@ class StompQueueManager extends QueueManager var $base = null; var $con = null; - protected $master = null; protected $sites = array(); function __construct() @@ -104,11 +103,12 @@ class StompQueueManager extends QueueManager */ function getQueues() { + $group = $this->activeGroup(); $site = common_config('site', 'server'); - if (empty($this->handlers[$site])) { + if (empty($this->groups[$site][$group])) { return array(); } else { - return array_keys($this->handlers[$site]); + return array_keys($this->groups[$site][$group]); } } @@ -118,10 +118,12 @@ class StompQueueManager extends QueueManager * * @param string $transport * @param string $class + * @param string $group */ - public function connect($transport, $class) + public function connect($transport, $class, $group='queuedaemon') { $this->handlers[common_config('site', 'server')][$transport] = $class; + $this->groups[common_config('site', 'server')][$group][$transport] = $class; } /** @@ -130,23 +132,23 @@ class StompQueueManager extends QueueManager */ public function enqueue($object, $queue) { - $notice = $object; + $msg = $this->encode($object); + $rep = $this->logrep($object); $this->_connect(); // XXX: serialize and send entire notice $result = $this->con->send($this->queueName($queue), - $notice->id, // BODY of the message - array ('created' => $notice->created)); + $msg, // BODY of the message + array ('created' => common_sql_now())); if (!$result) { - common_log(LOG_ERR, 'Error sending to '.$queue.' queue'); + common_log(LOG_ERR, "Error sending $rep to $queue queue"); return false; } - common_log(LOG_DEBUG, 'complete remote queueing notice ID = ' - . $notice->id . ' for ' . $queue); + common_log(LOG_DEBUG, "complete remote queueing $rep for $queue"); $this->stats('enqueued', $queue); } @@ -174,7 +176,7 @@ class StompQueueManager extends QueueManager $ok = true; $frames = $this->con->readFrames(); foreach ($frames as $frame) { - $ok = $ok && $this->_handleNotice($frame); + $ok = $ok && $this->_handleItem($frame); } return $ok; } @@ -265,7 +267,7 @@ class StompQueueManager extends QueueManager } /** - * Handle and acknowledge a notice event that's come in through a queue. + * Handle and acknowledge an event that's come in through a queue. * * If the queue handler reports failure, the message is requeued for later. * Missing notices or handler classes will drop the message. @@ -276,7 +278,7 @@ class StompQueueManager extends QueueManager * @param StompFrame $frame * @return bool */ - protected function _handleNotice($frame) + protected function _handleItem($frame) { list($site, $queue) = $this->parseDestination($frame->headers['destination']); if ($site != common_config('site', 'server')) { @@ -284,15 +286,23 @@ class StompQueueManager extends QueueManager StatusNet::init($site); } - $id = intval($frame->body); - $info = "notice $id posted at {$frame->headers['created']} in queue $queue"; + if (is_numeric($frame->body)) { + $id = intval($frame->body); + $info = "notice $id posted at {$frame->headers['created']} in queue $queue"; - $notice = Notice::staticGet('id', $id); - if (empty($notice)) { - $this->_log(LOG_WARNING, "Skipping missing $info"); - $this->con->ack($frame); - $this->stats('badnotice', $queue); - return false; + $notice = Notice::staticGet('id', $id); + if (empty($notice)) { + $this->_log(LOG_WARNING, "Skipping missing $info"); + $this->con->ack($frame); + $this->stats('badnotice', $queue); + return false; + } + + $item = $notice; + } else { + // @fixme should we serialize, or json, or what here? + $info = "string posted at {$frame->headers['created']} in queue $queue"; + $item = $frame->body; } $handler = $this->getHandler($queue); @@ -303,7 +313,7 @@ class StompQueueManager extends QueueManager return false; } - $ok = $handler->handle_notice($notice); + $ok = $handler->handle($item); if (!$ok) { $this->_log(LOG_WARNING, "Failed handling $info"); @@ -311,7 +321,7 @@ class StompQueueManager extends QueueManager // this kind of queue management ourselves; // if we don't ack, it should resend... $this->con->ack($frame); - $this->enqueue($notice, $queue); + $this->enqueue($item, $queue); $this->stats('requeued', $queue); return false; } diff --git a/lib/util.php b/lib/util.php index ef8a5d1f02..fb3b8be876 100644 --- a/lib/util.php +++ b/lib/util.php @@ -1130,7 +1130,8 @@ function common_request_id() $pid = getmypid(); $server = common_config('site', 'server'); if (php_sapi_name() == 'cli') { - return "$server:$pid"; + $script = basename($_SERVER['PHP_SELF']); + return "$server:$script:$pid"; } else { static $req_id = null; if (!isset($req_id)) { diff --git a/lib/xmppconfirmmanager.php b/lib/xmppconfirmmanager.php deleted file mode 100644 index ee4e294fd4..0000000000 --- a/lib/xmppconfirmmanager.php +++ /dev/null @@ -1,168 +0,0 @@ -. - */ - -if (!defined('STATUSNET') && !defined('LACONICA')) { - exit(1); -} - -/** - * Event handler for pushing new confirmations to Jabber users. - * @fixme recommend redoing this on a queue-trigger model - * @fixme expiration of old items got dropped in the past, put it back? - */ -class XmppConfirmManager extends IoManager -{ - - /** - * @return mixed XmppConfirmManager, or false if unneeded - */ - public static function get() - { - if (common_config('xmpp', 'enabled')) { - $site = common_config('site', 'server'); - return new XmppConfirmManager(); - } else { - return false; - } - } - - /** - * Tell the i/o master we need one instance for each supporting site - * being handled in this process. - */ - public static function multiSite() - { - return IoManager::INSTANCE_PER_SITE; - } - - function __construct() - { - $this->site = common_config('site', 'server'); - } - - /** - * 10 seconds? Really? That seems a bit frequent. - */ - function pollInterval() - { - return 10; - } - - /** - * Ping! - * @return boolean true if we found something - */ - function poll() - { - $this->switchSite(); - $confirm = $this->next_confirm(); - if ($confirm) { - $this->handle_confirm($confirm); - return true; - } else { - return false; - } - } - - protected function handle_confirm($confirm) - { - require_once INSTALLDIR . '/lib/jabber.php'; - - common_log(LOG_INFO, 'Sending confirmation for ' . $confirm->address); - $user = User::staticGet($confirm->user_id); - if (!$user) { - common_log(LOG_WARNING, 'Confirmation for unknown user ' . $confirm->user_id); - return; - } - $success = jabber_confirm_address($confirm->code, - $user->nickname, - $confirm->address); - if (!$success) { - common_log(LOG_ERR, 'Confirmation failed for ' . $confirm->address); - # Just let the claim age out; hopefully things work then - return; - } else { - common_log(LOG_INFO, 'Confirmation sent for ' . $confirm->address); - # Mark confirmation sent; need a dupe so we don't have the WHERE clause - $dupe = Confirm_address::staticGet('code', $confirm->code); - if (!$dupe) { - common_log(LOG_WARNING, 'Could not refetch confirm', __FILE__); - return; - } - $orig = clone($dupe); - $dupe->sent = $dupe->claimed; - $result = $dupe->update($orig); - if (!$result) { - common_log_db_error($dupe, 'UPDATE', __FILE__); - # Just let the claim age out; hopefully things work then - return; - } - } - return true; - } - - protected function next_confirm() - { - $confirm = new Confirm_address(); - $confirm->whereAdd('claimed IS null'); - $confirm->whereAdd('sent IS null'); - # XXX: eventually we could do other confirmations in the queue, too - $confirm->address_type = 'jabber'; - $confirm->orderBy('modified DESC'); - $confirm->limit(1); - if ($confirm->find(true)) { - common_log(LOG_INFO, 'Claiming confirmation for ' . $confirm->address); - # working around some weird DB_DataObject behaviour - $confirm->whereAdd(''); # clears where stuff - $original = clone($confirm); - $confirm->claimed = common_sql_now(); - $result = $confirm->update($original); - if ($result) { - common_log(LOG_INFO, 'Succeeded in claim! '. $result); - return $confirm; - } else { - common_log(LOG_INFO, 'Failed in claim!'); - return false; - } - } - return null; - } - - protected function clear_old_confirm_claims() - { - $confirm = new Confirm(); - $confirm->claimed = null; - $confirm->whereAdd('now() - claimed > '.CLAIM_TIMEOUT); - $confirm->update(DB_DATAOBJECT_WHEREADD_ONLY); - $confirm->free(); - unset($confirm); - } - - /** - * Make sure we're on the right site configuration - */ - protected function switchSite() - { - if ($this->site != common_config('site', 'server')) { - common_log(LOG_DEBUG, __METHOD__ . ": switching to site $this->site"); - $this->stats('switch'); - StatusNet::init($this->site); - } - } -} diff --git a/lib/xmppmanager.php b/lib/xmppmanager.php index dfff63a30c..299175dd7d 100644 --- a/lib/xmppmanager.php +++ b/lib/xmppmanager.php @@ -70,6 +70,7 @@ class XmppManager extends IoManager function __construct() { $this->site = common_config('site', 'server'); + $this->resource = common_config('xmpp', 'resource') . 'daemon'; } /** @@ -86,15 +87,19 @@ class XmppManager extends IoManager # Low priority; we don't want to receive messages common_log(LOG_INFO, "INITIALIZE"); - $this->conn = jabber_connect($this->resource()); + $this->conn = jabber_connect($this->resource); if (empty($this->conn)) { common_log(LOG_ERR, "Couldn't connect to server."); return false; } - $this->conn->addEventHandler('message', 'forward_message', $this); + $this->log(LOG_DEBUG, "Initializing stanza handlers."); + + $this->conn->addEventHandler('message', 'handle_message', $this); + $this->conn->addEventHandler('presence', 'handle_presence', $this); $this->conn->addEventHandler('reconnect', 'handle_reconnect', $this); + $this->conn->setReconnectTimeout(600); jabber_send_presence("Send me a message to post a notice", 'available', null, 'available', -1); @@ -175,12 +180,37 @@ class XmppManager extends IoManager } } + /** + * For queue handlers to pass us a message to push out, + * if we're active. + * + * @fixme should this be blocking etc? + * + * @param string $msg XML stanza to send + * @return boolean success + */ + public function send($msg) + { + if ($this->conn && !$this->conn->isDisconnected()) { + $bytes = $this->conn->send($msg); + if ($bytes > 0) { + $this->conn->processTime(0); + return true; + } else { + return false; + } + } else { + // Can't send right now... + return false; + } + } + /** * Send a keepalive ping to the XMPP server. */ protected function sendPing() { - $jid = jabber_daemon_address().'/'.$this->resource(); + $jid = jabber_daemon_address().'/'.$this->resource; $server = common_config('xmpp', 'server'); if (!isset($this->pingid)) { @@ -206,61 +236,239 @@ class XmppManager extends IoManager $this->conn->presence(null, 'available', null, 'available', -1); } - /** - * Callback for Jabber message event. - * - * This connection handles output; if we get a message straight to us, - * forward it on to our XmppDaemon listener for processing. - * - * @param $pl - */ - function forward_message(&$pl) + + function get_user($from) { + $user = User::staticGet('jabber', jabber_normalize_jid($from)); + return $user; + } + + /** + * XMPP callback for handling message input... + * @param array $pl XMPP payload + */ + function handle_message(&$pl) + { + $from = jabber_normalize_jid($pl['from']); + if ($pl['type'] != 'chat') { - common_log(LOG_DEBUG, 'Ignoring message of type ' . $pl['type'] . ' from ' . $pl['from']); + $this->log(LOG_WARNING, "Ignoring message of type ".$pl['type']." from $from."); return; } - $listener = $this->listener(); - if (strtolower($listener) == strtolower($pl['from'])) { - common_log(LOG_WARNING, 'Ignoring loop message.'); + + if (mb_strlen($pl['body']) == 0) { + $this->log(LOG_WARNING, "Ignoring message with empty body from $from."); return; } - common_log(LOG_INFO, 'Forwarding message from ' . $pl['from'] . ' to ' . $listener); - $this->conn->message($this->listener(), $pl['body'], 'chat', null, $this->ofrom($pl['from'])); - } - /** - * Build an block with an ofrom entry for forwarded messages - * - * @param string $from Jabber ID of original sender - * @return string XML fragment - */ - protected function ofrom($from) - { - $address = "\n"; - $address .= "
\n"; - $address .= "\n"; - return $address; - } + // Forwarded from another daemon for us to handle; this shouldn't + // happen any more but we might get some legacy items. + if ($this->is_self($from)) { + $this->log(LOG_INFO, "Got forwarded notice from self ($from)."); + $from = $this->get_ofrom($pl); + $this->log(LOG_INFO, "Originally sent by $from."); + if (is_null($from) || $this->is_self($from)) { + $this->log(LOG_INFO, "Ignoring notice originally sent by $from."); + return; + } + } - /** - * Build the complete JID of the XmppDaemon process which - * handles primary XMPP input for this site. - * - * @return string Jabber ID - */ - protected function listener() - { - if (common_config('xmpp', 'listener')) { - return common_config('xmpp', 'listener'); + $user = $this->get_user($from); + + // For common_current_user to work + global $_cur; + $_cur = $user; + + if (!$user) { + $this->from_site($from, 'Unknown user; go to ' . + common_local_url('imsettings') . + ' to add your address to your account'); + $this->log(LOG_WARNING, 'Message from unknown user ' . $from); + return; + } + if ($this->handle_command($user, $pl['body'])) { + $this->log(LOG_INFO, "Command message by $from handled."); + return; + } else if ($this->is_autoreply($pl['body'])) { + $this->log(LOG_INFO, 'Ignoring auto reply from ' . $from); + return; + } else if ($this->is_otr($pl['body'])) { + $this->log(LOG_INFO, 'Ignoring OTR from ' . $from); + return; } else { - return jabber_daemon_address() . '/' . common_config('xmpp','resource') . 'daemon'; + + $this->log(LOG_INFO, 'Posting a notice from ' . $user->nickname); + + $this->add_notice($user, $pl); + } + + $user->free(); + unset($user); + unset($_cur); + + unset($pl['xml']); + $pl['xml'] = null; + + $pl = null; + unset($pl); + } + + + function is_self($from) + { + return preg_match('/^'.strtolower(jabber_daemon_address()).'/', strtolower($from)); + } + + function get_ofrom($pl) + { + $xml = $pl['xml']; + $addresses = $xml->sub('addresses'); + if (!$addresses) { + $this->log(LOG_WARNING, 'Forwarded message without addresses'); + return null; + } + $address = $addresses->sub('address'); + if (!$address) { + $this->log(LOG_WARNING, 'Forwarded message without address'); + return null; + } + if (!array_key_exists('type', $address->attrs)) { + $this->log(LOG_WARNING, 'No type for forwarded message'); + return null; + } + $type = $address->attrs['type']; + if ($type != 'ofrom') { + $this->log(LOG_WARNING, 'Type of forwarded message is not ofrom'); + return null; + } + if (!array_key_exists('jid', $address->attrs)) { + $this->log(LOG_WARNING, 'No jid for forwarded message'); + return null; + } + $jid = $address->attrs['jid']; + if (!$jid) { + $this->log(LOG_WARNING, 'Could not get jid from address'); + return null; + } + $this->log(LOG_DEBUG, 'Got message forwarded from jid ' . $jid); + return $jid; + } + + function is_autoreply($txt) + { + if (preg_match('/[\[\(]?[Aa]uto[-\s]?[Rr]e(ply|sponse)[\]\)]/', $txt)) { + return true; + } else if (preg_match('/^System: Message wasn\'t delivered. Offline storage size was exceeded.$/', $txt)) { + return true; + } else { + return false; } } - protected function resource() + function is_otr($txt) { - return 'queue' . posix_getpid(); // @fixme PIDs won't be host-unique + if (preg_match('/^\?OTR/', $txt)) { + return true; + } else { + return false; + } + } + + function from_site($address, $msg) + { + $text = '['.common_config('site', 'name') . '] ' . $msg; + jabber_send_message($address, $text); + } + + function handle_command($user, $body) + { + $inter = new CommandInterpreter(); + $cmd = $inter->handle_command($user, $body); + if ($cmd) { + $chan = new XMPPChannel($this->conn); + $cmd->execute($chan); + return true; + } else { + return false; + } + } + + function add_notice(&$user, &$pl) + { + $body = trim($pl['body']); + $content_shortened = common_shorten_links($body); + if (Notice::contentTooLong($content_shortened)) { + $from = jabber_normalize_jid($pl['from']); + $this->from_site($from, sprintf(_('Message too long - maximum is %1$d characters, you sent %2$d.'), + Notice::maxContent(), + mb_strlen($content_shortened))); + return; + } + + try { + $notice = Notice::saveNew($user->id, $content_shortened, 'xmpp'); + } catch (Exception $e) { + $this->log(LOG_ERR, $e->getMessage()); + $this->from_site($user->jabber, $e->getMessage()); + return; + } + + common_broadcast_notice($notice); + $this->log(LOG_INFO, + 'Added notice ' . $notice->id . ' from user ' . $user->nickname); + $notice->free(); + unset($notice); + } + + function handle_presence(&$pl) + { + $from = jabber_normalize_jid($pl['from']); + switch ($pl['type']) { + case 'subscribe': + # We let anyone subscribe + $this->subscribed($from); + $this->log(LOG_INFO, + 'Accepted subscription from ' . $from); + break; + case 'subscribed': + case 'unsubscribed': + case 'unsubscribe': + $this->log(LOG_INFO, + 'Ignoring "' . $pl['type'] . '" from ' . $from); + break; + default: + if (!$pl['type']) { + $user = User::staticGet('jabber', $from); + if (!$user) { + $this->log(LOG_WARNING, 'Presence from unknown user ' . $from); + return; + } + if ($user->updatefrompresence) { + $this->log(LOG_INFO, 'Updating ' . $user->nickname . + ' status from presence.'); + $this->add_notice($user, $pl); + } + $user->free(); + unset($user); + } + break; + } + unset($pl['xml']); + $pl['xml'] = null; + + $pl = null; + unset($pl); + } + + function log($level, $msg) + { + $text = 'XMPPDaemon('.$this->resource.'): '.$msg; + common_log($level, $text); + } + + function subscribed($to) + { + jabber_special_presence('subscribed', $to); } /** diff --git a/lib/xmppoutqueuehandler.php b/lib/xmppoutqueuehandler.php new file mode 100644 index 0000000000..2afa260f18 --- /dev/null +++ b/lib/xmppoutqueuehandler.php @@ -0,0 +1,55 @@ +. + */ + +/** + * Queue handler for pre-processed outgoing XMPP messages. + * Formatted XML stanzas will have been pushed into the queue + * via the Queued_XMPP connection proxy, probably from some + * other queue processor. + * + * Here, the XML stanzas are simply pulled out of the queue and + * pushed out over the wire; an XmppManager is needed to set up + * and maintain the actual server connection. + * + * This queue will be run via XmppDaemon rather than QueueDaemon. + * + * @author Brion Vibber + */ +class XmppOutQueueHandler extends QueueHandler +{ + function transport() { + return 'xmppout'; + } + + /** + * Take a previously-queued XMPP stanza and send it out ot the server. + * @param string $msg + * @return boolean true on success + */ + function handle($msg) + { + assert(is_string($msg)); + + $xmpp = XmppManager::get(); + $ok = $xmpp->send($msg); + + return $ok; + } +} + diff --git a/plugins/Enjit/enjitqueuehandler.php b/plugins/Enjit/enjitqueuehandler.php index f0e706b929..14085cc5e3 100644 --- a/plugins/Enjit/enjitqueuehandler.php +++ b/plugins/Enjit/enjitqueuehandler.php @@ -32,14 +32,7 @@ class EnjitQueueHandler extends QueueHandler return 'enjit'; } - function start() - { - $this->log(LOG_INFO, "Starting EnjitQueueHandler"); - $this->log(LOG_INFO, "Broadcasting to ".common_config('enjit', 'apiurl')); - return true; - } - - function handle_notice($notice) + function handle($notice) { $profile = Profile::staticGet($notice->profile_id); diff --git a/plugins/Facebook/facebookqueuehandler.php b/plugins/Facebook/facebookqueuehandler.php index 1778690e5b..524af7bc45 100644 --- a/plugins/Facebook/facebookqueuehandler.php +++ b/plugins/Facebook/facebookqueuehandler.php @@ -28,7 +28,7 @@ class FacebookQueueHandler extends QueueHandler return 'facebook'; } - function handle_notice($notice) + function handle($notice) { if ($this->_isLocal($notice)) { return facebookBroadcastNotice($notice); diff --git a/plugins/RSSCloud/RSSCloudPlugin.php b/plugins/RSSCloud/RSSCloudPlugin.php index 2de162628f..9f444c8bba 100644 --- a/plugins/RSSCloud/RSSCloudPlugin.php +++ b/plugins/RSSCloud/RSSCloudPlugin.php @@ -138,6 +138,9 @@ class RSSCloudPlugin extends Plugin case 'RSSCloudNotifier': include_once INSTALLDIR . '/plugins/RSSCloud/RSSCloudNotifier.php'; return false; + case 'RSSCloudQueueHandler': + include_once INSTALLDIR . '/plugins/RSSCloud/RSSCloudQueueHandler.php'; + return false; case 'RSSCloudRequestNotifyAction': case 'LoggingAggregatorAction': include_once INSTALLDIR . '/plugins/RSSCloud/' . @@ -193,32 +196,6 @@ class RSSCloudPlugin extends Plugin return true; } - /** - * broadcast the message when not using queuehandler - * - * @param Notice &$notice the notice - * @param array $queue destination queue - * - * @return boolean hook return - */ - - function onUnqueueHandleNotice(&$notice, $queue) - { - if (($queue == 'rsscloud') && ($this->_isLocal($notice))) { - - common_debug('broadcasting rssCloud bound notice ' . $notice->id); - - $profile = $notice->getProfile(); - - $notifier = new RSSCloudNotifier(); - $notifier->notify($profile); - - return false; - } - - return true; - } - /** * Determine whether the notice was locally created * @@ -261,19 +238,15 @@ class RSSCloudPlugin extends Plugin } /** - * Add RSSCloudQueueHandler to the list of valid daemons to - * start + * Register RSSCloud notice queue handler * - * @param array $daemons the list of daemons to run + * @param QueueManager $manager * * @return boolean hook return - * */ - - function onGetValidDaemons($daemons) + function onEndInitializeQueueManager($manager) { - array_push($daemons, INSTALLDIR . - '/plugins/RSSCloud/RSSCloudQueueHandler.php'); + $manager->connect('rsscloud', 'RSSCloudQueueHandler'); return true; } diff --git a/plugins/RSSCloud/RSSCloudQueueHandler.php b/plugins/RSSCloud/RSSCloudQueueHandler.php old mode 100755 new mode 100644 index 693dd27c1f..295c261895 --- a/plugins/RSSCloud/RSSCloudQueueHandler.php +++ b/plugins/RSSCloud/RSSCloudQueueHandler.php @@ -1,4 +1,3 @@ -#!/usr/bin/env php . */ -define('INSTALLDIR', realpath(dirname(__FILE__) . '/../..')); - -$shortoptions = 'i::'; -$longoptions = array('id::'); - -$helptext = <<log(LOG_INFO, "INITIALIZE"); - $this->notifier = new RSSCloudNotifier(); - return true; - } - - function handle_notice($notice) + function handle($notice) { $profile = $notice->getProfile(); - return $this->notifier->notify($profile); + $notifier = new RSSCloudNotifier(); + return $notifier->notify($profile); } - - function finish() - { - } - } -if (have_option('i')) { - $id = get_option_value('i'); -} else if (have_option('--id')) { - $id = get_option_value('--id'); -} else if (count($args) > 0) { - $id = $args[0]; -} else { - $id = null; -} - -$handler = new RSSCloudQueueHandler($id); - -$handler->runOnce(); diff --git a/plugins/TwitterBridge/twitterqueuehandler.php b/plugins/TwitterBridge/twitterqueuehandler.php index 5089ca7b74..b5a624e83d 100644 --- a/plugins/TwitterBridge/twitterqueuehandler.php +++ b/plugins/TwitterBridge/twitterqueuehandler.php @@ -28,7 +28,7 @@ class TwitterQueueHandler extends QueueHandler return 'twitter'; } - function handle_notice($notice) + function handle($notice) { return broadcast_twitter($notice); } diff --git a/scripts/handlequeued.php b/scripts/handlequeued.php index 9031437aac..8158849695 100755 --- a/scripts/handlequeued.php +++ b/scripts/handlequeued.php @@ -50,7 +50,7 @@ if (empty($notice)) { exit(1); } -if (!$handler->handle_notice($notice)) { +if (!$handler->handle($notice)) { print "Failed to handle notice id $noticeId on queue '$queue'.\n"; exit(1); } diff --git a/scripts/queuedaemon.php b/scripts/queuedaemon.php index 162f617e0d..a9cfda6d72 100755 --- a/scripts/queuedaemon.php +++ b/scripts/queuedaemon.php @@ -29,6 +29,8 @@ $longoptions = array('id=', 'foreground', 'all', 'threads=', 'skip-xmpp', 'xmpp- * * Recognizes Linux and Mac OS X; others will return default of 1. * + * @fixme move this to SpawningDaemon, but to get the default val for help + * text we seem to need it before loading infrastructure * @return intval */ function getProcessorCount() @@ -83,143 +85,29 @@ define('CLAIM_TIMEOUT', 1200); * We can then pass individual items through the QueueHandler subclasses * they belong to. */ -class QueueDaemon extends Daemon +class QueueDaemon extends SpawningDaemon { - protected $allsites; - protected $threads=1; + protected $allsites = false; function __construct($id=null, $daemonize=true, $threads=1, $allsites=false) { - parent::__construct($daemonize); - - if ($id) { - $this->set_id($id); - } + parent::__construct($id, $daemonize, $threads); $this->all = $allsites; - $this->threads = $threads; - } - - /** - * How many seconds a polling-based queue manager should wait between - * checks for new items to handle. - * - * Defaults to 60 seconds; override to speed up or slow down. - * - * @return int timeout in seconds - */ - function timeout() - { - return 60; - } - - function name() - { - return strtolower(get_class($this).'.'.$this->get_id()); - } - - function run() - { - if ($this->threads > 1) { - return $this->runThreads(); - } else { - return $this->runLoop(); - } - } - - function runThreads() - { - $children = array(); - for ($i = 1; $i <= $this->threads; $i++) { - $pid = pcntl_fork(); - if ($pid < 0) { - print "Couldn't fork for thread $i; aborting\n"; - exit(1); - } else if ($pid == 0) { - $this->runChild($i); - exit(0); - } else { - $this->log(LOG_INFO, "Spawned thread $i as pid $pid"); - $children[$i] = $pid; - } - } - - $this->log(LOG_INFO, "Waiting for children to complete."); - while (count($children) > 0) { - $status = null; - $pid = pcntl_wait($status); - if ($pid > 0) { - $i = array_search($pid, $children); - if ($i === false) { - $this->log(LOG_ERR, "Unrecognized child pid $pid exited!"); - continue; - } - unset($children[$i]); - $this->log(LOG_INFO, "Thread $i pid $pid exited."); - - $pid = pcntl_fork(); - if ($pid < 0) { - print "Couldn't fork to respawn thread $i; aborting thread.\n"; - } else if ($pid == 0) { - $this->runChild($i); - exit(0); - } else { - $this->log(LOG_INFO, "Respawned thread $i as pid $pid"); - $children[$i] = $pid; - } - } - } - $this->log(LOG_INFO, "All child processes complete."); - return true; - } - - function runChild($thread) - { - $this->set_id($this->get_id() . "." . $thread); - $this->resetDb(); - $this->runLoop(); - } - - /** - * Reconnect to the database for each child process, - * or they'll get very confused trying to use the - * same socket. - */ - function resetDb() - { - // @fixme do we need to explicitly open the db too - // or is this implied? - global $_DB_DATAOBJECT; - unset($_DB_DATAOBJECT['CONNECTIONS']); - - // Reconnect main memcached, or threads will stomp on - // each other and corrupt their requests. - $cache = common_memcache(); - if ($cache) { - $cache->reconnect(); - } - - // Also reconnect memcached for status_network table. - if (!empty(Status_network::$cache)) { - Status_network::$cache->close(); - Status_network::$cache = null; - } } /** * Setup and start of run loop for this queue handler as a daemon. * Most of the heavy lifting is passed on to the QueueManager's service() - * method, which passes control on to the QueueHandler's handle_notice() - * method for each notice that comes in on the queue. - * - * Most of the time this won't need to be overridden in a subclass. + * method, which passes control on to the QueueHandler's handle() + * method for each item that comes in on the queue. * * @return boolean true on success, false on failure */ - function runLoop() + function runThread() { $this->log(LOG_INFO, 'checking for queued notices'); - $master = new IoMaster($this->get_id()); + $master = new QueueMaster($this->get_id()); $master->init($this->all); $master->service(); @@ -229,10 +117,25 @@ class QueueDaemon extends Daemon return true; } +} - function log($level, $msg) +class QueueMaster extends IoMaster +{ + /** + * Initialize IoManagers for the currently configured site + * which are appropriate to this instance. + */ + function initManagers() { - common_log($level, get_class($this) . ' ('. $this->get_id() .'): '.$msg); + $classes = array(); + if (Event::handle('StartQueueDaemonIoManagers', array(&$classes))) { + $classes[] = 'QueueManager'; + } + Event::handle('EndQueueDaemonIoManagers', array(&$classes)); + + foreach ($classes as $class) { + $this->instantiate($class); + } } } diff --git a/scripts/xmppdaemon.php b/scripts/xmppdaemon.php index cef9c4bd07..fd7cf055b4 100755 --- a/scripts/xmppdaemon.php +++ b/scripts/xmppdaemon.php @@ -33,347 +33,46 @@ END_OF_XMPP_HELP; require_once INSTALLDIR.'/scripts/commandline.inc'; -require_once INSTALLDIR . '/lib/common.php'; require_once INSTALLDIR . '/lib/jabber.php'; -require_once INSTALLDIR . '/lib/daemon.php'; -# This is kind of clunky; we create a class to call the global functions -# in jabber.php, which create a new XMPP class. A more elegant (?) solution -# might be to use make this a subclass of XMPP. - -class XMPPDaemon extends Daemon +class XMPPDaemon extends SpawningDaemon { - function __construct($resource=null, $daemonize=true) + function __construct($id=null, $daemonize=true, $threads=1) { - parent::__construct($daemonize); - - static $attrs = array('server', 'port', 'user', 'password', 'host'); - - foreach ($attrs as $attr) - { - $this->$attr = common_config('xmpp', $attr); + if ($threads != 1) { + // This should never happen. :) + throw new Exception("XMPPDaemon can must run single-threaded"); } - - if ($resource) { - $this->resource = $resource . 'daemon'; - } else { - $this->resource = common_config('xmpp', 'resource') . 'daemon'; - } - - $this->jid = $this->user.'@'.$this->server.'/'.$this->resource; - - $this->log(LOG_INFO, "INITIALIZE XMPPDaemon {$this->jid}"); + parent::__construct($id, $daemonize, $threads); } - function connect() + function runThread() { - $connect_to = ($this->host) ? $this->host : $this->server; + common_log(LOG_INFO, 'Waiting to listen to XMPP and queues'); - $this->log(LOG_INFO, "Connecting to $connect_to on port $this->port"); + $master = new XmppMaster($this->get_id()); + $master->init(); + $master->service(); - $this->conn = jabber_connect($this->resource); + common_log(LOG_INFO, 'terminating normally'); - if (!$this->conn) { - return false; - } - - $this->log(LOG_INFO, "Connected"); - - $this->conn->setReconnectTimeout(600); - - $this->log(LOG_INFO, "Sending initial presence."); - - jabber_send_presence("Send me a message to post a notice", 'available', - null, 'available', 100); - - $this->log(LOG_INFO, "Done connecting."); - - return !$this->conn->isDisconnected(); + return true; } - function name() +} + +class XmppMaster extends IoMaster +{ + /** + * Initialize IoManagers for the currently configured site + * which are appropriate to this instance. + */ + function initManagers() { - return strtolower('xmppdaemon.'.$this->resource); - } - - function run() - { - if ($this->connect()) { - - $this->log(LOG_DEBUG, "Initializing stanza handlers."); - - $this->conn->addEventHandler('message', 'handle_message', $this); - $this->conn->addEventHandler('presence', 'handle_presence', $this); - $this->conn->addEventHandler('reconnect', 'handle_reconnect', $this); - - $this->log(LOG_DEBUG, "Beginning processing loop."); - - while ($this->conn->processTime(60)) { - $this->sendPing(); - } - } - } - - function sendPing() - { - if (!isset($this->pingid)) { - $this->pingid = 0; - } else { - $this->pingid++; - } - - $this->log(LOG_DEBUG, "Sending ping #{$this->pingid}"); - - $this->conn->send(""); - } - - function handle_reconnect(&$pl) - { - $this->log(LOG_DEBUG, "Got reconnection callback."); - $this->conn->processUntil('session_start'); - $this->log(LOG_DEBUG, "Sending reconnection presence."); - $this->conn->presence('Send me a message to post a notice', 'available', null, 'available', 100); - unset($pl['xml']); - $pl['xml'] = null; - - $pl = null; - unset($pl); - } - - function get_user($from) - { - $user = User::staticGet('jabber', jabber_normalize_jid($from)); - return $user; - } - - function handle_message(&$pl) - { - $from = jabber_normalize_jid($pl['from']); - - if ($pl['type'] != 'chat') { - $this->log(LOG_WARNING, "Ignoring message of type ".$pl['type']." from $from."); - return; - } - - if (mb_strlen($pl['body']) == 0) { - $this->log(LOG_WARNING, "Ignoring message with empty body from $from."); - return; - } - - # Forwarded from another daemon (probably a broadcaster) for - # us to handle - - if ($this->is_self($from)) { - $this->log(LOG_INFO, "Got forwarded notice from self ($from)."); - $from = $this->get_ofrom($pl); - $this->log(LOG_INFO, "Originally sent by $from."); - if (is_null($from) || $this->is_self($from)) { - $this->log(LOG_INFO, "Ignoring notice originally sent by $from."); - return; - } - } - - $user = $this->get_user($from); - - // For common_current_user to work - global $_cur; - $_cur = $user; - - if (!$user) { - $this->from_site($from, 'Unknown user; go to ' . - common_local_url('imsettings') . - ' to add your address to your account'); - $this->log(LOG_WARNING, 'Message from unknown user ' . $from); - return; - } - if ($this->handle_command($user, $pl['body'])) { - $this->log(LOG_INFO, "Command message by $from handled."); - return; - } else if ($this->is_autoreply($pl['body'])) { - $this->log(LOG_INFO, 'Ignoring auto reply from ' . $from); - return; - } else if ($this->is_otr($pl['body'])) { - $this->log(LOG_INFO, 'Ignoring OTR from ' . $from); - return; - } else { - - $this->log(LOG_INFO, 'Posting a notice from ' . $user->nickname); - - $this->add_notice($user, $pl); - } - - $user->free(); - unset($user); - unset($_cur); - - unset($pl['xml']); - $pl['xml'] = null; - - $pl = null; - unset($pl); - } - - function is_self($from) - { - return preg_match('/^'.strtolower(jabber_daemon_address()).'/', strtolower($from)); - } - - function get_ofrom($pl) - { - $xml = $pl['xml']; - $addresses = $xml->sub('addresses'); - if (!$addresses) { - $this->log(LOG_WARNING, 'Forwarded message without addresses'); - return null; - } - $address = $addresses->sub('address'); - if (!$address) { - $this->log(LOG_WARNING, 'Forwarded message without address'); - return null; - } - if (!array_key_exists('type', $address->attrs)) { - $this->log(LOG_WARNING, 'No type for forwarded message'); - return null; - } - $type = $address->attrs['type']; - if ($type != 'ofrom') { - $this->log(LOG_WARNING, 'Type of forwarded message is not ofrom'); - return null; - } - if (!array_key_exists('jid', $address->attrs)) { - $this->log(LOG_WARNING, 'No jid for forwarded message'); - return null; - } - $jid = $address->attrs['jid']; - if (!$jid) { - $this->log(LOG_WARNING, 'Could not get jid from address'); - return null; - } - $this->log(LOG_DEBUG, 'Got message forwarded from jid ' . $jid); - return $jid; - } - - function is_autoreply($txt) - { - if (preg_match('/[\[\(]?[Aa]uto[-\s]?[Rr]e(ply|sponse)[\]\)]/', $txt)) { - return true; - } else if (preg_match('/^System: Message wasn\'t delivered. Offline storage size was exceeded.$/', $txt)) { - return true; - } else { - return false; - } - } - - function is_otr($txt) - { - if (preg_match('/^\?OTR/', $txt)) { - return true; - } else { - return false; - } - } - - function from_site($address, $msg) - { - $text = '['.common_config('site', 'name') . '] ' . $msg; - jabber_send_message($address, $text); - } - - function handle_command($user, $body) - { - $inter = new CommandInterpreter(); - $cmd = $inter->handle_command($user, $body); - if ($cmd) { - $chan = new XMPPChannel($this->conn); - $cmd->execute($chan); - return true; - } else { - return false; - } - } - - function add_notice(&$user, &$pl) - { - $body = trim($pl['body']); - $content_shortened = common_shorten_links($body); - if (Notice::contentTooLong($content_shortened)) { - $from = jabber_normalize_jid($pl['from']); - $this->from_site($from, sprintf(_('Message too long - maximum is %1$d characters, you sent %2$d.'), - Notice::maxContent(), - mb_strlen($content_shortened))); - return; - } - - try { - $notice = Notice::saveNew($user->id, $content_shortened, 'xmpp'); - } catch (Exception $e) { - $this->log(LOG_ERR, $e->getMessage()); - $this->from_site($user->jabber, $e->getMessage()); - return; - } - - common_broadcast_notice($notice); - $this->log(LOG_INFO, - 'Added notice ' . $notice->id . ' from user ' . $user->nickname); - $notice->free(); - unset($notice); - } - - function handle_presence(&$pl) - { - $from = jabber_normalize_jid($pl['from']); - switch ($pl['type']) { - case 'subscribe': - # We let anyone subscribe - $this->subscribed($from); - $this->log(LOG_INFO, - 'Accepted subscription from ' . $from); - break; - case 'subscribed': - case 'unsubscribed': - case 'unsubscribe': - $this->log(LOG_INFO, - 'Ignoring "' . $pl['type'] . '" from ' . $from); - break; - default: - if (!$pl['type']) { - $user = User::staticGet('jabber', $from); - if (!$user) { - $this->log(LOG_WARNING, 'Presence from unknown user ' . $from); - return; - } - if ($user->updatefrompresence) { - $this->log(LOG_INFO, 'Updating ' . $user->nickname . - ' status from presence.'); - $this->add_notice($user, $pl); - } - $user->free(); - unset($user); - } - break; - } - unset($pl['xml']); - $pl['xml'] = null; - - $pl = null; - unset($pl); - } - - function log($level, $msg) - { - $text = 'XMPPDaemon('.$this->resource.'): '.$msg; - common_log($level, $text); - if (!$this->daemonize) - { - $line = common_log_line($level, $text); - echo $line; - echo "\n"; - } - } - - function subscribed($to) - { - jabber_special_presence('subscribed', $to); + // @fixme right now there's a hack in QueueManager to determine + // which queues to subscribe to based on the master class. + $this->instantiate('QueueManager'); + $this->instantiate('XmppManager'); } } From 0e852def6ae5aa529cca0aef1187152fb5a880be Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Thu, 21 Jan 2010 16:42:50 -0800 Subject: [PATCH 38/53] XMPP queued output & initial retooling of DB queue manager to support non-Notice objects. Queue handlers for XMPP individual & firehose output now send their XML stanzas to another output queue instead of connecting directly to the chat server. This lets us have as many general processing threads as we need, while all actual XMPP input and output go through a single daemon with a single connection open. This avoids problems with multiple connected resources: * multiple windows shown in some chat clients (psi, gajim, kopete) * extra load on server * incoming message delivery forwarding issues Database changes: * queue_item drops 'notice_id' in favor of a 'frame' blob. This is based on Craig Andrews' work branch to generalize queues to take any object, but conservatively leaving out the serialization for now. Table updater (preserves any existing queued items) in db/rc3to09.sql Code changes to watch out for: * Queue handlers should now define a handle() method instead of handle_notice() * QueueDaemon and XmppDaemon now share common i/o (IoMaster) and respawning thread management (RespawningDaemon) infrastructure. * The polling XmppConfirmManager has been dropped, as the message is queued directly when saving IM settings. * Enable $config['queue']['debug_memory'] to output current memory usage at each run through the event loop to watch for memory leaks To do: * Adapt XMPP i/o to component connection mode for multi-site support. * XMPP input can also be broken out to a queue, which would allow the actual notice save etc to be handled by general queue threads. * Make sure there are no problems with simply pushing serialized Notice objects to queues. * Find a way to improve interactive performance of the database-backed queue handler; polling is pretty painful to XMPP. * Possibly redo the way QueueHandlers are injected into a QueueManager. The grouping used to split out the XMPP output queue is a bit awkward. --- actions/imsettings.php | 10 +- classes/Queue_item.php | 30 +- classes/statusnet.ini | 6 +- db/08to09.sql | 16 + db/rc3to09.sql | 16 + db/statusnet.sql | 5 +- lib/dbqueuemanager.php | 138 ++----- lib/default.php | 1 + lib/iomaster.php | 39 +- lib/jabber.php | 43 ++- lib/jabberqueuehandler.php | 4 +- lib/ombqueuehandler.php | 2 +- lib/pingqueuehandler.php | 2 +- lib/pluginqueuehandler.php | 2 +- lib/publicqueuehandler.php | 6 +- lib/queued_xmpp.php | 117 ++++++ lib/queuehandler.php | 95 +---- lib/queuemanager.php | 125 +++++-- lib/smsqueuehandler.php | 2 +- lib/spawningdaemon.php | 159 ++++++++ lib/stompqueuemanager.php | 56 +-- lib/util.php | 3 +- lib/xmppconfirmmanager.php | 168 --------- lib/xmppmanager.php | 298 ++++++++++++--- lib/xmppoutqueuehandler.php | 55 +++ plugins/Enjit/enjitqueuehandler.php | 9 +- plugins/Facebook/facebookqueuehandler.php | 2 +- plugins/RSSCloud/RSSCloudPlugin.php | 41 +- plugins/RSSCloud/RSSCloudQueueHandler.php | 50 +-- plugins/TwitterBridge/twitterqueuehandler.php | 2 +- scripts/handlequeued.php | 2 +- scripts/queuedaemon.php | 149 ++------ scripts/xmppdaemon.php | 353 ++---------------- 33 files changed, 951 insertions(+), 1055 deletions(-) create mode 100644 db/rc3to09.sql create mode 100644 lib/queued_xmpp.php create mode 100644 lib/spawningdaemon.php delete mode 100644 lib/xmppconfirmmanager.php create mode 100644 lib/xmppoutqueuehandler.php mode change 100755 => 100644 plugins/RSSCloud/RSSCloudQueueHandler.php diff --git a/actions/imsettings.php b/actions/imsettings.php index 751c6117cd..af4915843d 100644 --- a/actions/imsettings.php +++ b/actions/imsettings.php @@ -309,6 +309,8 @@ class ImsettingsAction extends ConnectSettingsAction $confirm->address_type = 'jabber'; $confirm->user_id = $user->id; $confirm->code = common_confirmation_code(64); + $confirm->sent = common_sql_now(); + $confirm->claimed = common_sql_now(); $result = $confirm->insert(); @@ -318,11 +320,9 @@ class ImsettingsAction extends ConnectSettingsAction return; } - if (!common_config('queue', 'enabled')) { - jabber_confirm_address($confirm->code, - $user->nickname, - $jabber); - } + jabber_confirm_address($confirm->code, + $user->nickname, + $jabber); $msg = sprintf(_('A confirmation code was sent '. 'to the IM address you added. '. diff --git a/classes/Queue_item.php b/classes/Queue_item.php index cf805a6060..f83c2cef18 100644 --- a/classes/Queue_item.php +++ b/classes/Queue_item.php @@ -10,8 +10,8 @@ class Queue_item extends Memcached_DataObject /* the code below is auto generated do not remove the above tag */ public $__table = 'queue_item'; // table name - public $notice_id; // int(4) primary_key not_null - public $transport; // varchar(8) primary_key not_null + public $id; // int(4) primary_key not_null + public $frame; // blob not_null public $created; // datetime() not_null public $claimed; // datetime() @@ -22,14 +22,21 @@ class Queue_item extends Memcached_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE - function sequenceKey() - { return array(false, false); } - - static function top($transport=null) { + /** + * @param mixed $transports name of a single queue or array of queues to pull from + * If not specified, checks all queues in the system. + */ + static function top($transports=null) { $qi = new Queue_item(); - if ($transport) { - $qi->transport = $transport; + if ($transports) { + if (is_array($transports)) { + // @fixme use safer escaping + $list = implode("','", array_map('addslashes', $transports)); + $qi->whereAdd("transport in ('$list')"); + } else { + $qi->transport = $transports; + } } $qi->orderBy('created'); $qi->whereAdd('claimed is null'); @@ -42,7 +49,7 @@ class Queue_item extends Memcached_DataObject # XXX: potential race condition # can we force it to only update if claimed is still null # (or old)? - common_log(LOG_INFO, 'claiming queue item = ' . $qi->notice_id . + common_log(LOG_INFO, 'claiming queue item id = ' . $qi->id . ' for transport ' . $qi->transport); $orig = clone($qi); $qi->claimed = common_sql_now(); @@ -57,9 +64,4 @@ class Queue_item extends Memcached_DataObject $qi = null; return null; } - - function pkeyGet($kv) - { - return Memcached_DataObject::pkeyGet('Queue_item', $kv); - } } diff --git a/classes/statusnet.ini b/classes/statusnet.ini index 73727a6d6a..6ce4495be0 100644 --- a/classes/statusnet.ini +++ b/classes/statusnet.ini @@ -396,14 +396,14 @@ tagged = K tag = K [queue_item] -notice_id = 129 +id = 129 +frame = 66 transport = 130 created = 142 claimed = 14 [queue_item__keys] -notice_id = K -transport = K +id = K [related_group] group_id = 129 diff --git a/db/08to09.sql b/db/08to09.sql index d9c25bc723..b10e47dbcb 100644 --- a/db/08to09.sql +++ b/db/08to09.sql @@ -94,3 +94,19 @@ create table user_location_prefs ( constraint primary key (user_id) ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; +create table queue_item_new ( + id integer auto_increment primary key comment 'unique identifier', + frame blob not null comment 'data: object reference or opaque string', + transport varchar(8) not null comment 'queue for what? "email", "jabber", "sms", "irc", ...', + created datetime not null comment 'date this record was created', + claimed datetime comment 'date this item was claimed', + + index queue_item_created_idx (created) + +) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; + +insert into queue_item_new (frame,transport,created,claimed) + select notice_id,transport,created,claimed from queue_item; +alter table queue_item rename to queue_item_old; +alter table queue_item_new rename to queue_item; + diff --git a/db/rc3to09.sql b/db/rc3to09.sql new file mode 100644 index 0000000000..02dc7a6e2e --- /dev/null +++ b/db/rc3to09.sql @@ -0,0 +1,16 @@ +create table queue_item_new ( + id integer auto_increment primary key comment 'unique identifier', + frame blob not null comment 'data: object reference or opaque string', + transport varchar(8) not null comment 'queue for what? "email", "jabber", "sms", "irc", ...', + created datetime not null comment 'date this record was created', + claimed datetime comment 'date this item was claimed', + + index queue_item_created_idx (created) + +) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; + +insert into queue_item_new (frame,transport,created,claimed) + select notice_id,transport,created,claimed from queue_item; +alter table queue_item rename to queue_item_old; +alter table queue_item_new rename to queue_item; + diff --git a/db/statusnet.sql b/db/statusnet.sql index cb33ccf33e..a9ed66cb4f 100644 --- a/db/statusnet.sql +++ b/db/statusnet.sql @@ -244,13 +244,12 @@ create table remember_me ( ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; create table queue_item ( - - notice_id integer not null comment 'notice queued' references notice (id), + id integer auto_increment primary key comment 'unique identifier', + frame blob not null comment 'data: object reference or opaque string', transport varchar(8) not null comment 'queue for what? "email", "jabber", "sms", "irc", ...', created datetime not null comment 'date this record was created', claimed datetime comment 'date this item was claimed', - constraint primary key (notice_id, transport), index queue_item_created_idx (created) ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; diff --git a/lib/dbqueuemanager.php b/lib/dbqueuemanager.php index 889365b649..c6350fc669 100644 --- a/lib/dbqueuemanager.php +++ b/lib/dbqueuemanager.php @@ -31,19 +31,17 @@ class DBQueueManager extends QueueManager { /** - * Saves a notice object reference into the queue item table. + * Saves an object reference into the queue item table. * @return boolean true on success * @throws ServerException on failure */ public function enqueue($object, $queue) { - $notice = $object; - $qi = new Queue_item(); - $qi->notice_id = $notice->id; + $qi->frame = $this->encode($object); $qi->transport = $queue; - $qi->created = $notice->created; + $qi->created = common_sql_now(); $result = $qi->insert(); if (!$result) { @@ -57,146 +55,92 @@ class DBQueueManager extends QueueManager } /** - * Poll every minute for new events during idle periods. + * Poll every 10 seconds for new events during idle periods. * We'll look in more often when there's data available. * * @return int seconds */ public function pollInterval() { - return 60; + return 10; } /** * Run a polling cycle during idle processing in the input loop. - * @return boolean true if we had a hit + * @return boolean true if we should poll again for more data immediately */ public function poll() { $this->_log(LOG_DEBUG, 'Checking for notices...'); - $item = $this->_nextItem(); - if ($item === false) { + $qi = Queue_item::top($this->getQueues()); + if (empty($qi)) { $this->_log(LOG_DEBUG, 'No notices waiting; idling.'); return false; } - if ($item === true) { - // We dequeued an entry for a deleted or invalid notice. - // Consider it a hit for poll rate purposes. - return true; - } - list($queue, $notice) = $item; - $this->_log(LOG_INFO, 'Got notice '. $notice->id . ' for transport ' . $queue); + $queue = $qi->transport; + $item = $this->decode($qi->frame); - // Yay! Got one! - $handler = $this->getHandler($queue); - if ($handler) { - if ($handler->handle_notice($notice)) { - $this->_log(LOG_INFO, "[$queue:notice $notice->id] Successfully handled notice"); - $this->_done($notice, $queue); + if ($item) { + $rep = $this->logrep($item); + $this->_log(LOG_INFO, "Got $rep for transport $queue"); + + $handler = $this->getHandler($queue); + if ($handler) { + if ($handler->handle($item)) { + $this->_log(LOG_INFO, "[$queue:$rep] Successfully handled item"); + $this->_done($qi); + } else { + $this->_log(LOG_INFO, "[$queue:$rep] Failed to handle item"); + $this->_fail($qi); + } } else { - $this->_log(LOG_INFO, "[$queue:notice $notice->id] Failed to handle notice"); - $this->_fail($notice, $queue); + $this->_log(LOG_INFO, "[$queue:$rep] No handler for queue $queue; discarding."); + $this->_done($qi); } } else { - $this->_log(LOG_INFO, "[$queue:notice $notice->id] No handler for queue $queue; discarding."); - $this->_done($notice, $queue); + $this->_log(LOG_INFO, "[$queue] Got empty/deleted item, discarding"); + $this->_fail($qi); } return true; } - /** - * Pop the oldest unclaimed item off the queue set and claim it. - * - * @return mixed false if no items; true if bogus hit; otherwise array(string, Notice) - * giving the queue transport name. - */ - protected function _nextItem() - { - $start = time(); - $result = null; - - $qi = Queue_item::top(); - if (empty($qi)) { - return false; - } - - $queue = $qi->transport; - $notice = Notice::staticGet('id', $qi->notice_id); - if (empty($notice)) { - $this->_log(LOG_INFO, "[$queue:notice $notice->id] dequeued non-existent notice"); - $qi->delete(); - return true; - } - - $result = $notice; - return array($queue, $notice); - } - /** * Delete our claimed item from the queue after successful processing. * - * @param Notice $object - * @param string $queue + * @param QueueItem $qi */ - protected function _done($object, $queue) + protected function _done($qi) { - // XXX: right now, we only handle notices + $queue = $qi->transport; - $notice = $object; - - $qi = Queue_item::pkeyGet(array('notice_id' => $notice->id, - 'transport' => $queue)); - - if (empty($qi)) { - $this->_log(LOG_INFO, "[$queue:notice $notice->id] Cannot find queue item"); - } else { - if (empty($qi->claimed)) { - $this->_log(LOG_WARNING, "[$queue:notice $notice->id] Reluctantly releasing unclaimed queue item"); - } - $qi->delete(); - $qi->free(); + if (empty($qi->claimed)) { + $this->_log(LOG_WARNING, "Reluctantly releasing unclaimed queue item $qi->id from $qi->queue"); } + $qi->delete(); - $this->_log(LOG_INFO, "[$queue:notice $notice->id] done with item"); $this->stats('handled', $queue); - - $notice->free(); } /** * Free our claimed queue item for later reprocessing in case of * temporary failure. * - * @param Notice $object - * @param string $queue + * @param QueueItem $qi */ - protected function _fail($object, $queue) + protected function _fail($qi) { - // XXX: right now, we only handle notices + $queue = $qi->transport; - $notice = $object; - - $qi = Queue_item::pkeyGet(array('notice_id' => $notice->id, - 'transport' => $queue)); - - if (empty($qi)) { - $this->_log(LOG_INFO, "[$queue:notice $notice->id] Cannot find queue item"); + if (empty($qi->claimed)) { + $this->_log(LOG_WARNING, "[$queue:item $qi->id] Ignoring failure for unclaimed queue item"); } else { - if (empty($qi->claimed)) { - $this->_log(LOG_WARNING, "[$queue:notice $notice->id] Ignoring failure for unclaimed queue item"); - } else { - $orig = clone($qi); - $qi->claimed = null; - $qi->update($orig); - $qi = null; - } + $orig = clone($qi); + $qi->claimed = null; + $qi->update($orig); } - $this->_log(LOG_INFO, "[$queue:notice $notice->id] done with queue item"); $this->stats('error', $queue); - - $notice->free(); } protected function _log($level, $msg) diff --git a/lib/default.php b/lib/default.php index fc6b4ab79c..0cb70de2d2 100644 --- a/lib/default.php +++ b/lib/default.php @@ -83,6 +83,7 @@ $default = 'stomp_password' => null, 'monitor' => null, // URL to monitor ping endpoint (work in progress) 'softlimit' => '90%', // total size or % of memory_limit at which to restart queue threads gracefully + 'debug_memory' => false, // true to spit memory usage to log ), 'license' => array('type' => 'cc', # can be 'cc', 'allrightsreserved', 'private' diff --git a/lib/iomaster.php b/lib/iomaster.php index ce77b53b2e..004e92b3ee 100644 --- a/lib/iomaster.php +++ b/lib/iomaster.php @@ -27,7 +27,7 @@ * @link http://status.net/ */ -class IoMaster +abstract class IoMaster { public $id; @@ -66,23 +66,18 @@ class IoMaster if ($site != common_config('site', 'server')) { StatusNet::init($site); } - - $classes = array(); - if (Event::handle('StartIoManagerClasses', array(&$classes))) { - $classes[] = 'QueueManager'; - if (common_config('xmpp', 'enabled') && !defined('XMPP_EMERGENCY_FLAG')) { - $classes[] = 'XmppManager'; // handles pings/reconnects - $classes[] = 'XmppConfirmManager'; // polls for outgoing confirmations - } - } - Event::handle('EndIoManagerClasses', array(&$classes)); - - foreach ($classes as $class) { - $this->instantiate($class); - } + $this->initManagers(); } } + /** + * Initialize IoManagers for the currently configured site + * which are appropriate to this instance. + * + * Pass class names into $this->instantiate() + */ + abstract function initManagers(); + /** * Pull all local sites from status_network table. * @return array of hostnames @@ -170,7 +165,7 @@ class IoMaster $write = array(); $except = array(); $this->logState('listening'); - common_log(LOG_INFO, "Waiting up to $timeout seconds for socket data..."); + common_log(LOG_DEBUG, "Waiting up to $timeout seconds for socket data..."); $ready = stream_select($read, $write, $except, $timeout, 0); if ($ready === false) { @@ -190,7 +185,7 @@ class IoMaster if ($timeout > 0 && empty($sockets)) { // If we had no listeners, sleep until the pollers' next requested wakeup. - common_log(LOG_INFO, "Sleeping $timeout seconds until next poll cycle..."); + common_log(LOG_DEBUG, "Sleeping $timeout seconds until next poll cycle..."); $this->logState('sleep'); sleep($timeout); } @@ -207,6 +202,8 @@ class IoMaster if ($usage > $memoryLimit) { common_log(LOG_INFO, "Queue thread hit soft memory limit ($usage > $memoryLimit); gracefully restarting."); break; + } else if (common_config('queue', 'debug_memory')) { + common_log(LOG_DEBUG, "Memory usage $usage"); } } } @@ -223,8 +220,7 @@ class IoMaster { $softLimit = trim(common_config('queue', 'softlimit')); if (substr($softLimit, -1) == '%') { - $limit = trim(ini_get('memory_limit')); - $limit = $this->parseMemoryLimit($limit); + $limit = $this->parseMemoryLimit(ini_get('memory_limit')); if ($limit > 0) { return intval(substr($softLimit, 0, -1) * $limit / 100); } else { @@ -242,9 +238,10 @@ class IoMaster * @param string $mem * @return int */ - protected function parseMemoryLimit($mem) + public function parseMemoryLimit($mem) { // http://www.php.net/manual/en/faq.using.php#faq.using.shorthandbytes + $mem = strtolower(trim($mem)); $size = array('k' => 1024, 'm' => 1024*1024, 'g' => 1024*1024*1024); @@ -253,7 +250,7 @@ class IoMaster } else if (is_numeric($mem)) { return intval($mem); } else { - $mult = strtolower(substr($mem, -1)); + $mult = substr($mem, -1); if (isset($size[$mult])) { return substr($mem, 0, -1) * $size[$mult]; } else { diff --git a/lib/jabber.php b/lib/jabber.php index 4cdfa67465..b6b23521bd 100644 --- a/lib/jabber.php +++ b/lib/jabber.php @@ -85,6 +85,27 @@ class Sharing_XMPP extends XMPPHP_XMPP } } +/** + * Build an XMPP proxy connection that'll save outgoing messages + * to the 'xmppout' queue to be picked up by xmppdaemon later. + */ +function jabber_proxy() +{ + $proxy = new Queued_XMPP(common_config('xmpp', 'host') ? + common_config('xmpp', 'host') : + common_config('xmpp', 'server'), + common_config('xmpp', 'port'), + common_config('xmpp', 'user'), + common_config('xmpp', 'password'), + common_config('xmpp', 'resource') . 'daemon', + common_config('xmpp', 'server'), + common_config('xmpp', 'debug') ? + true : false, + common_config('xmpp', 'debug') ? + XMPPHP_Log::LEVEL_VERBOSE : null); + return $proxy; +} + /** * Lazy-connect the configured Jabber account to the configured server; * if already opened, the same connection will be returned. @@ -143,7 +164,7 @@ function jabber_connect($resource=null) } /** - * send a single notice to a given Jabber address + * Queue send for a single notice to a given Jabber address * * @param string $to JID to send the notice to * @param Notice $notice notice to send @@ -153,10 +174,7 @@ function jabber_connect($resource=null) function jabber_send_notice($to, $notice) { - $conn = jabber_connect(); - if (!$conn) { - return false; - } + $conn = jabber_proxy(); $profile = Profile::staticGet($notice->profile_id); if (!$profile) { common_log(LOG_WARNING, 'Refusing to send notice with ' . @@ -221,10 +239,7 @@ function jabber_format_entry($profile, $notice) function jabber_send_message($to, $body, $type='chat', $subject=null) { - $conn = jabber_connect(); - if (!$conn) { - return false; - } + $conn = jabber_proxy(); $conn->message($to, $body, $type, $subject); return true; } @@ -319,7 +334,7 @@ function jabber_special_presence($type, $to=null, $show=null, $status=null) } /** - * broadcast a notice to all subscribers and reply recipients + * Queue broadcast of a notice to all subscribers and reply recipients * * This function will send a notice to all subscribers on the local server * who have Jabber addresses, and have Jabber notification enabled, and @@ -354,7 +369,7 @@ function jabber_broadcast_notice($notice) $sent_to = array(); - $conn = jabber_connect(); + $conn = jabber_proxy(); $ni = $notice->whoGets(); @@ -389,14 +404,13 @@ function jabber_broadcast_notice($notice) 'Sending notice ' . $notice->id . ' to ' . $user->jabber, __FILE__); $conn->message($user->jabber, $msg, 'chat', null, $entry); - $conn->processTime(0); } return true; } /** - * send a notice to all public listeners + * Queue send of a notice to all public listeners * * For notices that are generated on the local system (by users), we can optionally * forward them to remote listeners by XMPP. @@ -429,7 +443,7 @@ function jabber_public_notice($notice) $msg = jabber_format_notice($profile, $notice); $entry = jabber_format_entry($profile, $notice); - $conn = jabber_connect(); + $conn = jabber_proxy(); foreach ($public as $address) { common_log(LOG_INFO, @@ -437,7 +451,6 @@ function jabber_public_notice($notice) ' to public listener ' . $address, __FILE__); $conn->message($address, $msg, 'chat', null, $entry); - $conn->processTime(0); } $profile->free(); } diff --git a/lib/jabberqueuehandler.php b/lib/jabberqueuehandler.php index b1518866d7..83471f2df7 100644 --- a/lib/jabberqueuehandler.php +++ b/lib/jabberqueuehandler.php @@ -34,14 +34,14 @@ class JabberQueueHandler extends QueueHandler return 'jabber'; } - function handle_notice($notice) + function handle($notice) { require_once(INSTALLDIR.'/lib/jabber.php'); try { return jabber_broadcast_notice($notice); } catch (XMPPHP_Exception $e) { $this->log(LOG_ERR, "Got an XMPPHP_Exception: " . $e->getMessage()); - exit(1); + return false; } } } diff --git a/lib/ombqueuehandler.php b/lib/ombqueuehandler.php index 3ffc1313bc..24896c784c 100644 --- a/lib/ombqueuehandler.php +++ b/lib/ombqueuehandler.php @@ -36,7 +36,7 @@ class OmbQueueHandler extends QueueHandler * @fixme doesn't currently report failure back to the queue manager * because omb_broadcast_notice() doesn't report it to us */ - function handle_notice($notice) + function handle($notice) { if ($this->is_remote($notice)) { $this->log(LOG_DEBUG, 'Ignoring remote notice ' . $notice->id); diff --git a/lib/pingqueuehandler.php b/lib/pingqueuehandler.php index 8bb2180786..4e4d74cb1a 100644 --- a/lib/pingqueuehandler.php +++ b/lib/pingqueuehandler.php @@ -30,7 +30,7 @@ class PingQueueHandler extends QueueHandler { return 'ping'; } - function handle_notice($notice) { + function handle($notice) { require_once INSTALLDIR . '/lib/ping.php'; return ping_broadcast_notice($notice); } diff --git a/lib/pluginqueuehandler.php b/lib/pluginqueuehandler.php index 24d5046997..9653ccad42 100644 --- a/lib/pluginqueuehandler.php +++ b/lib/pluginqueuehandler.php @@ -42,7 +42,7 @@ class PluginQueueHandler extends QueueHandler return 'plugin'; } - function handle_notice($notice) + function handle($notice) { Event::handle('HandleQueuedNotice', array(&$notice)); return true; diff --git a/lib/publicqueuehandler.php b/lib/publicqueuehandler.php index 9ea9ee73a3..c9edb8d5d7 100644 --- a/lib/publicqueuehandler.php +++ b/lib/publicqueuehandler.php @@ -23,7 +23,6 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { /** * Queue handler for pushing new notices to public XMPP subscribers. - * @fixme correct this exception handling */ class PublicQueueHandler extends QueueHandler { @@ -33,15 +32,14 @@ class PublicQueueHandler extends QueueHandler return 'public'; } - function handle_notice($notice) + function handle($notice) { require_once(INSTALLDIR.'/lib/jabber.php'); try { return jabber_public_notice($notice); } catch (XMPPHP_Exception $e) { $this->log(LOG_ERR, "Got an XMPPHP_Exception: " . $e->getMessage()); - die($e->getMessage()); + return false; } - return true; } } diff --git a/lib/queued_xmpp.php b/lib/queued_xmpp.php new file mode 100644 index 0000000000..4b890c4ca4 --- /dev/null +++ b/lib/queued_xmpp.php @@ -0,0 +1,117 @@ +. + * + * @category Network + * @package StatusNet + * @author Brion Vibber + * @copyright 2010 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET') && !defined('LACONICA')) { + exit(1); +} + +require_once INSTALLDIR . '/lib/jabber.php'; + +class Queued_XMPP extends XMPPHP_XMPP +{ + /** + * Constructor + * + * @param string $host + * @param integer $port + * @param string $user + * @param string $password + * @param string $resource + * @param string $server + * @param boolean $printlog + * @param string $loglevel + */ + public function __construct($host, $port, $user, $password, $resource, $server = null, $printlog = false, $loglevel = null) + { + parent::__construct($host, $port, $user, $password, $resource, $server, $printlog, $loglevel); + // Normally the fulljid isn't filled out until resource binding time; + // we need to save it here since we're not talking to a real server. + $this->fulljid = "{$this->basejid}/{$this->resource}"; + } + + /** + * Send a formatted message to the outgoing queue for later forwarding + * to a real XMPP connection. + * + * @param string $msg + */ + public function send($msg, $timeout=NULL) + { + $qm = QueueManager::get(); + $qm->enqueue(strval($msg), 'xmppout'); + } + + /** + * Since we'll be getting input through a queue system's run loop, + * we'll process one standalone message at a time rather than our + * own XMPP message pump. + * + * @param string $message + */ + public function processMessage($message) { + $frame = array_shift($this->frames); + xml_parse($this->parser, $frame->body, false); + } + + //@{ + /** + * Stream i/o functions disabled; push input through processMessage() + */ + public function connect($timeout = 30, $persistent = false, $sendinit = true) + { + throw new Exception("Can't connect to server from XMPP queue proxy."); + } + + public function disconnect() + { + throw new Exception("Can't connect to server from XMPP queue proxy."); + } + + public function process() + { + throw new Exception("Can't read stream from XMPP queue proxy."); + } + + public function processUntil($event, $timeout=-1) + { + throw new Exception("Can't read stream from XMPP queue proxy."); + } + + public function read() + { + throw new Exception("Can't read stream from XMPP queue proxy."); + } + + public function readyToProcess() + { + throw new Exception("Can't read stream from XMPP queue proxy."); + } + //@} +} + diff --git a/lib/queuehandler.php b/lib/queuehandler.php index 613be6e330..2909cd83b1 100644 --- a/lib/queuehandler.php +++ b/lib/queuehandler.php @@ -22,51 +22,20 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } /** * Base class for queue handlers. * - * As extensions of the Daemon class, each queue handler has the ability - * to launch itself in the background, at which point it'll pass control - * to the configured QueueManager class to poll for updates. + * As of 0.9, queue handlers are short-lived for items as they are + * dequeued by a QueueManager running in an IoMaster in a daemon + * such as queuedaemon.php. + * + * Extensions requiring long-running maintenance or polling should + * register an IoManager. * * Subclasses must override at least the following methods: * - transport - * - handle_notice + * - handle */ -#class QueueHandler extends Daemon class QueueHandler { -# function __construct($id=null, $daemonize=true) -# { -# parent::__construct($daemonize); -# -# if ($id) { -# $this->set_id($id); -# } -# } - - /** - * How many seconds a polling-based queue manager should wait between - * checks for new items to handle. - * - * Defaults to 60 seconds; override to speed up or slow down. - * - * @fixme not really compatible with global queue manager - * @return int timeout in seconds - */ -# function timeout() -# { -# return 60; -# } - -# function class_name() -# { -# return ucfirst($this->transport()) . 'Handler'; -# } - -# function name() -# { -# return strtolower($this->class_name().'.'.$this->get_id()); -# } - /** * Return transport keyword which identifies items this queue handler * services; must be defined for all subclasses. @@ -83,61 +52,17 @@ class QueueHandler /** * Here's the meat of your queue handler -- you're handed a Notice - * object, which you may do as you will with. + * or other object, which you may do as you will with. * * If this function indicates failure, a warning will be logged * and the item is placed back in the queue to be re-run. * - * @param Notice $notice + * @param mixed $object * @return boolean true on success, false on failure */ - function handle_notice($notice) + function handle($object) { return true; } - - /** - * Setup and start of run loop for this queue handler as a daemon. - * Most of the heavy lifting is passed on to the QueueManager's service() - * method, which passes control back to our handle_notice() method for - * each notice that comes in on the queue. - * - * Most of the time this won't need to be overridden in a subclass. - * - * @return boolean true on success, false on failure - */ - function run() - { - if (!$this->start()) { - $this->log(LOG_WARNING, 'failed to start'); - return false; - } - - $this->log(LOG_INFO, 'checking for queued notices'); - - $queue = $this->transport(); - $timeout = $this->timeout(); - - $qm = QueueManager::get(); - - $qm->service($queue, $this); - - $this->log(LOG_INFO, 'finished servicing the queue'); - - if (!$this->finish()) { - $this->log(LOG_WARNING, 'failed to clean up'); - return false; - } - - $this->log(LOG_INFO, 'terminating normally'); - - return true; - } - - - function log($level, $msg) - { - common_log($level, $this->class_name() . ' ('. $this->get_id() .'): '.$msg); - } } diff --git a/lib/queuemanager.php b/lib/queuemanager.php index 291174d3c4..4eb39bfa8c 100644 --- a/lib/queuemanager.php +++ b/lib/queuemanager.php @@ -39,6 +39,10 @@ abstract class QueueManager extends IoManager { static $qm = null; + public $master = null; + public $handlers = array(); + public $groups = array(); + /** * Factory function to pull the appropriate QueueManager object * for this site's configuration. It can then be used to queue @@ -109,6 +113,64 @@ abstract class QueueManager extends IoManager */ abstract function enqueue($object, $queue); + /** + * Build a representation for an object for logging + * @param mixed + * @return string + */ + function logrep($object) { + if (is_object($object)) { + $class = get_class($object); + if (isset($object->id)) { + return "$class $object->id"; + } + return $class; + } + if (is_string($object)) { + $len = strlen($object); + $fragment = mb_substr($object, 0, 32); + if (mb_strlen($object) > 32) { + $fragment .= '...'; + } + return "string '$fragment' ($len bytes)"; + } + return strval($object); + } + + /** + * Encode an object for queued storage. + * Next gen may use serialization. + * + * @param mixed $object + * @return string + */ + protected function encode($object) + { + if ($object instanceof Notice) { + return $object->id; + } else if (is_string($object)) { + return $object; + } else { + throw new ServerException("Can't queue this type", 500); + } + } + + /** + * Decode an object from queued storage. + * Accepts back-compat notice reference entries and strings for now. + * + * @param string + * @return mixed + */ + protected function decode($frame) + { + if (is_numeric($frame)) { + return Notice::staticGet(intval($frame)); + } else { + return $frame; + } + } + /** * Instantiate the appropriate QueueHandler class for the given queue. * @@ -131,13 +193,15 @@ abstract class QueueManager extends IoManager } /** - * Get a list of all registered queue transport names. + * Get a list of registered queue transport names to be used + * for this daemon. * * @return array of strings */ function getQueues() { - return array_keys($this->handlers); + $group = $this->activeGroup(); + return array_keys($this->groups[$group]); } /** @@ -148,33 +212,29 @@ abstract class QueueManager extends IoManager */ function initialize() { + // @fixme we'll want to be able to listen to particular queues... if (Event::handle('StartInitializeQueueManager', array($this))) { - if (!defined('XMPP_ONLY_FLAG')) { // hack! - $this->connect('plugin', 'PluginQueueHandler'); - $this->connect('omb', 'OmbQueueHandler'); - $this->connect('ping', 'PingQueueHandler'); - if (common_config('sms', 'enabled')) { - $this->connect('sms', 'SmsQueueHandler'); - } + $this->connect('plugin', 'PluginQueueHandler'); + $this->connect('omb', 'OmbQueueHandler'); + $this->connect('ping', 'PingQueueHandler'); + if (common_config('sms', 'enabled')) { + $this->connect('sms', 'SmsQueueHandler'); } // XMPP output handlers... - if (common_config('xmpp', 'enabled') && !defined('XMPP_EMERGENCY_FLAG')) { - $this->connect('jabber', 'JabberQueueHandler'); - $this->connect('public', 'PublicQueueHandler'); - - // @fixme this should move up a level or should get an actual queue - $this->connect('confirm', 'XmppConfirmHandler'); - } + $this->connect('jabber', 'JabberQueueHandler'); + $this->connect('public', 'PublicQueueHandler'); + + // @fixme this should get an actual queue + //$this->connect('confirm', 'XmppConfirmHandler'); + + // For compat with old plugins not registering their own handlers. + $this->connect('plugin', 'PluginQueueHandler'); + + $this->connect('xmppout', 'XmppOutQueueHandler', 'xmppdaemon'); - if (!defined('XMPP_ONLY_FLAG')) { // hack! - // For compat with old plugins not registering their own handlers. - $this->connect('plugin', 'PluginQueueHandler'); - } - } - if (!defined('XMPP_ONLY_FLAG')) { // hack! - Event::handle('EndInitializeQueueManager', array($this)); } + Event::handle('EndInitializeQueueManager', array($this)); } /** @@ -183,10 +243,27 @@ abstract class QueueManager extends IoManager * * @param string $transport * @param string $class + * @param string $group */ - public function connect($transport, $class) + public function connect($transport, $class, $group='queuedaemon') { $this->handlers[$transport] = $class; + $this->groups[$group][$transport] = $class; + } + + /** + * @return string queue group to use for this request + */ + function activeGroup() + { + $group = 'queuedaemon'; + if ($this->master) { + // hack hack + if ($this->master instanceof XmppMaster) { + return 'xmppdaemon'; + } + } + return $group; } /** diff --git a/lib/smsqueuehandler.php b/lib/smsqueuehandler.php index 48a96409d0..6085d2b4ac 100644 --- a/lib/smsqueuehandler.php +++ b/lib/smsqueuehandler.php @@ -31,7 +31,7 @@ class SmsQueueHandler extends QueueHandler return 'sms'; } - function handle_notice($notice) + function handle($notice) { require_once(INSTALLDIR.'/lib/mail.php'); return mail_broadcast_notice_sms($notice); diff --git a/lib/spawningdaemon.php b/lib/spawningdaemon.php new file mode 100644 index 0000000000..8baefe88e8 --- /dev/null +++ b/lib/spawningdaemon.php @@ -0,0 +1,159 @@ +. + */ + +/** + * Base class for daemon that can launch one or more processing threads, + * respawning them if they exit. + * + * This is mainly intended for indefinite workloads such as monitoring + * a queue or maintaining an IM channel. + * + * Child classes should implement the + * + * We can then pass individual items through the QueueHandler subclasses + * they belong to. We additionally can handle queues for multiple sites. + * + * @package QueueHandler + * @author Brion Vibber + */ +abstract class SpawningDaemon extends Daemon +{ + protected $threads=1; + + function __construct($id=null, $daemonize=true, $threads=1) + { + parent::__construct($daemonize); + + if ($id) { + $this->set_id($id); + } + $this->threads = $threads; + } + + /** + * Perform some actual work! + * + * @return boolean true on success, false on failure + */ + public abstract function runThread(); + + /** + * Spawn one or more background processes and let them start running. + * Each individual process will execute whatever's in the runThread() + * method, which should be overridden. + * + * Child processes will be automatically respawned when they exit. + * + * @todo possibly allow for not respawning on "normal" exits... + * though ParallelizingDaemon is probably better for workloads + * that have forseeable endpoints. + */ + function run() + { + $children = array(); + for ($i = 1; $i <= $this->threads; $i++) { + $pid = pcntl_fork(); + if ($pid < 0) { + $this->log(LOG_ERROR, "Couldn't fork for thread $i; aborting\n"); + exit(1); + } else if ($pid == 0) { + $this->initAndRunChild($i); + } else { + $this->log(LOG_INFO, "Spawned thread $i as pid $pid"); + $children[$i] = $pid; + } + } + + $this->log(LOG_INFO, "Waiting for children to complete."); + while (count($children) > 0) { + $status = null; + $pid = pcntl_wait($status); + if ($pid > 0) { + $i = array_search($pid, $children); + if ($i === false) { + $this->log(LOG_ERR, "Unrecognized child pid $pid exited!"); + continue; + } + unset($children[$i]); + $this->log(LOG_INFO, "Thread $i pid $pid exited."); + + $pid = pcntl_fork(); + if ($pid < 0) { + $this->log(LOG_ERROR, "Couldn't fork to respawn thread $i; aborting thread.\n"); + } else if ($pid == 0) { + $this->initAndRunChild($i); + } else { + $this->log(LOG_INFO, "Respawned thread $i as pid $pid"); + $children[$i] = $pid; + } + } + } + $this->log(LOG_INFO, "All child processes complete."); + return true; + } + + /** + * Initialize things for a fresh thread, call runThread(), and + * exit at completion with appropriate return value. + */ + protected function initAndRunChild($thread) + { + $this->set_id($this->get_id() . "." . $thread); + $this->resetDb(); + $ok = $this->runThread(); + exit($ok ? 0 : 1); + } + + /** + * Reconnect to the database for each child process, + * or they'll get very confused trying to use the + * same socket. + */ + protected function resetDb() + { + // @fixme do we need to explicitly open the db too + // or is this implied? + global $_DB_DATAOBJECT; + unset($_DB_DATAOBJECT['CONNECTIONS']); + + // Reconnect main memcached, or threads will stomp on + // each other and corrupt their requests. + $cache = common_memcache(); + if ($cache) { + $cache->reconnect(); + } + + // Also reconnect memcached for status_network table. + if (!empty(Status_network::$cache)) { + Status_network::$cache->close(); + Status_network::$cache = null; + } + } + + function log($level, $msg) + { + common_log($level, get_class($this) . ' ('. $this->get_id() .'): '.$msg); + } + + function name() + { + return strtolower(get_class($this).'.'.$this->get_id()); + } +} + diff --git a/lib/stompqueuemanager.php b/lib/stompqueuemanager.php index 00590fdb69..f057bd9e41 100644 --- a/lib/stompqueuemanager.php +++ b/lib/stompqueuemanager.php @@ -39,7 +39,6 @@ class StompQueueManager extends QueueManager var $base = null; var $con = null; - protected $master = null; protected $sites = array(); function __construct() @@ -104,11 +103,12 @@ class StompQueueManager extends QueueManager */ function getQueues() { + $group = $this->activeGroup(); $site = common_config('site', 'server'); - if (empty($this->handlers[$site])) { + if (empty($this->groups[$site][$group])) { return array(); } else { - return array_keys($this->handlers[$site]); + return array_keys($this->groups[$site][$group]); } } @@ -118,10 +118,12 @@ class StompQueueManager extends QueueManager * * @param string $transport * @param string $class + * @param string $group */ - public function connect($transport, $class) + public function connect($transport, $class, $group='queuedaemon') { $this->handlers[common_config('site', 'server')][$transport] = $class; + $this->groups[common_config('site', 'server')][$group][$transport] = $class; } /** @@ -130,23 +132,23 @@ class StompQueueManager extends QueueManager */ public function enqueue($object, $queue) { - $notice = $object; + $msg = $this->encode($object); + $rep = $this->logrep($object); $this->_connect(); // XXX: serialize and send entire notice $result = $this->con->send($this->queueName($queue), - $notice->id, // BODY of the message - array ('created' => $notice->created)); + $msg, // BODY of the message + array ('created' => common_sql_now())); if (!$result) { - common_log(LOG_ERR, 'Error sending to '.$queue.' queue'); + common_log(LOG_ERR, "Error sending $rep to $queue queue"); return false; } - common_log(LOG_DEBUG, 'complete remote queueing notice ID = ' - . $notice->id . ' for ' . $queue); + common_log(LOG_DEBUG, "complete remote queueing $rep for $queue"); $this->stats('enqueued', $queue); } @@ -174,7 +176,7 @@ class StompQueueManager extends QueueManager $ok = true; $frames = $this->con->readFrames(); foreach ($frames as $frame) { - $ok = $ok && $this->_handleNotice($frame); + $ok = $ok && $this->_handleItem($frame); } return $ok; } @@ -265,7 +267,7 @@ class StompQueueManager extends QueueManager } /** - * Handle and acknowledge a notice event that's come in through a queue. + * Handle and acknowledge an event that's come in through a queue. * * If the queue handler reports failure, the message is requeued for later. * Missing notices or handler classes will drop the message. @@ -276,7 +278,7 @@ class StompQueueManager extends QueueManager * @param StompFrame $frame * @return bool */ - protected function _handleNotice($frame) + protected function _handleItem($frame) { list($site, $queue) = $this->parseDestination($frame->headers['destination']); if ($site != common_config('site', 'server')) { @@ -284,15 +286,23 @@ class StompQueueManager extends QueueManager StatusNet::init($site); } - $id = intval($frame->body); - $info = "notice $id posted at {$frame->headers['created']} in queue $queue"; + if (is_numeric($frame->body)) { + $id = intval($frame->body); + $info = "notice $id posted at {$frame->headers['created']} in queue $queue"; - $notice = Notice::staticGet('id', $id); - if (empty($notice)) { - $this->_log(LOG_WARNING, "Skipping missing $info"); - $this->con->ack($frame); - $this->stats('badnotice', $queue); - return false; + $notice = Notice::staticGet('id', $id); + if (empty($notice)) { + $this->_log(LOG_WARNING, "Skipping missing $info"); + $this->con->ack($frame); + $this->stats('badnotice', $queue); + return false; + } + + $item = $notice; + } else { + // @fixme should we serialize, or json, or what here? + $info = "string posted at {$frame->headers['created']} in queue $queue"; + $item = $frame->body; } $handler = $this->getHandler($queue); @@ -303,7 +313,7 @@ class StompQueueManager extends QueueManager return false; } - $ok = $handler->handle_notice($notice); + $ok = $handler->handle($item); if (!$ok) { $this->_log(LOG_WARNING, "Failed handling $info"); @@ -311,7 +321,7 @@ class StompQueueManager extends QueueManager // this kind of queue management ourselves; // if we don't ack, it should resend... $this->con->ack($frame); - $this->enqueue($notice, $queue); + $this->enqueue($item, $queue); $this->stats('requeued', $queue); return false; } diff --git a/lib/util.php b/lib/util.php index ef8a5d1f02..fb3b8be876 100644 --- a/lib/util.php +++ b/lib/util.php @@ -1130,7 +1130,8 @@ function common_request_id() $pid = getmypid(); $server = common_config('site', 'server'); if (php_sapi_name() == 'cli') { - return "$server:$pid"; + $script = basename($_SERVER['PHP_SELF']); + return "$server:$script:$pid"; } else { static $req_id = null; if (!isset($req_id)) { diff --git a/lib/xmppconfirmmanager.php b/lib/xmppconfirmmanager.php deleted file mode 100644 index ee4e294fd4..0000000000 --- a/lib/xmppconfirmmanager.php +++ /dev/null @@ -1,168 +0,0 @@ -. - */ - -if (!defined('STATUSNET') && !defined('LACONICA')) { - exit(1); -} - -/** - * Event handler for pushing new confirmations to Jabber users. - * @fixme recommend redoing this on a queue-trigger model - * @fixme expiration of old items got dropped in the past, put it back? - */ -class XmppConfirmManager extends IoManager -{ - - /** - * @return mixed XmppConfirmManager, or false if unneeded - */ - public static function get() - { - if (common_config('xmpp', 'enabled')) { - $site = common_config('site', 'server'); - return new XmppConfirmManager(); - } else { - return false; - } - } - - /** - * Tell the i/o master we need one instance for each supporting site - * being handled in this process. - */ - public static function multiSite() - { - return IoManager::INSTANCE_PER_SITE; - } - - function __construct() - { - $this->site = common_config('site', 'server'); - } - - /** - * 10 seconds? Really? That seems a bit frequent. - */ - function pollInterval() - { - return 10; - } - - /** - * Ping! - * @return boolean true if we found something - */ - function poll() - { - $this->switchSite(); - $confirm = $this->next_confirm(); - if ($confirm) { - $this->handle_confirm($confirm); - return true; - } else { - return false; - } - } - - protected function handle_confirm($confirm) - { - require_once INSTALLDIR . '/lib/jabber.php'; - - common_log(LOG_INFO, 'Sending confirmation for ' . $confirm->address); - $user = User::staticGet($confirm->user_id); - if (!$user) { - common_log(LOG_WARNING, 'Confirmation for unknown user ' . $confirm->user_id); - return; - } - $success = jabber_confirm_address($confirm->code, - $user->nickname, - $confirm->address); - if (!$success) { - common_log(LOG_ERR, 'Confirmation failed for ' . $confirm->address); - # Just let the claim age out; hopefully things work then - return; - } else { - common_log(LOG_INFO, 'Confirmation sent for ' . $confirm->address); - # Mark confirmation sent; need a dupe so we don't have the WHERE clause - $dupe = Confirm_address::staticGet('code', $confirm->code); - if (!$dupe) { - common_log(LOG_WARNING, 'Could not refetch confirm', __FILE__); - return; - } - $orig = clone($dupe); - $dupe->sent = $dupe->claimed; - $result = $dupe->update($orig); - if (!$result) { - common_log_db_error($dupe, 'UPDATE', __FILE__); - # Just let the claim age out; hopefully things work then - return; - } - } - return true; - } - - protected function next_confirm() - { - $confirm = new Confirm_address(); - $confirm->whereAdd('claimed IS null'); - $confirm->whereAdd('sent IS null'); - # XXX: eventually we could do other confirmations in the queue, too - $confirm->address_type = 'jabber'; - $confirm->orderBy('modified DESC'); - $confirm->limit(1); - if ($confirm->find(true)) { - common_log(LOG_INFO, 'Claiming confirmation for ' . $confirm->address); - # working around some weird DB_DataObject behaviour - $confirm->whereAdd(''); # clears where stuff - $original = clone($confirm); - $confirm->claimed = common_sql_now(); - $result = $confirm->update($original); - if ($result) { - common_log(LOG_INFO, 'Succeeded in claim! '. $result); - return $confirm; - } else { - common_log(LOG_INFO, 'Failed in claim!'); - return false; - } - } - return null; - } - - protected function clear_old_confirm_claims() - { - $confirm = new Confirm(); - $confirm->claimed = null; - $confirm->whereAdd('now() - claimed > '.CLAIM_TIMEOUT); - $confirm->update(DB_DATAOBJECT_WHEREADD_ONLY); - $confirm->free(); - unset($confirm); - } - - /** - * Make sure we're on the right site configuration - */ - protected function switchSite() - { - if ($this->site != common_config('site', 'server')) { - common_log(LOG_DEBUG, __METHOD__ . ": switching to site $this->site"); - $this->stats('switch'); - StatusNet::init($this->site); - } - } -} diff --git a/lib/xmppmanager.php b/lib/xmppmanager.php index dfff63a30c..299175dd7d 100644 --- a/lib/xmppmanager.php +++ b/lib/xmppmanager.php @@ -70,6 +70,7 @@ class XmppManager extends IoManager function __construct() { $this->site = common_config('site', 'server'); + $this->resource = common_config('xmpp', 'resource') . 'daemon'; } /** @@ -86,15 +87,19 @@ class XmppManager extends IoManager # Low priority; we don't want to receive messages common_log(LOG_INFO, "INITIALIZE"); - $this->conn = jabber_connect($this->resource()); + $this->conn = jabber_connect($this->resource); if (empty($this->conn)) { common_log(LOG_ERR, "Couldn't connect to server."); return false; } - $this->conn->addEventHandler('message', 'forward_message', $this); + $this->log(LOG_DEBUG, "Initializing stanza handlers."); + + $this->conn->addEventHandler('message', 'handle_message', $this); + $this->conn->addEventHandler('presence', 'handle_presence', $this); $this->conn->addEventHandler('reconnect', 'handle_reconnect', $this); + $this->conn->setReconnectTimeout(600); jabber_send_presence("Send me a message to post a notice", 'available', null, 'available', -1); @@ -175,12 +180,37 @@ class XmppManager extends IoManager } } + /** + * For queue handlers to pass us a message to push out, + * if we're active. + * + * @fixme should this be blocking etc? + * + * @param string $msg XML stanza to send + * @return boolean success + */ + public function send($msg) + { + if ($this->conn && !$this->conn->isDisconnected()) { + $bytes = $this->conn->send($msg); + if ($bytes > 0) { + $this->conn->processTime(0); + return true; + } else { + return false; + } + } else { + // Can't send right now... + return false; + } + } + /** * Send a keepalive ping to the XMPP server. */ protected function sendPing() { - $jid = jabber_daemon_address().'/'.$this->resource(); + $jid = jabber_daemon_address().'/'.$this->resource; $server = common_config('xmpp', 'server'); if (!isset($this->pingid)) { @@ -206,61 +236,239 @@ class XmppManager extends IoManager $this->conn->presence(null, 'available', null, 'available', -1); } - /** - * Callback for Jabber message event. - * - * This connection handles output; if we get a message straight to us, - * forward it on to our XmppDaemon listener for processing. - * - * @param $pl - */ - function forward_message(&$pl) + + function get_user($from) { + $user = User::staticGet('jabber', jabber_normalize_jid($from)); + return $user; + } + + /** + * XMPP callback for handling message input... + * @param array $pl XMPP payload + */ + function handle_message(&$pl) + { + $from = jabber_normalize_jid($pl['from']); + if ($pl['type'] != 'chat') { - common_log(LOG_DEBUG, 'Ignoring message of type ' . $pl['type'] . ' from ' . $pl['from']); + $this->log(LOG_WARNING, "Ignoring message of type ".$pl['type']." from $from."); return; } - $listener = $this->listener(); - if (strtolower($listener) == strtolower($pl['from'])) { - common_log(LOG_WARNING, 'Ignoring loop message.'); + + if (mb_strlen($pl['body']) == 0) { + $this->log(LOG_WARNING, "Ignoring message with empty body from $from."); return; } - common_log(LOG_INFO, 'Forwarding message from ' . $pl['from'] . ' to ' . $listener); - $this->conn->message($this->listener(), $pl['body'], 'chat', null, $this->ofrom($pl['from'])); - } - /** - * Build an block with an ofrom entry for forwarded messages - * - * @param string $from Jabber ID of original sender - * @return string XML fragment - */ - protected function ofrom($from) - { - $address = "\n"; - $address .= "
\n"; - $address .= "\n"; - return $address; - } + // Forwarded from another daemon for us to handle; this shouldn't + // happen any more but we might get some legacy items. + if ($this->is_self($from)) { + $this->log(LOG_INFO, "Got forwarded notice from self ($from)."); + $from = $this->get_ofrom($pl); + $this->log(LOG_INFO, "Originally sent by $from."); + if (is_null($from) || $this->is_self($from)) { + $this->log(LOG_INFO, "Ignoring notice originally sent by $from."); + return; + } + } - /** - * Build the complete JID of the XmppDaemon process which - * handles primary XMPP input for this site. - * - * @return string Jabber ID - */ - protected function listener() - { - if (common_config('xmpp', 'listener')) { - return common_config('xmpp', 'listener'); + $user = $this->get_user($from); + + // For common_current_user to work + global $_cur; + $_cur = $user; + + if (!$user) { + $this->from_site($from, 'Unknown user; go to ' . + common_local_url('imsettings') . + ' to add your address to your account'); + $this->log(LOG_WARNING, 'Message from unknown user ' . $from); + return; + } + if ($this->handle_command($user, $pl['body'])) { + $this->log(LOG_INFO, "Command message by $from handled."); + return; + } else if ($this->is_autoreply($pl['body'])) { + $this->log(LOG_INFO, 'Ignoring auto reply from ' . $from); + return; + } else if ($this->is_otr($pl['body'])) { + $this->log(LOG_INFO, 'Ignoring OTR from ' . $from); + return; } else { - return jabber_daemon_address() . '/' . common_config('xmpp','resource') . 'daemon'; + + $this->log(LOG_INFO, 'Posting a notice from ' . $user->nickname); + + $this->add_notice($user, $pl); + } + + $user->free(); + unset($user); + unset($_cur); + + unset($pl['xml']); + $pl['xml'] = null; + + $pl = null; + unset($pl); + } + + + function is_self($from) + { + return preg_match('/^'.strtolower(jabber_daemon_address()).'/', strtolower($from)); + } + + function get_ofrom($pl) + { + $xml = $pl['xml']; + $addresses = $xml->sub('addresses'); + if (!$addresses) { + $this->log(LOG_WARNING, 'Forwarded message without addresses'); + return null; + } + $address = $addresses->sub('address'); + if (!$address) { + $this->log(LOG_WARNING, 'Forwarded message without address'); + return null; + } + if (!array_key_exists('type', $address->attrs)) { + $this->log(LOG_WARNING, 'No type for forwarded message'); + return null; + } + $type = $address->attrs['type']; + if ($type != 'ofrom') { + $this->log(LOG_WARNING, 'Type of forwarded message is not ofrom'); + return null; + } + if (!array_key_exists('jid', $address->attrs)) { + $this->log(LOG_WARNING, 'No jid for forwarded message'); + return null; + } + $jid = $address->attrs['jid']; + if (!$jid) { + $this->log(LOG_WARNING, 'Could not get jid from address'); + return null; + } + $this->log(LOG_DEBUG, 'Got message forwarded from jid ' . $jid); + return $jid; + } + + function is_autoreply($txt) + { + if (preg_match('/[\[\(]?[Aa]uto[-\s]?[Rr]e(ply|sponse)[\]\)]/', $txt)) { + return true; + } else if (preg_match('/^System: Message wasn\'t delivered. Offline storage size was exceeded.$/', $txt)) { + return true; + } else { + return false; } } - protected function resource() + function is_otr($txt) { - return 'queue' . posix_getpid(); // @fixme PIDs won't be host-unique + if (preg_match('/^\?OTR/', $txt)) { + return true; + } else { + return false; + } + } + + function from_site($address, $msg) + { + $text = '['.common_config('site', 'name') . '] ' . $msg; + jabber_send_message($address, $text); + } + + function handle_command($user, $body) + { + $inter = new CommandInterpreter(); + $cmd = $inter->handle_command($user, $body); + if ($cmd) { + $chan = new XMPPChannel($this->conn); + $cmd->execute($chan); + return true; + } else { + return false; + } + } + + function add_notice(&$user, &$pl) + { + $body = trim($pl['body']); + $content_shortened = common_shorten_links($body); + if (Notice::contentTooLong($content_shortened)) { + $from = jabber_normalize_jid($pl['from']); + $this->from_site($from, sprintf(_('Message too long - maximum is %1$d characters, you sent %2$d.'), + Notice::maxContent(), + mb_strlen($content_shortened))); + return; + } + + try { + $notice = Notice::saveNew($user->id, $content_shortened, 'xmpp'); + } catch (Exception $e) { + $this->log(LOG_ERR, $e->getMessage()); + $this->from_site($user->jabber, $e->getMessage()); + return; + } + + common_broadcast_notice($notice); + $this->log(LOG_INFO, + 'Added notice ' . $notice->id . ' from user ' . $user->nickname); + $notice->free(); + unset($notice); + } + + function handle_presence(&$pl) + { + $from = jabber_normalize_jid($pl['from']); + switch ($pl['type']) { + case 'subscribe': + # We let anyone subscribe + $this->subscribed($from); + $this->log(LOG_INFO, + 'Accepted subscription from ' . $from); + break; + case 'subscribed': + case 'unsubscribed': + case 'unsubscribe': + $this->log(LOG_INFO, + 'Ignoring "' . $pl['type'] . '" from ' . $from); + break; + default: + if (!$pl['type']) { + $user = User::staticGet('jabber', $from); + if (!$user) { + $this->log(LOG_WARNING, 'Presence from unknown user ' . $from); + return; + } + if ($user->updatefrompresence) { + $this->log(LOG_INFO, 'Updating ' . $user->nickname . + ' status from presence.'); + $this->add_notice($user, $pl); + } + $user->free(); + unset($user); + } + break; + } + unset($pl['xml']); + $pl['xml'] = null; + + $pl = null; + unset($pl); + } + + function log($level, $msg) + { + $text = 'XMPPDaemon('.$this->resource.'): '.$msg; + common_log($level, $text); + } + + function subscribed($to) + { + jabber_special_presence('subscribed', $to); } /** diff --git a/lib/xmppoutqueuehandler.php b/lib/xmppoutqueuehandler.php new file mode 100644 index 0000000000..2afa260f18 --- /dev/null +++ b/lib/xmppoutqueuehandler.php @@ -0,0 +1,55 @@ +. + */ + +/** + * Queue handler for pre-processed outgoing XMPP messages. + * Formatted XML stanzas will have been pushed into the queue + * via the Queued_XMPP connection proxy, probably from some + * other queue processor. + * + * Here, the XML stanzas are simply pulled out of the queue and + * pushed out over the wire; an XmppManager is needed to set up + * and maintain the actual server connection. + * + * This queue will be run via XmppDaemon rather than QueueDaemon. + * + * @author Brion Vibber + */ +class XmppOutQueueHandler extends QueueHandler +{ + function transport() { + return 'xmppout'; + } + + /** + * Take a previously-queued XMPP stanza and send it out ot the server. + * @param string $msg + * @return boolean true on success + */ + function handle($msg) + { + assert(is_string($msg)); + + $xmpp = XmppManager::get(); + $ok = $xmpp->send($msg); + + return $ok; + } +} + diff --git a/plugins/Enjit/enjitqueuehandler.php b/plugins/Enjit/enjitqueuehandler.php index f0e706b929..14085cc5e3 100644 --- a/plugins/Enjit/enjitqueuehandler.php +++ b/plugins/Enjit/enjitqueuehandler.php @@ -32,14 +32,7 @@ class EnjitQueueHandler extends QueueHandler return 'enjit'; } - function start() - { - $this->log(LOG_INFO, "Starting EnjitQueueHandler"); - $this->log(LOG_INFO, "Broadcasting to ".common_config('enjit', 'apiurl')); - return true; - } - - function handle_notice($notice) + function handle($notice) { $profile = Profile::staticGet($notice->profile_id); diff --git a/plugins/Facebook/facebookqueuehandler.php b/plugins/Facebook/facebookqueuehandler.php index 1778690e5b..524af7bc45 100644 --- a/plugins/Facebook/facebookqueuehandler.php +++ b/plugins/Facebook/facebookqueuehandler.php @@ -28,7 +28,7 @@ class FacebookQueueHandler extends QueueHandler return 'facebook'; } - function handle_notice($notice) + function handle($notice) { if ($this->_isLocal($notice)) { return facebookBroadcastNotice($notice); diff --git a/plugins/RSSCloud/RSSCloudPlugin.php b/plugins/RSSCloud/RSSCloudPlugin.php index 2de162628f..9f444c8bba 100644 --- a/plugins/RSSCloud/RSSCloudPlugin.php +++ b/plugins/RSSCloud/RSSCloudPlugin.php @@ -138,6 +138,9 @@ class RSSCloudPlugin extends Plugin case 'RSSCloudNotifier': include_once INSTALLDIR . '/plugins/RSSCloud/RSSCloudNotifier.php'; return false; + case 'RSSCloudQueueHandler': + include_once INSTALLDIR . '/plugins/RSSCloud/RSSCloudQueueHandler.php'; + return false; case 'RSSCloudRequestNotifyAction': case 'LoggingAggregatorAction': include_once INSTALLDIR . '/plugins/RSSCloud/' . @@ -193,32 +196,6 @@ class RSSCloudPlugin extends Plugin return true; } - /** - * broadcast the message when not using queuehandler - * - * @param Notice &$notice the notice - * @param array $queue destination queue - * - * @return boolean hook return - */ - - function onUnqueueHandleNotice(&$notice, $queue) - { - if (($queue == 'rsscloud') && ($this->_isLocal($notice))) { - - common_debug('broadcasting rssCloud bound notice ' . $notice->id); - - $profile = $notice->getProfile(); - - $notifier = new RSSCloudNotifier(); - $notifier->notify($profile); - - return false; - } - - return true; - } - /** * Determine whether the notice was locally created * @@ -261,19 +238,15 @@ class RSSCloudPlugin extends Plugin } /** - * Add RSSCloudQueueHandler to the list of valid daemons to - * start + * Register RSSCloud notice queue handler * - * @param array $daemons the list of daemons to run + * @param QueueManager $manager * * @return boolean hook return - * */ - - function onGetValidDaemons($daemons) + function onEndInitializeQueueManager($manager) { - array_push($daemons, INSTALLDIR . - '/plugins/RSSCloud/RSSCloudQueueHandler.php'); + $manager->connect('rsscloud', 'RSSCloudQueueHandler'); return true; } diff --git a/plugins/RSSCloud/RSSCloudQueueHandler.php b/plugins/RSSCloud/RSSCloudQueueHandler.php old mode 100755 new mode 100644 index 693dd27c1f..295c261895 --- a/plugins/RSSCloud/RSSCloudQueueHandler.php +++ b/plugins/RSSCloud/RSSCloudQueueHandler.php @@ -1,4 +1,3 @@ -#!/usr/bin/env php . */ -define('INSTALLDIR', realpath(dirname(__FILE__) . '/../..')); - -$shortoptions = 'i::'; -$longoptions = array('id::'); - -$helptext = <<log(LOG_INFO, "INITIALIZE"); - $this->notifier = new RSSCloudNotifier(); - return true; - } - - function handle_notice($notice) + function handle($notice) { $profile = $notice->getProfile(); - return $this->notifier->notify($profile); + $notifier = new RSSCloudNotifier(); + return $notifier->notify($profile); } - - function finish() - { - } - } -if (have_option('i')) { - $id = get_option_value('i'); -} else if (have_option('--id')) { - $id = get_option_value('--id'); -} else if (count($args) > 0) { - $id = $args[0]; -} else { - $id = null; -} - -$handler = new RSSCloudQueueHandler($id); - -$handler->runOnce(); diff --git a/plugins/TwitterBridge/twitterqueuehandler.php b/plugins/TwitterBridge/twitterqueuehandler.php index 5089ca7b74..b5a624e83d 100644 --- a/plugins/TwitterBridge/twitterqueuehandler.php +++ b/plugins/TwitterBridge/twitterqueuehandler.php @@ -28,7 +28,7 @@ class TwitterQueueHandler extends QueueHandler return 'twitter'; } - function handle_notice($notice) + function handle($notice) { return broadcast_twitter($notice); } diff --git a/scripts/handlequeued.php b/scripts/handlequeued.php index 9031437aac..8158849695 100755 --- a/scripts/handlequeued.php +++ b/scripts/handlequeued.php @@ -50,7 +50,7 @@ if (empty($notice)) { exit(1); } -if (!$handler->handle_notice($notice)) { +if (!$handler->handle($notice)) { print "Failed to handle notice id $noticeId on queue '$queue'.\n"; exit(1); } diff --git a/scripts/queuedaemon.php b/scripts/queuedaemon.php index 162f617e0d..a9cfda6d72 100755 --- a/scripts/queuedaemon.php +++ b/scripts/queuedaemon.php @@ -29,6 +29,8 @@ $longoptions = array('id=', 'foreground', 'all', 'threads=', 'skip-xmpp', 'xmpp- * * Recognizes Linux and Mac OS X; others will return default of 1. * + * @fixme move this to SpawningDaemon, but to get the default val for help + * text we seem to need it before loading infrastructure * @return intval */ function getProcessorCount() @@ -83,143 +85,29 @@ define('CLAIM_TIMEOUT', 1200); * We can then pass individual items through the QueueHandler subclasses * they belong to. */ -class QueueDaemon extends Daemon +class QueueDaemon extends SpawningDaemon { - protected $allsites; - protected $threads=1; + protected $allsites = false; function __construct($id=null, $daemonize=true, $threads=1, $allsites=false) { - parent::__construct($daemonize); - - if ($id) { - $this->set_id($id); - } + parent::__construct($id, $daemonize, $threads); $this->all = $allsites; - $this->threads = $threads; - } - - /** - * How many seconds a polling-based queue manager should wait between - * checks for new items to handle. - * - * Defaults to 60 seconds; override to speed up or slow down. - * - * @return int timeout in seconds - */ - function timeout() - { - return 60; - } - - function name() - { - return strtolower(get_class($this).'.'.$this->get_id()); - } - - function run() - { - if ($this->threads > 1) { - return $this->runThreads(); - } else { - return $this->runLoop(); - } - } - - function runThreads() - { - $children = array(); - for ($i = 1; $i <= $this->threads; $i++) { - $pid = pcntl_fork(); - if ($pid < 0) { - print "Couldn't fork for thread $i; aborting\n"; - exit(1); - } else if ($pid == 0) { - $this->runChild($i); - exit(0); - } else { - $this->log(LOG_INFO, "Spawned thread $i as pid $pid"); - $children[$i] = $pid; - } - } - - $this->log(LOG_INFO, "Waiting for children to complete."); - while (count($children) > 0) { - $status = null; - $pid = pcntl_wait($status); - if ($pid > 0) { - $i = array_search($pid, $children); - if ($i === false) { - $this->log(LOG_ERR, "Unrecognized child pid $pid exited!"); - continue; - } - unset($children[$i]); - $this->log(LOG_INFO, "Thread $i pid $pid exited."); - - $pid = pcntl_fork(); - if ($pid < 0) { - print "Couldn't fork to respawn thread $i; aborting thread.\n"; - } else if ($pid == 0) { - $this->runChild($i); - exit(0); - } else { - $this->log(LOG_INFO, "Respawned thread $i as pid $pid"); - $children[$i] = $pid; - } - } - } - $this->log(LOG_INFO, "All child processes complete."); - return true; - } - - function runChild($thread) - { - $this->set_id($this->get_id() . "." . $thread); - $this->resetDb(); - $this->runLoop(); - } - - /** - * Reconnect to the database for each child process, - * or they'll get very confused trying to use the - * same socket. - */ - function resetDb() - { - // @fixme do we need to explicitly open the db too - // or is this implied? - global $_DB_DATAOBJECT; - unset($_DB_DATAOBJECT['CONNECTIONS']); - - // Reconnect main memcached, or threads will stomp on - // each other and corrupt their requests. - $cache = common_memcache(); - if ($cache) { - $cache->reconnect(); - } - - // Also reconnect memcached for status_network table. - if (!empty(Status_network::$cache)) { - Status_network::$cache->close(); - Status_network::$cache = null; - } } /** * Setup and start of run loop for this queue handler as a daemon. * Most of the heavy lifting is passed on to the QueueManager's service() - * method, which passes control on to the QueueHandler's handle_notice() - * method for each notice that comes in on the queue. - * - * Most of the time this won't need to be overridden in a subclass. + * method, which passes control on to the QueueHandler's handle() + * method for each item that comes in on the queue. * * @return boolean true on success, false on failure */ - function runLoop() + function runThread() { $this->log(LOG_INFO, 'checking for queued notices'); - $master = new IoMaster($this->get_id()); + $master = new QueueMaster($this->get_id()); $master->init($this->all); $master->service(); @@ -229,10 +117,25 @@ class QueueDaemon extends Daemon return true; } +} - function log($level, $msg) +class QueueMaster extends IoMaster +{ + /** + * Initialize IoManagers for the currently configured site + * which are appropriate to this instance. + */ + function initManagers() { - common_log($level, get_class($this) . ' ('. $this->get_id() .'): '.$msg); + $classes = array(); + if (Event::handle('StartQueueDaemonIoManagers', array(&$classes))) { + $classes[] = 'QueueManager'; + } + Event::handle('EndQueueDaemonIoManagers', array(&$classes)); + + foreach ($classes as $class) { + $this->instantiate($class); + } } } diff --git a/scripts/xmppdaemon.php b/scripts/xmppdaemon.php index cef9c4bd07..fd7cf055b4 100755 --- a/scripts/xmppdaemon.php +++ b/scripts/xmppdaemon.php @@ -33,347 +33,46 @@ END_OF_XMPP_HELP; require_once INSTALLDIR.'/scripts/commandline.inc'; -require_once INSTALLDIR . '/lib/common.php'; require_once INSTALLDIR . '/lib/jabber.php'; -require_once INSTALLDIR . '/lib/daemon.php'; -# This is kind of clunky; we create a class to call the global functions -# in jabber.php, which create a new XMPP class. A more elegant (?) solution -# might be to use make this a subclass of XMPP. - -class XMPPDaemon extends Daemon +class XMPPDaemon extends SpawningDaemon { - function __construct($resource=null, $daemonize=true) + function __construct($id=null, $daemonize=true, $threads=1) { - parent::__construct($daemonize); - - static $attrs = array('server', 'port', 'user', 'password', 'host'); - - foreach ($attrs as $attr) - { - $this->$attr = common_config('xmpp', $attr); + if ($threads != 1) { + // This should never happen. :) + throw new Exception("XMPPDaemon can must run single-threaded"); } - - if ($resource) { - $this->resource = $resource . 'daemon'; - } else { - $this->resource = common_config('xmpp', 'resource') . 'daemon'; - } - - $this->jid = $this->user.'@'.$this->server.'/'.$this->resource; - - $this->log(LOG_INFO, "INITIALIZE XMPPDaemon {$this->jid}"); + parent::__construct($id, $daemonize, $threads); } - function connect() + function runThread() { - $connect_to = ($this->host) ? $this->host : $this->server; + common_log(LOG_INFO, 'Waiting to listen to XMPP and queues'); - $this->log(LOG_INFO, "Connecting to $connect_to on port $this->port"); + $master = new XmppMaster($this->get_id()); + $master->init(); + $master->service(); - $this->conn = jabber_connect($this->resource); + common_log(LOG_INFO, 'terminating normally'); - if (!$this->conn) { - return false; - } - - $this->log(LOG_INFO, "Connected"); - - $this->conn->setReconnectTimeout(600); - - $this->log(LOG_INFO, "Sending initial presence."); - - jabber_send_presence("Send me a message to post a notice", 'available', - null, 'available', 100); - - $this->log(LOG_INFO, "Done connecting."); - - return !$this->conn->isDisconnected(); + return true; } - function name() +} + +class XmppMaster extends IoMaster +{ + /** + * Initialize IoManagers for the currently configured site + * which are appropriate to this instance. + */ + function initManagers() { - return strtolower('xmppdaemon.'.$this->resource); - } - - function run() - { - if ($this->connect()) { - - $this->log(LOG_DEBUG, "Initializing stanza handlers."); - - $this->conn->addEventHandler('message', 'handle_message', $this); - $this->conn->addEventHandler('presence', 'handle_presence', $this); - $this->conn->addEventHandler('reconnect', 'handle_reconnect', $this); - - $this->log(LOG_DEBUG, "Beginning processing loop."); - - while ($this->conn->processTime(60)) { - $this->sendPing(); - } - } - } - - function sendPing() - { - if (!isset($this->pingid)) { - $this->pingid = 0; - } else { - $this->pingid++; - } - - $this->log(LOG_DEBUG, "Sending ping #{$this->pingid}"); - - $this->conn->send(""); - } - - function handle_reconnect(&$pl) - { - $this->log(LOG_DEBUG, "Got reconnection callback."); - $this->conn->processUntil('session_start'); - $this->log(LOG_DEBUG, "Sending reconnection presence."); - $this->conn->presence('Send me a message to post a notice', 'available', null, 'available', 100); - unset($pl['xml']); - $pl['xml'] = null; - - $pl = null; - unset($pl); - } - - function get_user($from) - { - $user = User::staticGet('jabber', jabber_normalize_jid($from)); - return $user; - } - - function handle_message(&$pl) - { - $from = jabber_normalize_jid($pl['from']); - - if ($pl['type'] != 'chat') { - $this->log(LOG_WARNING, "Ignoring message of type ".$pl['type']." from $from."); - return; - } - - if (mb_strlen($pl['body']) == 0) { - $this->log(LOG_WARNING, "Ignoring message with empty body from $from."); - return; - } - - # Forwarded from another daemon (probably a broadcaster) for - # us to handle - - if ($this->is_self($from)) { - $this->log(LOG_INFO, "Got forwarded notice from self ($from)."); - $from = $this->get_ofrom($pl); - $this->log(LOG_INFO, "Originally sent by $from."); - if (is_null($from) || $this->is_self($from)) { - $this->log(LOG_INFO, "Ignoring notice originally sent by $from."); - return; - } - } - - $user = $this->get_user($from); - - // For common_current_user to work - global $_cur; - $_cur = $user; - - if (!$user) { - $this->from_site($from, 'Unknown user; go to ' . - common_local_url('imsettings') . - ' to add your address to your account'); - $this->log(LOG_WARNING, 'Message from unknown user ' . $from); - return; - } - if ($this->handle_command($user, $pl['body'])) { - $this->log(LOG_INFO, "Command message by $from handled."); - return; - } else if ($this->is_autoreply($pl['body'])) { - $this->log(LOG_INFO, 'Ignoring auto reply from ' . $from); - return; - } else if ($this->is_otr($pl['body'])) { - $this->log(LOG_INFO, 'Ignoring OTR from ' . $from); - return; - } else { - - $this->log(LOG_INFO, 'Posting a notice from ' . $user->nickname); - - $this->add_notice($user, $pl); - } - - $user->free(); - unset($user); - unset($_cur); - - unset($pl['xml']); - $pl['xml'] = null; - - $pl = null; - unset($pl); - } - - function is_self($from) - { - return preg_match('/^'.strtolower(jabber_daemon_address()).'/', strtolower($from)); - } - - function get_ofrom($pl) - { - $xml = $pl['xml']; - $addresses = $xml->sub('addresses'); - if (!$addresses) { - $this->log(LOG_WARNING, 'Forwarded message without addresses'); - return null; - } - $address = $addresses->sub('address'); - if (!$address) { - $this->log(LOG_WARNING, 'Forwarded message without address'); - return null; - } - if (!array_key_exists('type', $address->attrs)) { - $this->log(LOG_WARNING, 'No type for forwarded message'); - return null; - } - $type = $address->attrs['type']; - if ($type != 'ofrom') { - $this->log(LOG_WARNING, 'Type of forwarded message is not ofrom'); - return null; - } - if (!array_key_exists('jid', $address->attrs)) { - $this->log(LOG_WARNING, 'No jid for forwarded message'); - return null; - } - $jid = $address->attrs['jid']; - if (!$jid) { - $this->log(LOG_WARNING, 'Could not get jid from address'); - return null; - } - $this->log(LOG_DEBUG, 'Got message forwarded from jid ' . $jid); - return $jid; - } - - function is_autoreply($txt) - { - if (preg_match('/[\[\(]?[Aa]uto[-\s]?[Rr]e(ply|sponse)[\]\)]/', $txt)) { - return true; - } else if (preg_match('/^System: Message wasn\'t delivered. Offline storage size was exceeded.$/', $txt)) { - return true; - } else { - return false; - } - } - - function is_otr($txt) - { - if (preg_match('/^\?OTR/', $txt)) { - return true; - } else { - return false; - } - } - - function from_site($address, $msg) - { - $text = '['.common_config('site', 'name') . '] ' . $msg; - jabber_send_message($address, $text); - } - - function handle_command($user, $body) - { - $inter = new CommandInterpreter(); - $cmd = $inter->handle_command($user, $body); - if ($cmd) { - $chan = new XMPPChannel($this->conn); - $cmd->execute($chan); - return true; - } else { - return false; - } - } - - function add_notice(&$user, &$pl) - { - $body = trim($pl['body']); - $content_shortened = common_shorten_links($body); - if (Notice::contentTooLong($content_shortened)) { - $from = jabber_normalize_jid($pl['from']); - $this->from_site($from, sprintf(_('Message too long - maximum is %1$d characters, you sent %2$d.'), - Notice::maxContent(), - mb_strlen($content_shortened))); - return; - } - - try { - $notice = Notice::saveNew($user->id, $content_shortened, 'xmpp'); - } catch (Exception $e) { - $this->log(LOG_ERR, $e->getMessage()); - $this->from_site($user->jabber, $e->getMessage()); - return; - } - - common_broadcast_notice($notice); - $this->log(LOG_INFO, - 'Added notice ' . $notice->id . ' from user ' . $user->nickname); - $notice->free(); - unset($notice); - } - - function handle_presence(&$pl) - { - $from = jabber_normalize_jid($pl['from']); - switch ($pl['type']) { - case 'subscribe': - # We let anyone subscribe - $this->subscribed($from); - $this->log(LOG_INFO, - 'Accepted subscription from ' . $from); - break; - case 'subscribed': - case 'unsubscribed': - case 'unsubscribe': - $this->log(LOG_INFO, - 'Ignoring "' . $pl['type'] . '" from ' . $from); - break; - default: - if (!$pl['type']) { - $user = User::staticGet('jabber', $from); - if (!$user) { - $this->log(LOG_WARNING, 'Presence from unknown user ' . $from); - return; - } - if ($user->updatefrompresence) { - $this->log(LOG_INFO, 'Updating ' . $user->nickname . - ' status from presence.'); - $this->add_notice($user, $pl); - } - $user->free(); - unset($user); - } - break; - } - unset($pl['xml']); - $pl['xml'] = null; - - $pl = null; - unset($pl); - } - - function log($level, $msg) - { - $text = 'XMPPDaemon('.$this->resource.'): '.$msg; - common_log($level, $text); - if (!$this->daemonize) - { - $line = common_log_line($level, $text); - echo $line; - echo "\n"; - } - } - - function subscribed($to) - { - jabber_special_presence('subscribed', $to); + // @fixme right now there's a hack in QueueManager to determine + // which queues to subscribe to based on the master class. + $this->instantiate('QueueManager'); + $this->instantiate('XmppManager'); } } From 672126968f42ebda3cc444190c4364ea35144dad Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Fri, 22 Jan 2010 10:12:26 -0500 Subject: [PATCH 39/53] Updated some references to the long gnone "isEnclosure" function to the new "getEnclosure" --- classes/File.php | 2 ++ lib/api.php | 9 +++++---- lib/util.php | 15 ++++----------- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/classes/File.php b/classes/File.php index c527c4ffe9..34e4632a8c 100644 --- a/classes/File.php +++ b/classes/File.php @@ -251,6 +251,8 @@ class File extends Memcached_DataObject if($oembed->modified) $enclosure->modified=$oembed->modified; unset($oembed->size); } + } else { + return false; } } } diff --git a/lib/api.php b/lib/api.php index 794b140507..b4803fe62d 100644 --- a/lib/api.php +++ b/lib/api.php @@ -288,11 +288,12 @@ class ApiAction extends Action $twitter_status['attachments'] = array(); foreach ($attachments as $attachment) { - if ($attachment->isEnclosure()) { + $enclosure_o=$attachment->getEnclosure(); + if ($attachment_enclosure) { $enclosure = array(); - $enclosure['url'] = $attachment->url; - $enclosure['mimetype'] = $attachment->mimetype; - $enclosure['size'] = $attachment->size; + $enclosure['url'] = $enclosure_o->url; + $enclosure['mimetype'] = $enclosure_o->mimetype; + $enclosure['size'] = $enclosure_o->size; $twitter_status['attachments'][] = $enclosure; } } diff --git a/lib/util.php b/lib/util.php index fb3b8be876..01b159ac15 100644 --- a/lib/util.php +++ b/lib/util.php @@ -596,20 +596,13 @@ function common_linkify($url) { } if (!empty($f)) { - if ($f->isEnclosure()) { + if ($f->getEnclosure()) { $is_attachment = true; $attachment_id = $f->id; - } else { - $foe = File_oembed::staticGet('file_id', $f->id); - if (!empty($foe)) { - // if it has OEmbed info, it's an attachment, too - $is_attachment = true; - $attachment_id = $f->id; - $thumb = File_thumbnail::staticGet('file_id', $f->id); - if (!empty($thumb)) { - $has_thumb = true; - } + $thumb = File_thumbnail::staticGet('file_id', $f->id); + if (!empty($thumb)) { + $has_thumb = true; } } } From 7be5e7e524bbe3a789b2f352f14a011fc1dc8ba2 Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Fri, 22 Jan 2010 10:40:21 -0500 Subject: [PATCH 40/53] stupid mistake... let's not talk about this. --- lib/api.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/api.php b/lib/api.php index b4803fe62d..825262b4c1 100644 --- a/lib/api.php +++ b/lib/api.php @@ -289,7 +289,7 @@ class ApiAction extends Action foreach ($attachments as $attachment) { $enclosure_o=$attachment->getEnclosure(); - if ($attachment_enclosure) { + if ($enclosure_o) { $enclosure = array(); $enclosure['url'] = $enclosure_o->url; $enclosure['mimetype'] = $enclosure_o->mimetype; From a3e484a0e898bb94dd45cd7807bea1a931d7c6a9 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 22 Jan 2010 10:46:11 -0500 Subject: [PATCH 41/53] Memcached_DataObject unnecessarily require_once'd itself --- classes/Memcached_DataObject.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/classes/Memcached_DataObject.php b/classes/Memcached_DataObject.php index 4ecab9db62..6ddef48160 100644 --- a/classes/Memcached_DataObject.php +++ b/classes/Memcached_DataObject.php @@ -19,8 +19,6 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } -require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; - class Memcached_DataObject extends DB_DataObject { /** @@ -353,7 +351,7 @@ class Memcached_DataObject extends DB_DataObject unset($_DB_DATAOBJECT['CONNECTIONS'][$index]); } } - + $result = parent::_connect(); if ($result && !$exists) { From b7940ef39f476b6a4cd7619267b735e98b0d7cfa Mon Sep 17 00:00:00 2001 From: Eric Helgeson Date: Fri, 22 Jan 2010 11:02:23 -0500 Subject: [PATCH 42/53] Fix unqueuemanager to work with new Queue layout pushed in 0e852def6ae5aa529cca0aef1187152fb5a880be "* Queue handlers should now define a handle() method instead of handle_notice()" And Queue managers should call handle() :) --- lib/unqueuemanager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/unqueuemanager.php b/lib/unqueuemanager.php index 5595eac052..785de7c8ce 100644 --- a/lib/unqueuemanager.php +++ b/lib/unqueuemanager.php @@ -47,7 +47,7 @@ class UnQueueManager extends QueueManager $handler = $this->getHandler($queue); if ($handler) { - $handler->handle_notice($notice); + $handler->handle($notice); } else { if (Event::handle('UnqueueHandleNotice', array(&$notice, $queue))) { throw new ServerException("UnQueueManager: Unknown queue: $queue"); From c9aafe2d4ff8ae2057d124e3ca281679c7ff0885 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Fri, 22 Jan 2010 19:18:14 +0100 Subject: [PATCH 43/53] Fixed innerHTML problem in IE7 and 8 for badge script --- js/identica-badge.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/identica-badge.js b/js/identica-badge.js index 8276f22a1d..e43d1c43c7 100644 --- a/js/identica-badge.js +++ b/js/identica-badge.js @@ -223,7 +223,7 @@ function markupPost(raw, server) { }, changeUserTo : function(el) { $.a.user = el.rel; - $.s.h.a.innerHTML = el.rev + $.a.headerText; + $.s.h.a.appendChild(document.createTextNode(el.rev + $.a.headerText)); $.s.h.a.href = 'http://' + $.a.server + '/' + el.id; $.f.runSearch(); }, From df9b780706eec9ff67e97803f5f70b475b010281 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Tue, 6 Oct 2009 15:29:22 -0400 Subject: [PATCH 44/53] action/doc.php is PHPCS clean --- actions/doc.php | 61 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/actions/doc.php b/actions/doc.php index 836f039d32..5df18a859f 100644 --- a/actions/doc.php +++ b/actions/doc.php @@ -49,7 +49,7 @@ class DocAction extends Action var $title; /** - * Class handler. + * Handle a request * * @param array $args array of arguments * @@ -71,6 +71,7 @@ class DocAction extends Action } $c = file_get_contents($this->filename); + $this->output = common_markup_to_html($c); Event::handle('EndLoadDoc', array($this->title, &$this->output)); @@ -79,30 +80,48 @@ class DocAction extends Action $this->showPage(); } - // overrrided to add entry-title class - function showPageTitle() { + /** + * Page title + * + * Gives the page title of the document. Override default for hAtom entry. + * + * @return void + */ + + function showPageTitle() + { $this->element('h1', array('class' => 'entry-title'), $this->title()); } - // overrided to add hentry, and content-inner classes + /** + * Block for content. + * + * Overrides default from Action to wrap everything in an hAtom entry. + * + * @return void. + */ + function showContentBlock() - { - $this->elementStart('div', array('id' => 'content', 'class' => 'hentry')); - $this->showPageTitle(); - $this->showPageNoticeBlock(); - $this->elementStart('div', array('id' => 'content_inner', - 'class' => 'entry-content')); - // show the actual content (forms, lists, whatever) - $this->showContent(); - $this->elementEnd('div'); - $this->elementEnd('div'); - } + { + $this->elementStart('div', array('id' => 'content', 'class' => 'hentry')); + $this->showPageTitle(); + $this->showPageNoticeBlock(); + $this->elementStart('div', array('id' => 'content_inner', + 'class' => 'entry-content')); + // show the actual content (forms, lists, whatever) + $this->showContent(); + $this->elementEnd('div'); + $this->elementEnd('div'); + } /** * Display content. * - * @return nothing + * Shows the content of the document. + * + * @return void */ + function showContent() { $this->raw($this->output); @@ -111,6 +130,8 @@ class DocAction extends Action /** * Page title. * + * Uses the title of the document. + * * @return page title */ function title() @@ -118,6 +139,14 @@ class DocAction extends Action return ucfirst($this->title); } + /** + * These pages are read-only. + * + * @param array $args unused. + * + * @return boolean read-only flag (false) + */ + function isReadOnly($args) { return true; From 9f815c968f855b75e82224d85314007ec0613aad Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Wed, 7 Oct 2009 05:14:25 -0400 Subject: [PATCH 45/53] restructure doc.php for new use --- actions/doc.php | 75 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 54 insertions(+), 21 deletions(-) diff --git a/actions/doc.php b/actions/doc.php index 5df18a859f..99c2c79665 100644 --- a/actions/doc.php +++ b/actions/doc.php @@ -45,8 +45,18 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { */ class DocAction extends Action { - var $filename; - var $title; + var $output = null; + var $filename = null; + var $title = null; + + function prepare($args) + { + $this->title = $this->trimmed('title'); + $this->output = null; + + $this->loadDoc(); + return true; + } /** * Handle a request @@ -58,25 +68,6 @@ class DocAction extends Action function handle($args) { parent::handle($args); - - $this->title = $this->trimmed('title'); - $this->output = null; - - if (Event::handle('StartLoadDoc', array(&$this->title, &$this->output))) { - - $this->filename = INSTALLDIR.'/doc-src/'.$this->title; - if (!file_exists($this->filename)) { - $this->clientError(_('No such document.')); - return; - } - - $c = file_get_contents($this->filename); - - $this->output = common_markup_to_html($c); - - Event::handle('EndLoadDoc', array($this->title, &$this->output)); - } - $this->showPage(); } @@ -151,4 +142,46 @@ class DocAction extends Action { return true; } + + function loadDoc() + { + if (Event::handle('StartLoadDoc', array(&$this->title, &$this->output))) { + + $this->filename = $this->getFilename(); + + if (empty($this->filename)) { + throw new ClientException(sprintf(_('No such document "%s"'), $this->title), 404); + } + + $c = file_get_contents($this->filename); + + $this->output = common_markup_to_html($c); + + Event::handle('EndLoadDoc', array($this->title, &$this->output)); + } + } + + function getFilename() + { + $local = array_merge(glob(INSTALLDIR.'/local/doc-src/'.$this->title), + glob(INSTALLDIR.'/local/doc-src/'.$this->title.'.*')); + + if (count($local)) { + return $this->negotiateLanguage($local); + } + + $dist = array_merge(glob(INSTALLDIR.'/doc-src/'.$this->title), + glob(INSTALLDIR.'/doc-src/'.$this->title.'.*')); + + if (count($dist)) { + return $this->negotiateLanguage($dist); + } + + return null; + } + + function negotiateLanguage($files) + { + // FIXME: write this + } } From 104d300799c0817bdbe893f08fd9b46d37a75a80 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Fri, 22 Jan 2010 14:13:28 -0500 Subject: [PATCH 46/53] do actual language negotiation for help docs --- actions/doc.php | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/actions/doc.php b/actions/doc.php index 99c2c79665..25d363472a 100644 --- a/actions/doc.php +++ b/actions/doc.php @@ -51,6 +51,8 @@ class DocAction extends Action function prepare($args) { + parent::prepare($args); + $this->title = $this->trimmed('title'); $this->output = null; @@ -163,25 +165,41 @@ class DocAction extends Action function getFilename() { - $local = array_merge(glob(INSTALLDIR.'/local/doc-src/'.$this->title), - glob(INSTALLDIR.'/local/doc-src/'.$this->title.'.*')); - - if (count($local)) { - return $this->negotiateLanguage($local); + if (file_exists(INSTALLDIR.'/local/doc-src/'.$this->title)) { + $localDef = INSTALLDIR.'/local/doc-src/'.$this->title; } - $dist = array_merge(glob(INSTALLDIR.'/doc-src/'.$this->title), - glob(INSTALLDIR.'/doc-src/'.$this->title.'.*')); + $local = glob(INSTALLDIR.'/local/doc-src/'.$this->title.'.*'); - if (count($dist)) { - return $this->negotiateLanguage($dist); + if (count($local) || isset($localDef)) { + return $this->negotiateLanguage($local, $localDef); + } + + if (file_exists(INSTALLDIR.'/doc-src/'.$this->title)) { + $distDef = INSTALLDIR.'/doc-src/'.$this->title; + } + + $dist = glob(INSTALLDIR.'/doc-src/'.$this->title.'.*'); + + if (count($dist) || isset($distDef)) { + return $this->negotiateLanguage($dist, $distDef); } return null; } - function negotiateLanguage($files) + function negotiateLanguage($filenames, $defaultFilename=null) { - // FIXME: write this + // XXX: do this better + + $langcode = common_language(); + + foreach ($filenames as $filename) { + if (preg_match('/\.'.$langcode.'$/', $filename)) { + return $filename; + } + } + + return $defaultFilename; } } From 8bf2a9046bd364f684374b0388c8ea1a71b5ae0b Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Fri, 22 Jan 2010 19:18:14 +0100 Subject: [PATCH 47/53] Fixed innerHTML problem in IE7 and 8 for badge script --- js/identica-badge.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/identica-badge.js b/js/identica-badge.js index 8276f22a1d..e43d1c43c7 100644 --- a/js/identica-badge.js +++ b/js/identica-badge.js @@ -223,7 +223,7 @@ function markupPost(raw, server) { }, changeUserTo : function(el) { $.a.user = el.rel; - $.s.h.a.innerHTML = el.rev + $.a.headerText; + $.s.h.a.appendChild(document.createTextNode(el.rev + $.a.headerText)); $.s.h.a.href = 'http://' + $.a.server + '/' + el.id; $.f.runSearch(); }, From 99866a459bff927c4a72c17904d2ecbc1c421af3 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Fri, 22 Jan 2010 12:35:05 -0800 Subject: [PATCH 48/53] Fix for stuck queue messages: wrap processing in stomp transactions so our lack of an ACK if PHP dies actually triggers redelivery. Previously, messages once delivered would just get stuck in the queue seemingly forever if they never got ACKed. Note this could lead to partial duplication, for instance if the OMB or Twitter queue handlers die after 1/2 of the outgoing sends. Recommendations: * catch exceptions more aggressively within queue handlers (so only PHP fatal errors are likely to kill in the middle) * for processing that involves sending to multiple clients, consider a second queue similar to the XMPP output, eg for OMB: - first queue gets delivery list and builds message data, enqueueing it for each target address - second queue can handle each individual outgoing message (and attempt redelivery etc separately) This would also protect better against a recurring error preventing delivery in the second part, and could spread out any slow sends over multiple threads. --- lib/stompqueuemanager.php | 68 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 4 deletions(-) diff --git a/lib/stompqueuemanager.php b/lib/stompqueuemanager.php index f057bd9e41..8f0091a138 100644 --- a/lib/stompqueuemanager.php +++ b/lib/stompqueuemanager.php @@ -41,6 +41,10 @@ class StompQueueManager extends QueueManager protected $sites = array(); + protected $useTransactions = true; + protected $transaction = null; + protected $transactionCount = 0; + function __construct() { parent::__construct(); @@ -201,6 +205,7 @@ class StompQueueManager extends QueueManager } else { $this->doSubscribe(); } + $this->begin(); return true; } @@ -213,6 +218,9 @@ class StompQueueManager extends QueueManager */ public function finish() { + // If there are any outstanding delivered messages we haven't processed, + // free them for another thread to take. + $this->rollback(); if ($this->sites) { foreach ($this->sites as $server) { StatusNet::init($server); @@ -293,7 +301,9 @@ class StompQueueManager extends QueueManager $notice = Notice::staticGet('id', $id); if (empty($notice)) { $this->_log(LOG_WARNING, "Skipping missing $info"); - $this->con->ack($frame); + $this->ack($frame); + $this->commit(); + $this->begin(); $this->stats('badnotice', $queue); return false; } @@ -308,7 +318,9 @@ class StompQueueManager extends QueueManager $handler = $this->getHandler($queue); if (!$handler) { $this->_log(LOG_ERROR, "Missing handler class; skipping $info"); - $this->con->ack($frame); + $this->ack($frame); + $this->commit(); + $this->begin(); $this->stats('badhandler', $queue); return false; } @@ -320,14 +332,18 @@ class StompQueueManager extends QueueManager // FIXME we probably shouldn't have to do // this kind of queue management ourselves; // if we don't ack, it should resend... - $this->con->ack($frame); + $this->ack($frame); $this->enqueue($item, $queue); + $this->commit(); + $this->begin(); $this->stats('requeued', $queue); return false; } $this->_log(LOG_INFO, "Successfully handled $info"); - $this->con->ack($frame); + $this->ack($frame); + $this->commit(); + $this->begin(); $this->stats('handled', $queue); return true; } @@ -369,5 +385,49 @@ class StompQueueManager extends QueueManager { common_log($level, 'StompQueueManager: '.$msg); } + + protected function begin() + { + if ($this->useTransactions) { + if ($this->transaction) { + throw new Exception("Tried to start transaction in the middle of a transaction"); + } + $this->transactionCount++; + $this->transaction = $this->master->id . '-' . $this->transactionCount . '-' . time(); + $this->con->begin($this->transaction); + } + } + + protected function ack($frame) + { + if ($this->useTransactions) { + if (!$this->transaction) { + throw new Exception("Tried to ack but not in a transaction"); + } + } + $this->con->ack($frame, $this->transaction); + } + + protected function commit() + { + if ($this->useTransactions) { + if (!$this->transaction) { + throw new Exception("Tried to commit but not in a transaction"); + } + $this->con->commit($this->transaction); + $this->transaction = null; + } + } + + protected function rollback() + { + if ($this->useTransactions) { + if (!$this->transaction) { + throw new Exception("Tried to rollback but not in a transaction"); + } + $this->con->commit($this->transaction); + $this->transaction = null; + } + } } From 6d055ce09ea516f115a7c21a59d11f9257ce0d9e Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Fri, 22 Jan 2010 13:49:05 -0800 Subject: [PATCH 49/53] Fix unqueuemanager for updated QueueHandler interface --- lib/unqueuemanager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/unqueuemanager.php b/lib/unqueuemanager.php index 5595eac052..785de7c8ce 100644 --- a/lib/unqueuemanager.php +++ b/lib/unqueuemanager.php @@ -47,7 +47,7 @@ class UnQueueManager extends QueueManager $handler = $this->getHandler($queue); if ($handler) { - $handler->handle_notice($notice); + $handler->handle($notice); } else { if (Event::handle('UnqueueHandleNotice', array(&$notice, $queue))) { throw new ServerException("UnQueueManager: Unknown queue: $queue"); From 71b3b9ee2be6973c3f55a59811ae103321c5abcc Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Fri, 22 Jan 2010 13:58:20 -0800 Subject: [PATCH 50/53] Consolidate PuSH publishing ping into a single POST for all feeds, and fix server response (if any on failure) to go to log instead of stdout. --- plugins/PubSubHubBub/PubSubHubBubPlugin.php | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/plugins/PubSubHubBub/PubSubHubBubPlugin.php b/plugins/PubSubHubBub/PubSubHubBubPlugin.php index 8286cd5489..ce6086df94 100644 --- a/plugins/PubSubHubBub/PubSubHubBubPlugin.php +++ b/plugins/PubSubHubBub/PubSubHubBubPlugin.php @@ -211,13 +211,20 @@ class PubSubHubBubPlugin extends Plugin 'format' => 'atom')); } } + $feeds = array_unique($feeds); - foreach (array_unique($feeds) as $feed) { - if (!$publisher->publish_update($feed)) { - common_log_line(LOG_WARNING, - $feed.' was not published to hub at '. - $this->hub.':'.$publisher->last_response()); - } + ob_start(); + $ok = $publisher->publish_update($feeds); + $push_last_response = ob_get_clean(); + + if (!$ok) { + common_log(LOG_WARNING, + 'Failure publishing ' . count($feeds) . ' feeds to hub at '. + $this->hub.': '.$push_last_response); + } else { + common_log(LOG_INFO, + 'Published ' . count($feeds) . ' feeds to hub at '. + $this->hub.': '.$push_last_response); } return true; From 845f051c2f85248ef85d0a34f032792ca83f04a4 Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Fri, 22 Jan 2010 18:02:05 -0500 Subject: [PATCH 51/53] StompQueueManager uses decode() to decode queued frames --- lib/stompqueuemanager.php | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/lib/stompqueuemanager.php b/lib/stompqueuemanager.php index 8f0091a138..4bbdeedc20 100644 --- a/lib/stompqueuemanager.php +++ b/lib/stompqueuemanager.php @@ -294,26 +294,7 @@ class StompQueueManager extends QueueManager StatusNet::init($site); } - if (is_numeric($frame->body)) { - $id = intval($frame->body); - $info = "notice $id posted at {$frame->headers['created']} in queue $queue"; - - $notice = Notice::staticGet('id', $id); - if (empty($notice)) { - $this->_log(LOG_WARNING, "Skipping missing $info"); - $this->ack($frame); - $this->commit(); - $this->begin(); - $this->stats('badnotice', $queue); - return false; - } - - $item = $notice; - } else { - // @fixme should we serialize, or json, or what here? - $info = "string posted at {$frame->headers['created']} in queue $queue"; - $item = $frame->body; - } + $item = $this->decode($frame->body); $handler = $this->getHandler($queue); if (!$handler) { From 23c0d663d63c49183494ebb049160af633a2d2ec Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Sat, 23 Jan 2010 01:03:41 -0500 Subject: [PATCH 52/53] Allow for instances as well as class names to be passed as queue handlers and iomanagers. --- lib/iomaster.php | 10 +++++++--- lib/queuemanager.php | 6 ++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/iomaster.php b/lib/iomaster.php index 004e92b3ee..29bd677bd4 100644 --- a/lib/iomaster.php +++ b/lib/iomaster.php @@ -102,7 +102,7 @@ abstract class IoMaster */ protected function instantiate($class) { - if (isset($this->singletons[$class])) { + if (is_string($class) && isset($this->singletons[$class])) { // Already instantiated a multi-site-capable handler. // Just let it know it should listen to this site too! $this->singletons[$class]->addSite(common_config('site', 'server')); @@ -129,7 +129,11 @@ abstract class IoMaster protected function getManager($class) { - return call_user_func(array($class, 'get')); + if(is_object($class)){ + return $class; + } else { + return call_user_func(array($class, 'get')); + } } /** @@ -347,7 +351,7 @@ abstract class IoMaster * for per-queue and per-site records. * * @param string $key counter name - * @param array $owners list of owner keys like 'queue:jabber' or 'site:stat01' + * @param array $owners list of owner keys like 'queue:xmpp' or 'site:stat01' */ public function stats($key, $owners=array()) { diff --git a/lib/queuemanager.php b/lib/queuemanager.php index 4eb39bfa8c..b2e86b127e 100644 --- a/lib/queuemanager.php +++ b/lib/queuemanager.php @@ -181,7 +181,9 @@ abstract class QueueManager extends IoManager { if (isset($this->handlers[$queue])) { $class = $this->handlers[$queue]; - if (class_exists($class)) { + if(is_object($class)) { + return $class; + } else if (class_exists($class)) { return new $class(); } else { common_log(LOG_ERR, "Nonexistent handler class '$class' for queue '$queue'"); @@ -242,7 +244,7 @@ abstract class QueueManager extends IoManager * Only registered transports will be reliably picked up! * * @param string $transport - * @param string $class + * @param string $class class name or object instance * @param string $group */ public function connect($transport, $class, $group='queuedaemon') From 8c54151dbd2dbf99b23124ec618b2fa5570ac2ee Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Sat, 23 Jan 2010 13:08:59 -0500 Subject: [PATCH 53/53] Use StartQueueDaemonIoManagers instead of removed StartIoManagerClasses event --- plugins/Imap/ImapPlugin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/Imap/ImapPlugin.php b/plugins/Imap/ImapPlugin.php index 89a775a16a..d1e920b009 100644 --- a/plugins/Imap/ImapPlugin.php +++ b/plugins/Imap/ImapPlugin.php @@ -86,7 +86,7 @@ class ImapPlugin extends Plugin } } - function onStartIoManagerClasses(&$classes) + function onStartQueueDaemonIoManagers(&$classes) { $classes[] = new ImapManager($this); }