forked from GNUsocial/gnu-social
Merge branch '1.0.x' of git://gitorious.org/statusnet/mainline
Conflicts: actions/public.php
This commit is contained in:
@@ -145,12 +145,10 @@ class OStatusPlugin extends Plugin
|
||||
$user = $feed->getUser();
|
||||
$id = $user->id;
|
||||
$profile = $user->getProfile();
|
||||
$feed->setActivitySubject($profile->asActivityNoun('subject'));
|
||||
} else if ($feed instanceof AtomGroupNoticeFeed) {
|
||||
$salmonAction = 'groupsalmon';
|
||||
$group = $feed->getGroup();
|
||||
$id = $group->id;
|
||||
$feed->setActivitySubject($group->asActivitySubject());
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
@@ -421,12 +419,12 @@ class OStatusPlugin extends Plugin
|
||||
}
|
||||
|
||||
function onEndShowStatusNetStyles($action) {
|
||||
$action->cssLink('plugins/OStatus/theme/base/css/ostatus.css');
|
||||
$action->cssLink($this->path('theme/base/css/ostatus.css'));
|
||||
return true;
|
||||
}
|
||||
|
||||
function onEndShowStatusNetScripts($action) {
|
||||
$action->script('plugins/OStatus/js/ostatus.js');
|
||||
$action->script($this->path('js/ostatus.js'));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -994,17 +992,29 @@ class OStatusPlugin extends Plugin
|
||||
return false;
|
||||
}
|
||||
|
||||
function onStartGetProfileFromURI($uri, &$profile) {
|
||||
function onStartGetProfileFromURI($uri, &$profile)
|
||||
{
|
||||
// Don't want to do Web-based discovery on our own server,
|
||||
// so we check locally first.
|
||||
|
||||
// XXX: do discovery here instead (OStatus_profile::ensureProfileURI($uri))
|
||||
$user = User::staticGet('uri', $uri);
|
||||
|
||||
if (!empty($user)) {
|
||||
$profile = $user->getProfile();
|
||||
return false;
|
||||
}
|
||||
|
||||
$oprofile = Ostatus_profile::staticGet('uri', $uri);
|
||||
// Now, check remotely
|
||||
|
||||
if (!empty($oprofile) && !$oprofile->isGroup()) {
|
||||
$oprofile = Ostatus_profile::ensureProfileURI($uri);
|
||||
|
||||
if (!empty($oprofile)) {
|
||||
$profile = $oprofile->localProfile();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Still not a hit, so give up.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -47,6 +47,9 @@ class GroupsalmonAction extends SalmonAction
|
||||
$this->clientError(_m('No such group.'));
|
||||
}
|
||||
|
||||
|
||||
$this->target = $this->group;
|
||||
|
||||
$oprofile = Ostatus_profile::staticGet('group_id', $id);
|
||||
if ($oprofile) {
|
||||
// TRANS: Client error.
|
||||
|
@@ -115,10 +115,15 @@ class OStatusInitAction extends Action
|
||||
|
||||
$this->elementStart('ul', 'form_data');
|
||||
$this->elementStart('li', array('id' => 'ostatus_nickname'));
|
||||
// TRANS: Field label.
|
||||
$this->input('nickname', _m('User nickname'), $this->nickname,
|
||||
_m('Nickname of the user you want to follow.'));
|
||||
$this->hidden('group', $this->group); // pass-through for magic links
|
||||
if ($this->group) {
|
||||
// TRANS: Field label.
|
||||
$this->input('group', _m('Group nickname'), $this->group,
|
||||
_m('Nickname of the group you want to join.'));
|
||||
} else {
|
||||
// TRANS: Field label.
|
||||
$this->input('nickname', _m('User nickname'), $this->nickname,
|
||||
_m('Nickname of the user you want to follow.'));
|
||||
}
|
||||
$this->elementEnd('li');
|
||||
$this->elementStart('li', array('id' => 'ostatus_profile'));
|
||||
// TRANS: Field label.
|
||||
|
@@ -163,65 +163,41 @@ class OStatusSubAction extends Action
|
||||
}
|
||||
|
||||
$this->elementStart('div', 'entity_profile vcard');
|
||||
$this->elementStart('dl', 'entity_depiction');
|
||||
$this->element('dt', null, _m('Photo'));
|
||||
$this->elementStart('dd');
|
||||
$this->element('img', array('src' => $avatar,
|
||||
'class' => 'photo avatar',
|
||||
'class' => 'photo avatar entity_depiction',
|
||||
'width' => AVATAR_PROFILE_SIZE,
|
||||
'height' => AVATAR_PROFILE_SIZE,
|
||||
'alt' => $nickname));
|
||||
$this->elementEnd('dd');
|
||||
$this->elementEnd('dl');
|
||||
|
||||
$this->elementStart('dl', 'entity_nickname');
|
||||
$this->element('dt', null, _m('Nickname'));
|
||||
$this->elementStart('dd');
|
||||
$hasFN = ($fullname !== '') ? 'nickname' : 'fn nickname';
|
||||
$hasFN = ($fullname !== '') ? 'nickname' : 'fn nickname entity_nickname';
|
||||
$this->elementStart('a', array('href' => $profile,
|
||||
'class' => 'url '.$hasFN));
|
||||
$this->raw($nickname);
|
||||
$this->elementEnd('a');
|
||||
$this->elementEnd('dd');
|
||||
$this->elementEnd('dl');
|
||||
|
||||
if (!is_null($fullname)) {
|
||||
$this->elementStart('dl', 'entity_fn');
|
||||
$this->elementStart('dd');
|
||||
$this->elementStart('span', 'fn');
|
||||
$this->elementStart('div', 'fn entity_fn');
|
||||
$this->raw($fullname);
|
||||
$this->elementEnd('span');
|
||||
$this->elementEnd('dd');
|
||||
$this->elementEnd('dl');
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
|
||||
if (!is_null($location)) {
|
||||
$this->elementStart('dl', 'entity_location');
|
||||
$this->element('dt', null, _m('Location'));
|
||||
$this->elementStart('dd', 'label');
|
||||
$this->elementStart('div', 'label entity_location');
|
||||
$this->raw($location);
|
||||
$this->elementEnd('dd');
|
||||
$this->elementEnd('dl');
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
|
||||
if (!is_null($homepage)) {
|
||||
$this->elementStart('dl', 'entity_url');
|
||||
$this->element('dt', null, _m('URL'));
|
||||
$this->elementStart('dd');
|
||||
$this->elementStart('a', array('href' => $homepage,
|
||||
'class' => 'url'));
|
||||
'class' => 'url entity_url'));
|
||||
$this->raw($homepage);
|
||||
$this->elementEnd('a');
|
||||
$this->elementEnd('dd');
|
||||
$this->elementEnd('dl');
|
||||
}
|
||||
|
||||
if (!is_null($note)) {
|
||||
$this->elementStart('dl', 'entity_note');
|
||||
$this->element('dt', null, _m('Note'));
|
||||
$this->elementStart('dd', 'note');
|
||||
$this->elementStart('div', 'note entity_note');
|
||||
$this->raw($note);
|
||||
$this->elementEnd('dd');
|
||||
$this->elementEnd('dl');
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
|
@@ -43,6 +43,8 @@ class UsersalmonAction extends SalmonAction
|
||||
$this->clientError(_m('No such user.'));
|
||||
}
|
||||
|
||||
$this->target = $this->user;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -487,7 +487,15 @@ class FeedSub extends Memcached_DataObject
|
||||
if ($their_hmac === $our_hmac) {
|
||||
return true;
|
||||
}
|
||||
common_log(LOG_ERR, __METHOD__ . ": ignoring PuSH with bad SHA-1 HMAC: got $their_hmac, expected $our_hmac");
|
||||
if (common_config('feedsub', 'debug')) {
|
||||
$tempfile = tempnam(sys_get_temp_dir(), 'feedsub-receive');
|
||||
if ($tempfile) {
|
||||
file_put_contents($tempfile, $post);
|
||||
}
|
||||
common_log(LOG_ERR, __METHOD__ . ": ignoring PuSH with bad SHA-1 HMAC: got $their_hmac, expected $our_hmac for feed $this->uri on $this->huburi; saved to $tempfile");
|
||||
} else {
|
||||
common_log(LOG_ERR, __METHOD__ . ": ignoring PuSH with bad SHA-1 HMAC: got $their_hmac, expected $our_hmac for feed $this->uri on $this->huburi");
|
||||
}
|
||||
} else {
|
||||
common_log(LOG_ERR, __METHOD__ . ": ignoring PuSH with bogus HMAC '$hmac'");
|
||||
}
|
||||
|
@@ -39,11 +39,41 @@ class Magicsig extends Memcached_DataObject
|
||||
|
||||
public $__table = 'magicsig';
|
||||
|
||||
/**
|
||||
* Key to user.id/profile.id for the local user whose key we're storing.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $user_id;
|
||||
|
||||
/**
|
||||
* Flattened string representation of the key pair; callers should
|
||||
* usually use $this->publicKey and $this->privateKey directly,
|
||||
* which hold live Crypt_RSA key objects.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $keypair;
|
||||
|
||||
/**
|
||||
* Crypto algorithm used for this key; currently only RSA-SHA256 is supported.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $alg;
|
||||
|
||||
/**
|
||||
* Public RSA key; gets serialized in/out via $this->keypair string.
|
||||
*
|
||||
* @var Crypt_RSA
|
||||
*/
|
||||
public $publicKey;
|
||||
|
||||
/**
|
||||
* PrivateRSA key; gets serialized in/out via $this->keypair string.
|
||||
*
|
||||
* @var Crypt_RSA
|
||||
*/
|
||||
public $privateKey;
|
||||
|
||||
public function __construct($alg = 'RSA-SHA256')
|
||||
@@ -51,6 +81,13 @@ class Magicsig extends Memcached_DataObject
|
||||
$this->alg = $alg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a Magicsig object from the cache or database on a field match.
|
||||
*
|
||||
* @param string $k
|
||||
* @param mixed $v
|
||||
* @return Magicsig
|
||||
*/
|
||||
public /*static*/ function staticGet($k, $v=null)
|
||||
{
|
||||
$obj = parent::staticGet(__CLASS__, $k, $v);
|
||||
@@ -103,6 +140,14 @@ class Magicsig extends Memcached_DataObject
|
||||
return array(false, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save this keypair into the database.
|
||||
*
|
||||
* Overloads default insert behavior to encode the live key objects
|
||||
* as a flat string for storage.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function insert()
|
||||
{
|
||||
$this->keypair = $this->toString();
|
||||
@@ -110,6 +155,14 @@ class Magicsig extends Memcached_DataObject
|
||||
return parent::insert();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a new keypair for a local user and store in the database.
|
||||
*
|
||||
* Warning: this can be very slow on systems without the GMP module.
|
||||
* Runtimes of 20-30 seconds are not unheard-of.
|
||||
*
|
||||
* @param int $user_id id of local user we're creating a key for
|
||||
*/
|
||||
public function generate($user_id)
|
||||
{
|
||||
$rsa = new Crypt_RSA();
|
||||
@@ -128,6 +181,12 @@ class Magicsig extends Memcached_DataObject
|
||||
$this->insert();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode the keypair or public key as a string.
|
||||
*
|
||||
* @param boolean $full_pair set to false to leave out the private key.
|
||||
* @return string
|
||||
*/
|
||||
public function toString($full_pair = true)
|
||||
{
|
||||
$mod = Magicsig::base64_url_encode($this->publicKey->modulus->toBytes());
|
||||
@@ -140,6 +199,13 @@ class Magicsig extends Memcached_DataObject
|
||||
return 'RSA.' . $mod . '.' . $exp . $private_exp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a string representation of an RSA public key or keypair
|
||||
* as a Magicsig object which can be used to sign or verify.
|
||||
*
|
||||
* @param string $text
|
||||
* @return Magicsig
|
||||
*/
|
||||
public static function fromString($text)
|
||||
{
|
||||
$magic_sig = new Magicsig();
|
||||
@@ -168,6 +234,14 @@ class Magicsig extends Memcached_DataObject
|
||||
return $magic_sig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill out $this->privateKey or $this->publicKey with a Crypt_RSA object
|
||||
* representing the give key (as mod/exponent pair).
|
||||
*
|
||||
* @param string $mod base64-encoded
|
||||
* @param string $exp base64-encoded exponent
|
||||
* @param string $type one of 'public' or 'private'
|
||||
*/
|
||||
public function loadKey($mod, $exp, $type = 'public')
|
||||
{
|
||||
common_log(LOG_DEBUG, "Adding ".$type." key: (".$mod .', '. $exp .")");
|
||||
@@ -186,11 +260,22 @@ class Magicsig extends Memcached_DataObject
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the crypto algorithm used for this key.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->alg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of a hash function to use for signing with this key.
|
||||
*
|
||||
* @return string
|
||||
* @fixme is this used? doesn't seem to be called by name.
|
||||
*/
|
||||
public function getHash()
|
||||
{
|
||||
switch ($this->alg) {
|
||||
@@ -200,24 +285,48 @@ class Magicsig extends Memcached_DataObject
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate base64-encoded signature for the given byte string
|
||||
* using our private key.
|
||||
*
|
||||
* @param string $bytes as raw byte string
|
||||
* @return string base64-encoded signature
|
||||
*/
|
||||
public function sign($bytes)
|
||||
{
|
||||
$sig = $this->privateKey->sign($bytes);
|
||||
return Magicsig::base64_url_encode($sig);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $signed_bytes as raw byte string
|
||||
* @param string $signature as base64
|
||||
* @return boolean
|
||||
*/
|
||||
public function verify($signed_bytes, $signature)
|
||||
{
|
||||
$signature = Magicsig::base64_url_decode($signature);
|
||||
return $this->publicKey->verify($signed_bytes, $signature);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* URL-encoding-friendly base64 variant encoding.
|
||||
*
|
||||
* @param string $input
|
||||
* @return string
|
||||
*/
|
||||
public static function base64_url_encode($input)
|
||||
{
|
||||
return strtr(base64_encode($input), '+/', '-_');
|
||||
}
|
||||
|
||||
/**
|
||||
* URL-encoding-friendly base64 variant decoding.
|
||||
*
|
||||
* @param string $input
|
||||
* @return string
|
||||
*/
|
||||
public static function base64_url_decode($input)
|
||||
{
|
||||
return base64_decode(strtr($input, '-_', '+/'));
|
||||
|
@@ -293,6 +293,7 @@ class Ostatus_profile extends Managed_DataObject
|
||||
* an acceptable response from the remote site.
|
||||
*
|
||||
* @param mixed $entry XML string, Notice, or Activity
|
||||
* @param Profile $actor
|
||||
* @return boolean success
|
||||
*/
|
||||
public function notifyActivity($entry, $actor)
|
||||
@@ -419,7 +420,8 @@ class Ostatus_profile extends Managed_DataObject
|
||||
{
|
||||
$activity = new Activity($entry, $feed);
|
||||
|
||||
if (Event::handle('StartHandleFeedEntry', array($activity))) {
|
||||
if (Event::handle('StartHandleFeedEntryWithProfile', array($activity, $this)) &&
|
||||
Event::handle('StartHandleFeedEntry', array($activity))) {
|
||||
|
||||
// @todo process all activity objects
|
||||
switch ($activity->objects[0]->type) {
|
||||
@@ -441,6 +443,7 @@ class Ostatus_profile extends Managed_DataObject
|
||||
}
|
||||
|
||||
Event::handle('EndHandleFeedEntry', array($activity));
|
||||
Event::handle('EndHandleFeedEntryWithProfile', array($activity, $this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -453,36 +456,10 @@ class Ostatus_profile extends Managed_DataObject
|
||||
*/
|
||||
public function processPost($activity, $method)
|
||||
{
|
||||
if ($this->isGroup()) {
|
||||
// A group feed will contain posts from multiple authors.
|
||||
// @fixme validate these profiles in some way!
|
||||
$oprofile = self::ensureActorProfile($activity);
|
||||
if ($oprofile->isGroup()) {
|
||||
// Groups can't post notices in StatusNet.
|
||||
common_log(LOG_WARNING, "OStatus: skipping post with group listed as author: $oprofile->uri in feed from $this->uri");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$actor = $activity->actor;
|
||||
$oprofile = $this->checkAuthorship($activity);
|
||||
|
||||
if (empty($actor)) {
|
||||
// OK here! assume the default
|
||||
} else if ($actor->id == $this->uri || $actor->link == $this->uri) {
|
||||
$this->updateFromActivityObject($actor);
|
||||
} else if ($actor->id) {
|
||||
// We have an ActivityStreams actor with an explicit ID that doesn't match the feed owner.
|
||||
// This isn't what we expect from mainline OStatus person feeds!
|
||||
// Group feeds go down another path, with different validation...
|
||||
// Most likely this is a plain ol' blog feed of some kind which
|
||||
// doesn't match our expectations. We'll take the entry, but ignore
|
||||
// the <author> info.
|
||||
common_log(LOG_WARNING, "Got an actor '{$actor->title}' ({$actor->id}) on single-user feed for {$this->uri}");
|
||||
} else {
|
||||
// Plain <author> without ActivityStreams actor info.
|
||||
// We'll just ignore this info for now and save the update under the feed's identity.
|
||||
}
|
||||
|
||||
$oprofile = $this;
|
||||
if (empty($oprofile)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// It's not always an ActivityObject::NOTE, but... let's just say it is.
|
||||
@@ -897,54 +874,19 @@ class Ostatus_profile extends Managed_DataObject
|
||||
* @return Ostatus_profile
|
||||
* @throws Exception
|
||||
*/
|
||||
|
||||
public static function ensureAtomFeed($feedEl, $hints)
|
||||
{
|
||||
// Try to get a profile from the feed activity:subject
|
||||
$author = ActivityUtils::getFeedAuthor($feedEl);
|
||||
|
||||
$subject = ActivityUtils::child($feedEl, Activity::SUBJECT, Activity::SPEC);
|
||||
|
||||
if (!empty($subject)) {
|
||||
$subjObject = new ActivityObject($subject);
|
||||
return self::ensureActivityObjectProfile($subjObject, $hints);
|
||||
if (empty($author)) {
|
||||
// XXX: make some educated guesses here
|
||||
// TRANS: Feed sub exception.
|
||||
throw new FeedSubException(_m('Can\'t find enough profile '.
|
||||
'information to make a feed.'));
|
||||
}
|
||||
|
||||
// Otherwise, try the feed author
|
||||
|
||||
$author = ActivityUtils::child($feedEl, Activity::AUTHOR, Activity::ATOM);
|
||||
|
||||
if (!empty($author)) {
|
||||
$authorObject = new ActivityObject($author);
|
||||
return self::ensureActivityObjectProfile($authorObject, $hints);
|
||||
}
|
||||
|
||||
// Sheesh. Not a very nice feed! Let's try fingerpoken in the
|
||||
// entries.
|
||||
|
||||
$entries = $feedEl->getElementsByTagNameNS(Activity::ATOM, 'entry');
|
||||
|
||||
if (!empty($entries) && $entries->length > 0) {
|
||||
|
||||
$entry = $entries->item(0);
|
||||
|
||||
$actor = ActivityUtils::child($entry, Activity::ACTOR, Activity::SPEC);
|
||||
|
||||
if (!empty($actor)) {
|
||||
$actorObject = new ActivityObject($actor);
|
||||
return self::ensureActivityObjectProfile($actorObject, $hints);
|
||||
|
||||
}
|
||||
|
||||
$author = ActivityUtils::child($entry, Activity::AUTHOR, Activity::ATOM);
|
||||
|
||||
if (!empty($author)) {
|
||||
$authorObject = new ActivityObject($author);
|
||||
return self::ensureActivityObjectProfile($authorObject, $hints);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: make some educated guesses here
|
||||
// TRANS: Feed sub exception.
|
||||
throw new FeedSubException(_m('Can\'t find enough profile information to make a feed.'));
|
||||
return self::ensureActivityObjectProfile($author, $hints);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1132,7 +1074,8 @@ class Ostatus_profile extends Managed_DataObject
|
||||
return $url;
|
||||
}
|
||||
}
|
||||
return common_path('plugins/OStatus/images/96px-Feed-icon.svg.png');
|
||||
|
||||
return Plugin::staticPath('OStatus', 'images/96px-Feed-icon.svg.png');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1373,7 +1316,17 @@ class Ostatus_profile extends Managed_DataObject
|
||||
{
|
||||
$orig = clone($profile);
|
||||
|
||||
$profile->nickname = self::getActivityObjectNickname($object, $hints);
|
||||
// Existing nickname is better than nothing.
|
||||
|
||||
if (!array_key_exists('nickname', $hints)) {
|
||||
$hints['nickname'] = $profile->nickname;
|
||||
}
|
||||
|
||||
$nickname = self::getActivityObjectNickname($object, $hints);
|
||||
|
||||
if (!empty($nickname)) {
|
||||
$profile->nickname = $nickname;
|
||||
}
|
||||
|
||||
if (!empty($object->title)) {
|
||||
$profile->fullname = $object->title;
|
||||
@@ -1389,9 +1342,23 @@ class Ostatus_profile extends Managed_DataObject
|
||||
$profile->profileurl = $object->id;
|
||||
}
|
||||
|
||||
$profile->bio = self::getActivityObjectBio($object, $hints);
|
||||
$profile->location = self::getActivityObjectLocation($object, $hints);
|
||||
$profile->homepage = self::getActivityObjectHomepage($object, $hints);
|
||||
$bio = self::getActivityObjectBio($object, $hints);
|
||||
|
||||
if (!empty($bio)) {
|
||||
$profile->bio = $bio;
|
||||
}
|
||||
|
||||
$location = self::getActivityObjectLocation($object, $hints);
|
||||
|
||||
if (!empty($location)) {
|
||||
$profile->location = $location;
|
||||
}
|
||||
|
||||
$homepage = self::getActivityObjectHomepage($object, $hints);
|
||||
|
||||
if (!empty($homepage)) {
|
||||
$profile->homepage = $homepage;
|
||||
}
|
||||
|
||||
if (!empty($object->geopoint)) {
|
||||
$location = ActivityContext::locationFromPoint($object->geopoint);
|
||||
@@ -1799,12 +1766,55 @@ class Ostatus_profile extends Managed_DataObject
|
||||
case 'mailto':
|
||||
$rest = $match[2];
|
||||
$oprofile = Ostatus_profile::ensureWebfinger($rest);
|
||||
break;
|
||||
default:
|
||||
common_log("Unrecognized URI protocol for profile: $protocol ($uri)");
|
||||
throw new ServerException("Unrecognized URI protocol for profile: $protocol ($uri)");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
throw new ServerException("No URI protocol for profile: ($uri)");
|
||||
}
|
||||
}
|
||||
|
||||
return $oprofile;
|
||||
}
|
||||
|
||||
function checkAuthorship($activity)
|
||||
{
|
||||
if ($this->isGroup()) {
|
||||
// A group feed will contain posts from multiple authors.
|
||||
// @fixme validate these profiles in some way!
|
||||
$oprofile = self::ensureActorProfile($activity);
|
||||
if ($oprofile->isGroup()) {
|
||||
// Groups can't post notices in StatusNet.
|
||||
common_log(LOG_WARNING,
|
||||
"OStatus: skipping post with group listed as author: ".
|
||||
"$oprofile->uri in feed from $this->uri");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$actor = $activity->actor;
|
||||
|
||||
if (empty($actor)) {
|
||||
// OK here! assume the default
|
||||
} else if ($actor->id == $this->uri || $actor->link == $this->uri) {
|
||||
$this->updateFromActivityObject($actor);
|
||||
} else if ($actor->id) {
|
||||
// We have an ActivityStreams actor with an explicit ID that doesn't match the feed owner.
|
||||
// This isn't what we expect from mainline OStatus person feeds!
|
||||
// Group feeds go down another path, with different validation...
|
||||
// Most likely this is a plain ol' blog feed of some kind which
|
||||
// doesn't match our expectations. We'll take the entry, but ignore
|
||||
// the <author> info.
|
||||
common_log(LOG_WARNING, "Got an actor '{$actor->title}' ({$actor->id}) on single-user feed for {$this->uri}");
|
||||
} else {
|
||||
// Plain <author> without ActivityStreams actor info.
|
||||
// We'll just ignore this info for now and save the update under the feed's identity.
|
||||
}
|
||||
|
||||
$oprofile = $this;
|
||||
}
|
||||
|
||||
return $oprofile;
|
||||
}
|
||||
}
|
||||
|
@@ -1,274 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet - the distributed open-source microblogging tool
|
||||
* Copyright (C) 2010, StatusNet, Inc.
|
||||
*
|
||||
* A sample module to show best practices for StatusNet plugins
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @package StatusNet
|
||||
* @author James Walker <james@status.net>
|
||||
* @copyright 2010 StatusNet, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class implements LRDD-based service discovery based on the "Hammer Draft"
|
||||
* (including webfinger)
|
||||
*
|
||||
* @see http://groups.google.com/group/webfinger/browse_thread/thread/9f3d93a479e91bbf
|
||||
*/
|
||||
class Discovery
|
||||
{
|
||||
|
||||
const LRDD_REL = 'lrdd';
|
||||
const PROFILEPAGE = 'http://webfinger.net/rel/profile-page';
|
||||
const UPDATESFROM = 'http://schemas.google.com/g/2010#updates-from';
|
||||
const HCARD = 'http://microformats.org/profile/hcard';
|
||||
|
||||
public $methods = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->registerMethod('Discovery_LRDD_Host_Meta');
|
||||
$this->registerMethod('Discovery_LRDD_Link_Header');
|
||||
$this->registerMethod('Discovery_LRDD_Link_HTML');
|
||||
}
|
||||
|
||||
public function registerMethod($class)
|
||||
{
|
||||
$this->methods[] = $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a "user id" make sure it's normalized to either a webfinger
|
||||
* acct: uri or a profile HTTP URL.
|
||||
*/
|
||||
public static function normalize($user_id)
|
||||
{
|
||||
if (substr($user_id, 0, 5) == 'http:' ||
|
||||
substr($user_id, 0, 6) == 'https:' ||
|
||||
substr($user_id, 0, 5) == 'acct:') {
|
||||
return $user_id;
|
||||
}
|
||||
|
||||
if (strpos($user_id, '@') !== FALSE) {
|
||||
return 'acct:' . $user_id;
|
||||
}
|
||||
|
||||
return 'http://' . $user_id;
|
||||
}
|
||||
|
||||
public static function isWebfinger($user_id)
|
||||
{
|
||||
$uri = Discovery::normalize($user_id);
|
||||
|
||||
return (substr($uri, 0, 5) == 'acct:');
|
||||
}
|
||||
|
||||
/**
|
||||
* This implements the actual lookup procedure
|
||||
*/
|
||||
public function lookup($id)
|
||||
{
|
||||
// Normalize the incoming $id to make sure we have a uri
|
||||
$uri = $this->normalize($id);
|
||||
|
||||
foreach ($this->methods as $class) {
|
||||
$links = call_user_func(array($class, 'discover'), $uri);
|
||||
if ($link = Discovery::getService($links, Discovery::LRDD_REL)) {
|
||||
// Load the LRDD XRD
|
||||
if (!empty($link['template'])) {
|
||||
$xrd_uri = Discovery::applyTemplate($link['template'], $uri);
|
||||
} else {
|
||||
$xrd_uri = $link['href'];
|
||||
}
|
||||
|
||||
$xrd = $this->fetchXrd($xrd_uri);
|
||||
if ($xrd) {
|
||||
return $xrd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TRANS: Exception.
|
||||
throw new Exception(sprintf(_m('Unable to find services for %s.'),$id));
|
||||
}
|
||||
|
||||
public static function getService($links, $service) {
|
||||
if (!is_array($links)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($links as $link) {
|
||||
if ($link['rel'] == $service) {
|
||||
return $link;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function applyTemplate($template, $id)
|
||||
{
|
||||
$template = str_replace('{uri}', urlencode($id), $template);
|
||||
|
||||
return $template;
|
||||
}
|
||||
|
||||
public static function fetchXrd($url)
|
||||
{
|
||||
try {
|
||||
$client = new HTTPClient();
|
||||
$response = $client->get($url);
|
||||
} catch (HTTP_Request2_Exception $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($response->getStatus() != 200) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return XRD::parse($response->getBody());
|
||||
}
|
||||
}
|
||||
|
||||
interface Discovery_LRDD
|
||||
{
|
||||
public function discover($uri);
|
||||
}
|
||||
|
||||
class Discovery_LRDD_Host_Meta implements Discovery_LRDD
|
||||
{
|
||||
public function discover($uri)
|
||||
{
|
||||
if (Discovery::isWebfinger($uri)) {
|
||||
// We have a webfinger acct: - start with host-meta
|
||||
list($name, $domain) = explode('@', $uri);
|
||||
} else {
|
||||
$domain = parse_url($uri, PHP_URL_HOST);
|
||||
}
|
||||
|
||||
$url = 'http://'. $domain .'/.well-known/host-meta';
|
||||
|
||||
$xrd = Discovery::fetchXrd($url);
|
||||
|
||||
if ($xrd) {
|
||||
if ($xrd->host != $domain) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $xrd->links;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Discovery_LRDD_Link_Header implements Discovery_LRDD
|
||||
{
|
||||
public function discover($uri)
|
||||
{
|
||||
try {
|
||||
$client = new HTTPClient();
|
||||
$response = $client->get($uri);
|
||||
} catch (HTTP_Request2_Exception $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($response->getStatus() != 200) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$link_header = $response->getHeader('Link');
|
||||
if (!$link_header) {
|
||||
// return false;
|
||||
}
|
||||
|
||||
return array(Discovery_LRDD_Link_Header::parseHeader($link_header));
|
||||
}
|
||||
|
||||
protected static function parseHeader($header)
|
||||
{
|
||||
$lh = new LinkHeader($header);
|
||||
|
||||
return array('href' => $lh->href,
|
||||
'rel' => $lh->rel,
|
||||
'type' => $lh->type);
|
||||
}
|
||||
}
|
||||
|
||||
class Discovery_LRDD_Link_HTML implements Discovery_LRDD
|
||||
{
|
||||
public function discover($uri)
|
||||
{
|
||||
try {
|
||||
$client = new HTTPClient();
|
||||
$response = $client->get($uri);
|
||||
} catch (HTTP_Request2_Exception $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($response->getStatus() != 200) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Discovery_LRDD_Link_HTML::parse($response->getBody());
|
||||
}
|
||||
|
||||
public function parse($html)
|
||||
{
|
||||
$links = array();
|
||||
|
||||
preg_match('/<head(\s[^>]*)?>(.*?)<\/head>/is', $html, $head_matches);
|
||||
$head_html = $head_matches[2];
|
||||
|
||||
preg_match_all('/<link\s[^>]*>/i', $head_html, $link_matches);
|
||||
|
||||
foreach ($link_matches[0] as $link_html) {
|
||||
$link_url = null;
|
||||
$link_rel = null;
|
||||
$link_type = null;
|
||||
|
||||
preg_match('/\srel=(("|\')([^\\2]*?)\\2|[^"\'\s]+)/i', $link_html, $rel_matches);
|
||||
if ( isset($rel_matches[3]) ) {
|
||||
$link_rel = $rel_matches[3];
|
||||
} else if ( isset($rel_matches[1]) ) {
|
||||
$link_rel = $rel_matches[1];
|
||||
}
|
||||
|
||||
preg_match('/\shref=(("|\')([^\\2]*?)\\2|[^"\'\s]+)/i', $link_html, $href_matches);
|
||||
if ( isset($href_matches[3]) ) {
|
||||
$link_uri = $href_matches[3];
|
||||
} else if ( isset($href_matches[1]) ) {
|
||||
$link_uri = $href_matches[1];
|
||||
}
|
||||
|
||||
preg_match('/\stype=(("|\')([^\\2]*?)\\2|[^"\'\s]+)/i', $link_html, $type_matches);
|
||||
if ( isset($type_matches[3]) ) {
|
||||
$link_type = $type_matches[3];
|
||||
} else if ( isset($type_matches[1]) ) {
|
||||
$link_type = $type_matches[1];
|
||||
}
|
||||
|
||||
$links[] = array(
|
||||
'href' => $link_url,
|
||||
'rel' => $link_rel,
|
||||
'type' => $link_type,
|
||||
);
|
||||
}
|
||||
|
||||
return $links;
|
||||
}
|
||||
}
|
@@ -1,66 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @todo Add file header and documentation.
|
||||
*/
|
||||
|
||||
class LinkHeader
|
||||
{
|
||||
var $href;
|
||||
var $rel;
|
||||
var $type;
|
||||
|
||||
function __construct($str)
|
||||
{
|
||||
preg_match('/^<[^>]+>/', $str, $uri_reference);
|
||||
//if (empty($uri_reference)) return;
|
||||
|
||||
$this->href = trim($uri_reference[0], '<>');
|
||||
$this->rel = array();
|
||||
$this->type = null;
|
||||
|
||||
// remove uri-reference from header
|
||||
$str = substr($str, strlen($uri_reference[0]));
|
||||
|
||||
// parse link-params
|
||||
$params = explode(';', $str);
|
||||
|
||||
foreach ($params as $param) {
|
||||
if (empty($param)) continue;
|
||||
list($param_name, $param_value) = explode('=', $param, 2);
|
||||
$param_name = trim($param_name);
|
||||
$param_value = preg_replace('(^"|"$)', '', trim($param_value));
|
||||
|
||||
// for now we only care about 'rel' and 'type' link params
|
||||
// TODO do something with the other links-params
|
||||
switch ($param_name) {
|
||||
case 'rel':
|
||||
$this->rel = trim($param_value);
|
||||
break;
|
||||
|
||||
case 'type':
|
||||
$this->type = trim($param_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static function getLink($response, $rel=null, $type=null)
|
||||
{
|
||||
$headers = $response->getHeader('Link');
|
||||
if ($headers) {
|
||||
// Can get an array or string, so try to simplify the path
|
||||
if (!is_array($headers)) {
|
||||
$headers = array($headers);
|
||||
}
|
||||
|
||||
foreach ($headers as $header) {
|
||||
$lh = new LinkHeader($header);
|
||||
|
||||
if ((is_null($rel) || $lh->rel == $rel) &&
|
||||
(is_null($type) || $lh->type == $type)) {
|
||||
return $lh->href;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -80,21 +80,53 @@ class MagicEnvelope
|
||||
throw new Exception(_m('Unable to locate signer public key.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* The current MagicEnvelope spec as used in StatusNet 0.9.7 and later
|
||||
* includes both the original data and some signing metadata fields as
|
||||
* the input plaintext for the signature hash.
|
||||
*
|
||||
* @param array $env
|
||||
* @return string
|
||||
*/
|
||||
public function signingText($env) {
|
||||
return implode('.', array($env['data'], // this field is pre-base64'd
|
||||
Magicsig::base64_url_encode($env['data_type']),
|
||||
Magicsig::base64_url_encode($env['encoding']),
|
||||
Magicsig::base64_url_encode($env['alg'])));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param <type> $text
|
||||
* @param <type> $mimetype
|
||||
* @param <type> $keypair
|
||||
* @return array: associative array of envelope properties
|
||||
* @fixme it might be easier to work with storing envelope data these in the object instead of passing arrays around
|
||||
*/
|
||||
public function signMessage($text, $mimetype, $keypair)
|
||||
{
|
||||
$signature_alg = Magicsig::fromString($keypair);
|
||||
$armored_text = Magicsig::base64_url_encode($text);
|
||||
|
||||
return array(
|
||||
$env = array(
|
||||
'data' => $armored_text,
|
||||
'encoding' => MagicEnvelope::ENCODING,
|
||||
'data_type' => $mimetype,
|
||||
'sig' => $signature_alg->sign($armored_text),
|
||||
'sig' => '',
|
||||
'alg' => $signature_alg->getName()
|
||||
);
|
||||
|
||||
$env['sig'] = $signature_alg->sign($this->signingText($env));
|
||||
|
||||
return $env;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an <me:env> XML representation of the envelope.
|
||||
*
|
||||
* @param array $env associative array with envelope data
|
||||
* @return string representation of XML document
|
||||
* @fixme it might be easier to work with storing envelope data these in the object instead of passing arrays around
|
||||
*/
|
||||
public function toXML($env) {
|
||||
$xs = new XMLStringer();
|
||||
$xs->startXML();
|
||||
@@ -110,6 +142,16 @@ class MagicEnvelope
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the contained XML payload, and insert a copy of the envelope
|
||||
* signature data as an <me:provenance> section.
|
||||
*
|
||||
* @param array $env associative array with envelope data
|
||||
* @return string representation of modified XML document
|
||||
*
|
||||
* @fixme in case of XML parsing errors, this will spew to the error log or output
|
||||
* @fixme it might be easier to work with storing envelope data these in the object instead of passing arrays around
|
||||
*/
|
||||
public function unfold($env)
|
||||
{
|
||||
$dom = new DOMDocument();
|
||||
@@ -136,6 +178,14 @@ class MagicEnvelope
|
||||
return $dom->saveXML();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the author URI referenced in the given Atom entry.
|
||||
*
|
||||
* @param string $text string containing Atom entry XML
|
||||
* @return mixed URI string or false if XML parsing fails, or null if no author URI can be found
|
||||
*
|
||||
* @fixme XML parsing failures will spew to error logs/output
|
||||
*/
|
||||
public function getAuthor($text) {
|
||||
$doc = new DOMDocument();
|
||||
if (!$doc->loadXML($text)) {
|
||||
@@ -153,11 +203,30 @@ class MagicEnvelope
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the author in the Atom entry fragment claims to match
|
||||
* the given identifier URI.
|
||||
*
|
||||
* @param string $text string containing Atom entry XML
|
||||
* @param string $signer_uri
|
||||
* @return boolean
|
||||
*/
|
||||
public function checkAuthor($text, $signer_uri)
|
||||
{
|
||||
return ($this->getAuthor($text) == $signer_uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to verify cryptographic signing for parsed envelope data.
|
||||
* Requires network access to retrieve public key referenced by the envelope signer.
|
||||
*
|
||||
* Details of failure conditions are dumped to output log and not exposed to caller.
|
||||
*
|
||||
* @param array $env array representation of magic envelope data, as returned from MagicEnvelope::parse()
|
||||
* @return boolean
|
||||
*
|
||||
* @fixme it might be easier to work with storing envelope data these in the object instead of passing arrays around
|
||||
*/
|
||||
public function verify($env)
|
||||
{
|
||||
if ($env['alg'] != 'RSA-SHA256') {
|
||||
@@ -187,15 +256,35 @@ class MagicEnvelope
|
||||
return false;
|
||||
}
|
||||
|
||||
return $verifier->verify($env['data'], $env['sig']);
|
||||
return $verifier->verify($this->signingText($env), $env['sig']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract envelope data from an XML document containing an <me:env> or <me:provenance> element.
|
||||
*
|
||||
* @param string XML source
|
||||
* @return mixed associative array of envelope data, or false on unrecognized input
|
||||
*
|
||||
* @fixme it might be easier to work with storing envelope data these in the object instead of passing arrays around
|
||||
* @fixme will spew errors to logs or output in case of XML parse errors
|
||||
* @fixme may give fatal errors if some elements are missing or invalid XML
|
||||
* @fixme calling DOMDocument::loadXML statically triggers warnings in strict mode
|
||||
*/
|
||||
public function parse($text)
|
||||
{
|
||||
$dom = DOMDocument::loadXML($text);
|
||||
return $this->fromDom($dom);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract envelope data from an XML document containing an <me:env> or <me:provenance> element.
|
||||
*
|
||||
* @param DOMDocument $dom
|
||||
* @return mixed associative array of envelope data, or false on unrecognized input
|
||||
*
|
||||
* @fixme it might be easier to work with storing envelope data these in the object instead of passing arrays around
|
||||
* @fixme may give fatal errors if some elements are missing
|
||||
*/
|
||||
public function fromDom($dom)
|
||||
{
|
||||
$env_element = $dom->getElementsByTagNameNS(MagicEnvelope::NS, 'env')->item(0);
|
||||
@@ -218,3 +307,24 @@ class MagicEnvelope
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Variant of MagicEnvelope using the earlier signature form listed in the MagicEnvelope
|
||||
* spec in early 2010; this was used in StatusNet up through 0.9.6, so for backwards compatiblity
|
||||
* we still need to accept and sometimes send this format.
|
||||
*/
|
||||
class MagicEnvelopeCompat extends MagicEnvelope {
|
||||
|
||||
/**
|
||||
* StatusNet through 0.9.6 used an earlier version of the MagicEnvelope spec
|
||||
* which used only the input data, without the additional fields, as the plaintext
|
||||
* for signing.
|
||||
*
|
||||
* @param array $env
|
||||
* @return string
|
||||
*/
|
||||
public function signingText($env) {
|
||||
return $env['data'];
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -38,10 +38,12 @@ class Salmon
|
||||
/**
|
||||
* Sign and post the given Atom entry as a Salmon message.
|
||||
*
|
||||
* @fixme pass through the actor for signing?
|
||||
* Side effects: may generate a keypair on-demand for the given user,
|
||||
* which can be very slow on some systems.
|
||||
*
|
||||
* @param string $endpoint_uri
|
||||
* @param string $xml
|
||||
* @param string $xml string representation of payload
|
||||
* @param Profile $actor local user profile whose keys to sign with
|
||||
* @return boolean success
|
||||
*/
|
||||
public function post($endpoint_uri, $xml, $actor)
|
||||
@@ -50,34 +52,65 @@ class Salmon
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$xml = $this->createMagicEnv($xml, $actor);
|
||||
} catch (Exception $e) {
|
||||
common_log(LOG_ERR, "Salmon unable to sign: " . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
foreach ($this->formatClasses() as $class) {
|
||||
try {
|
||||
$envelope = $this->createMagicEnv($xml, $actor, $class);
|
||||
} catch (Exception $e) {
|
||||
common_log(LOG_ERR, "Salmon unable to sign: " . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
$headers = array('Content-Type: application/magic-envelope+xml');
|
||||
|
||||
try {
|
||||
$client = new HTTPClient();
|
||||
$client->setBody($envelope);
|
||||
$response = $client->post($endpoint_uri, $headers);
|
||||
} catch (HTTP_Request2_Exception $e) {
|
||||
common_log(LOG_ERR, "Salmon ($class) post to $endpoint_uri failed: " . $e->getMessage());
|
||||
continue;
|
||||
}
|
||||
if ($response->getStatus() != 200) {
|
||||
common_log(LOG_ERR, "Salmon ($class) at $endpoint_uri returned status " .
|
||||
$response->getStatus() . ': ' . $response->getBody());
|
||||
continue;
|
||||
}
|
||||
|
||||
$headers = array('Content-Type: application/magic-envelope+xml');
|
||||
|
||||
try {
|
||||
$client = new HTTPClient();
|
||||
$client->setBody($xml);
|
||||
$response = $client->post($endpoint_uri, $headers);
|
||||
} catch (HTTP_Request2_Exception $e) {
|
||||
common_log(LOG_ERR, "Salmon post to $endpoint_uri failed: " . $e->getMessage());
|
||||
return false;
|
||||
// Success!
|
||||
return true;
|
||||
}
|
||||
if ($response->getStatus() != 200) {
|
||||
common_log(LOG_ERR, "Salmon at $endpoint_uri returned status " .
|
||||
$response->getStatus() . ': ' . $response->getBody());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public function createMagicEnv($text, $actor)
|
||||
/**
|
||||
* List the magic envelope signature class variants in the order we try them.
|
||||
* Multiples are needed for backwards-compat with StatusNet prior to 0.9.7,
|
||||
* which used a draft version of the magic envelope spec.
|
||||
*/
|
||||
protected function formatClasses() {
|
||||
return array('MagicEnvelope', 'MagicEnvelopeCompat');
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode the given string as a signed MagicEnvelope XML document,
|
||||
* using the keypair for the given local user profile.
|
||||
*
|
||||
* Side effects: will create and store a keypair on-demand if one
|
||||
* hasn't already been generated for this user. This can be very slow
|
||||
* on some systems.
|
||||
*
|
||||
* @param string $text XML fragment to sign, assumed to be Atom
|
||||
* @param Profile $actor Profile of a local user to use as signer
|
||||
* @param string $class to override the magic envelope signature version, pass a MagicEnvelope subclass here
|
||||
*
|
||||
* @return string XML string representation of magic envelope
|
||||
*
|
||||
* @throws Exception on bad profile input or key generation problems
|
||||
* @fixme if signing fails, this seems to return the original text without warning. Is there a reason for this?
|
||||
*/
|
||||
public function createMagicEnv($text, $actor, $class='MagicEnvelope')
|
||||
{
|
||||
$magic_env = new MagicEnvelope();
|
||||
$magic_env = new $class();
|
||||
|
||||
$user = User::staticGet('id', $actor->id);
|
||||
if ($user->id) {
|
||||
@@ -101,12 +134,32 @@ class Salmon
|
||||
return $magic_env->toXML($env);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given magic envelope is well-formed and correctly signed.
|
||||
* Needs to have network access to fetch public keys over the web.
|
||||
* Both current and back-compat signature formats will be checked.
|
||||
*
|
||||
* Side effects: exceptions and caching updates may occur during network
|
||||
* fetches.
|
||||
*
|
||||
* @param string $text XML fragment of magic envelope
|
||||
* @return boolean
|
||||
*
|
||||
* @throws Exception on bad profile input or key generation problems
|
||||
* @fixme could hit fatal errors or spew output on invalid XML
|
||||
*/
|
||||
public function verifyMagicEnv($text)
|
||||
{
|
||||
$magic_env = new MagicEnvelope();
|
||||
foreach ($this->formatClasses() as $class) {
|
||||
$magic_env = new $class();
|
||||
|
||||
$env = $magic_env->parse($text);
|
||||
$env = $magic_env->parse($text);
|
||||
|
||||
return $magic_env->verify($env);
|
||||
if ($magic_env->verify($env)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@@ -30,6 +30,7 @@ class SalmonAction extends Action
|
||||
{
|
||||
var $xml = null;
|
||||
var $activity = null;
|
||||
var $target = null;
|
||||
|
||||
function prepare($args)
|
||||
{
|
||||
@@ -82,7 +83,8 @@ class SalmonAction extends Action
|
||||
StatusNet::setApi(true); // Send smaller error pages
|
||||
|
||||
common_log(LOG_DEBUG, "Got a " . $this->activity->verb);
|
||||
if (Event::handle('StartHandleSalmon', array($this->activity))) {
|
||||
if (Event::handle('StartHandleSalmonTarget', array($this->activity, $this->target)) &&
|
||||
Event::handle('StartHandleSalmon', array($this->activity))) {
|
||||
switch ($this->activity->verb)
|
||||
{
|
||||
case ActivityVerb::POST:
|
||||
@@ -118,6 +120,7 @@ class SalmonAction extends Action
|
||||
throw new ClientException(_m("Unrecognized activity type."));
|
||||
}
|
||||
Event::handle('EndHandleSalmon', array($this->activity));
|
||||
Event::handle('EndHandleSalmonTarget', array($this->activity, $this->target));
|
||||
}
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -9,13 +9,13 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: StatusNet - OStatus\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2010-12-16 15:08+0000\n"
|
||||
"PO-Revision-Date: 2010-12-16 15:12:44+0000\n"
|
||||
"POT-Creation-Date: 2011-01-14 10:29+0000\n"
|
||||
"PO-Revision-Date: 2011-01-14 10:33:50+0000\n"
|
||||
"Language-Team: Breton <http://translatewiki.net/wiki/Portal:br>\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-POT-Import-Date: 2010-11-30 20:43:51+0000\n"
|
||||
"X-Generator: MediaWiki 1.18alpha (r78478); Translate extension (2010-09-17)\n"
|
||||
"X-POT-Import-Date: 2011-01-10 18:26:06+0000\n"
|
||||
"X-Generator: MediaWiki 1.18alpha (r80246); Translate extension (2010-09-17)\n"
|
||||
"X-Translation-Project: translatewiki.net at http://translatewiki.net\n"
|
||||
"X-Language-Code: br\n"
|
||||
"X-Message-Group: #out-statusnet-plugin-ostatus\n"
|
||||
@@ -23,94 +23,94 @@ msgstr ""
|
||||
|
||||
#. TRANS: Link description for link to subscribe to a remote user.
|
||||
#. TRANS: Link text for a user to subscribe to an OStatus user.
|
||||
#: OStatusPlugin.php:225 OStatusPlugin.php:935
|
||||
#: OStatusPlugin.php:223 OStatusPlugin.php:933
|
||||
msgid "Subscribe"
|
||||
msgstr "Koumanantiñ"
|
||||
|
||||
#. TRANS: Link description for link to join a remote group.
|
||||
#: OStatusPlugin.php:244 OStatusPlugin.php:653 actions/ostatussub.php:109
|
||||
#: OStatusPlugin.php:242 OStatusPlugin.php:651 actions/ostatussub.php:109
|
||||
msgid "Join"
|
||||
msgstr "Stagañ"
|
||||
|
||||
#. TRANSLATE: %s is a domain.
|
||||
#: OStatusPlugin.php:457
|
||||
#: OStatusPlugin.php:455
|
||||
#, php-format
|
||||
msgid "Sent from %s via OStatus"
|
||||
msgstr "Kaset adalek %s dre OStatus"
|
||||
|
||||
#. TRANS: Exception.
|
||||
#: OStatusPlugin.php:529
|
||||
#: OStatusPlugin.php:527
|
||||
msgid "Could not set up remote subscription."
|
||||
msgstr ""
|
||||
|
||||
#: OStatusPlugin.php:603
|
||||
#: OStatusPlugin.php:601
|
||||
msgid "Unfollow"
|
||||
msgstr "Chom hep heuliañ"
|
||||
|
||||
#. TRANS: Success message for unsubscribe from user attempt through OStatus.
|
||||
#. TRANS: %1$s is the unsubscriber's name, %2$s is the unsubscribed user's name.
|
||||
#: OStatusPlugin.php:606
|
||||
#: OStatusPlugin.php:604
|
||||
#, php-format
|
||||
msgid "%1$s stopped following %2$s."
|
||||
msgstr ""
|
||||
|
||||
#: OStatusPlugin.php:634
|
||||
#: OStatusPlugin.php:632
|
||||
msgid "Could not set up remote group membership."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Success message for subscribe to group attempt through OStatus.
|
||||
#. TRANS: %1$s is the member name, %2$s is the subscribed group's name.
|
||||
#: OStatusPlugin.php:656
|
||||
#: OStatusPlugin.php:654
|
||||
#, php-format
|
||||
msgid "%1$s has joined group %2$s."
|
||||
msgstr "%1$s a zo bet er strollad %2$s."
|
||||
|
||||
#. TRANS: Exception.
|
||||
#: OStatusPlugin.php:665
|
||||
#: OStatusPlugin.php:663
|
||||
msgid "Failed joining remote group."
|
||||
msgstr ""
|
||||
|
||||
#: OStatusPlugin.php:705
|
||||
#: OStatusPlugin.php:703
|
||||
msgid "Leave"
|
||||
msgstr "Kuitaat"
|
||||
|
||||
#. TRANS: Success message for unsubscribe from group attempt through OStatus.
|
||||
#. TRANS: %1$s is the member name, %2$s is the unsubscribed group's name.
|
||||
#: OStatusPlugin.php:708
|
||||
#: OStatusPlugin.php:706
|
||||
#, php-format
|
||||
msgid "%1$s has left group %2$s."
|
||||
msgstr ""
|
||||
|
||||
#: OStatusPlugin.php:783
|
||||
#: OStatusPlugin.php:781
|
||||
msgid "Disfavor"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Success message for remove a favorite notice through OStatus.
|
||||
#. TRANS: %1$s is the unfavoring user's name, %2$s is URI to the no longer favored notice.
|
||||
#: OStatusPlugin.php:786
|
||||
#: OStatusPlugin.php:784
|
||||
#, php-format
|
||||
msgid "%1$s marked notice %2$s as no longer a favorite."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Link text for link to remote subscribe.
|
||||
#: OStatusPlugin.php:862
|
||||
#: OStatusPlugin.php:860
|
||||
msgid "Remote"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Title for activity.
|
||||
#: OStatusPlugin.php:902
|
||||
#: OStatusPlugin.php:900
|
||||
msgid "Profile update"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Ping text for remote profile update through OStatus.
|
||||
#. TRANS: %s is user that updated their profile.
|
||||
#: OStatusPlugin.php:905
|
||||
#: OStatusPlugin.php:903
|
||||
#, php-format
|
||||
msgid "%s has updated their profile page."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Plugin description.
|
||||
#: OStatusPlugin.php:950
|
||||
#: OStatusPlugin.php:948
|
||||
msgid ""
|
||||
"Follow people across social networks that implement <a href=\"http://ostatus."
|
||||
"org/\">OStatus</a>."
|
||||
@@ -161,102 +161,102 @@ msgid "RSS feed without a channel."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: classes/Ostatus_profile.php:478
|
||||
#: classes/Ostatus_profile.php:479
|
||||
msgid "Can't handle that kind of post."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception. %s is a source URI.
|
||||
#: classes/Ostatus_profile.php:561
|
||||
#: classes/Ostatus_profile.php:537
|
||||
#, php-format
|
||||
msgid "No content for notice %s."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Shown when a notice is longer than supported and/or when attachments are present. At runtime
|
||||
#. TRANS: this will usually be replaced with localised text from StatusNet core messages.
|
||||
#: classes/Ostatus_profile.php:596
|
||||
#: classes/Ostatus_profile.php:572
|
||||
msgid "Show more"
|
||||
msgstr "Diskouez muioc'h"
|
||||
|
||||
#. TRANS: Exception. %s is a profile URL.
|
||||
#: classes/Ostatus_profile.php:789
|
||||
#: classes/Ostatus_profile.php:765
|
||||
#, php-format
|
||||
msgid "Could not reach profile page %s."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception. %s is a URL.
|
||||
#: classes/Ostatus_profile.php:847
|
||||
#: classes/Ostatus_profile.php:823
|
||||
#, php-format
|
||||
msgid "Could not find a feed URL for profile page %s."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Feed sub exception.
|
||||
#: classes/Ostatus_profile.php:985
|
||||
#: classes/Ostatus_profile.php:922
|
||||
msgid "Can't find enough profile information to make a feed."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Server exception. %s is a URL.
|
||||
#: classes/Ostatus_profile.php:1045
|
||||
#: classes/Ostatus_profile.php:986
|
||||
#, php-format
|
||||
msgid "Invalid avatar URL %s."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Server exception. %s is a URI.
|
||||
#: classes/Ostatus_profile.php:1056
|
||||
#: classes/Ostatus_profile.php:997
|
||||
#, php-format
|
||||
msgid "Tried to update avatar for unsaved remote profile %s."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Server exception. %s is a URL.
|
||||
#: classes/Ostatus_profile.php:1066
|
||||
#: classes/Ostatus_profile.php:1007
|
||||
#, php-format
|
||||
msgid "Unable to fetch avatar from %s."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception.
|
||||
#: classes/Ostatus_profile.php:1292
|
||||
#: classes/Ostatus_profile.php:1233
|
||||
msgid "Local user can't be referenced as remote."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception.
|
||||
#: classes/Ostatus_profile.php:1297
|
||||
#: classes/Ostatus_profile.php:1238
|
||||
msgid "Local group can't be referenced as remote."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Server exception.
|
||||
#: classes/Ostatus_profile.php:1349 classes/Ostatus_profile.php:1360
|
||||
#: classes/Ostatus_profile.php:1290 classes/Ostatus_profile.php:1301
|
||||
msgid "Can't save local profile."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Server exception.
|
||||
#: classes/Ostatus_profile.php:1368
|
||||
#: classes/Ostatus_profile.php:1309
|
||||
msgid "Can't save OStatus profile."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception.
|
||||
#: classes/Ostatus_profile.php:1632 classes/Ostatus_profile.php:1660
|
||||
#: classes/Ostatus_profile.php:1573 classes/Ostatus_profile.php:1601
|
||||
msgid "Not a valid webfinger address."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception. %s is a webfinger address.
|
||||
#: classes/Ostatus_profile.php:1742
|
||||
#: classes/Ostatus_profile.php:1683
|
||||
#, php-format
|
||||
msgid "Couldn't save profile for \"%s\"."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception. %s is a webfinger address.
|
||||
#: classes/Ostatus_profile.php:1761
|
||||
#: classes/Ostatus_profile.php:1702
|
||||
#, php-format
|
||||
msgid "Couldn't save ostatus_profile for \"%s\"."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception. %s is a webfinger address.
|
||||
#: classes/Ostatus_profile.php:1769
|
||||
#: classes/Ostatus_profile.php:1710
|
||||
#, php-format
|
||||
msgid "Couldn't find a valid profile for \"%s\"."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Server exception.
|
||||
#: classes/Ostatus_profile.php:1812
|
||||
#: classes/Ostatus_profile.php:1753
|
||||
msgid "Could not store HTML content of long post as file."
|
||||
msgstr ""
|
||||
|
||||
@@ -273,72 +273,72 @@ msgid "Callback returned status: %1$s. Body: %2$s"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client error. POST is a HTTP command. It should not be translated.
|
||||
#: lib/salmonaction.php:42
|
||||
#: lib/salmonaction.php:43
|
||||
msgid "This method requires a POST."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client error. Do not translate "application/magic-envelope+xml"
|
||||
#: lib/salmonaction.php:47
|
||||
#: lib/salmonaction.php:48
|
||||
msgid "Salmon requires \"application/magic-envelope+xml\"."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client error.
|
||||
#: lib/salmonaction.php:57
|
||||
#: lib/salmonaction.php:58
|
||||
msgid "Salmon signature verification failed."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client error.
|
||||
#: lib/salmonaction.php:69
|
||||
#: lib/salmonaction.php:70
|
||||
msgid "Salmon post must be an Atom entry."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: lib/salmonaction.php:118
|
||||
#: lib/salmonaction.php:120
|
||||
msgid "Unrecognized activity type."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: lib/salmonaction.php:127
|
||||
#: lib/salmonaction.php:130
|
||||
msgid "This target doesn't understand posts."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: lib/salmonaction.php:133
|
||||
#: lib/salmonaction.php:136
|
||||
msgid "This target doesn't understand follows."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: lib/salmonaction.php:139
|
||||
#: lib/salmonaction.php:142
|
||||
msgid "This target doesn't understand unfollows."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: lib/salmonaction.php:145
|
||||
#: lib/salmonaction.php:148
|
||||
msgid "This target doesn't understand favorites."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: lib/salmonaction.php:151
|
||||
#: lib/salmonaction.php:154
|
||||
msgid "This target doesn't understand unfavorites."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: lib/salmonaction.php:157
|
||||
#: lib/salmonaction.php:160
|
||||
msgid "This target doesn't understand share events."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: lib/salmonaction.php:163
|
||||
#: lib/salmonaction.php:166
|
||||
msgid "This target doesn't understand joins."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: lib/salmonaction.php:169
|
||||
#: lib/salmonaction.php:172
|
||||
msgid "This target doesn't understand leave events."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception.
|
||||
#: lib/salmonaction.php:197
|
||||
#: lib/salmonaction.php:200
|
||||
msgid "Received a salmon slap from unidentified actor."
|
||||
msgstr ""
|
||||
|
||||
@@ -428,38 +428,38 @@ msgid "No ID."
|
||||
msgstr "ID ebet"
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: actions/usersalmon.php:81
|
||||
#: actions/usersalmon.php:83
|
||||
msgid "In reply to unknown notice."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: actions/usersalmon.php:86
|
||||
#: actions/usersalmon.php:88
|
||||
msgid "In reply to a notice not by this user and not mentioning this user."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: actions/usersalmon.php:163
|
||||
#: actions/usersalmon.php:165
|
||||
msgid "Could not save new favorite."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: actions/usersalmon.php:195
|
||||
#: actions/usersalmon.php:197
|
||||
msgid "Can't favorite/unfavorite without an object."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: actions/usersalmon.php:207
|
||||
#: actions/usersalmon.php:209
|
||||
msgid "Can't handle that kind of object for liking/faving."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception. %s is an object ID.
|
||||
#: actions/usersalmon.php:214
|
||||
#: actions/usersalmon.php:216
|
||||
#, php-format
|
||||
msgid "Notice with ID %s unknown."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception. %1$s is a notice ID, %2$s is a user ID.
|
||||
#: actions/usersalmon.php:219
|
||||
#: actions/usersalmon.php:221
|
||||
#, php-format
|
||||
msgid "Notice with ID %1$s not posted by %2$s."
|
||||
msgstr ""
|
||||
@@ -482,7 +482,7 @@ msgstr "Kenderc'hel"
|
||||
|
||||
#: actions/ostatusgroup.php:105
|
||||
msgid "You are already a member of this group."
|
||||
msgstr ""
|
||||
msgstr "Un ezel eus ar strollad-mañ oc'h dija."
|
||||
|
||||
#. TRANS: OStatus remote group subscription dialog error.
|
||||
#: actions/ostatusgroup.php:140
|
||||
@@ -517,36 +517,36 @@ msgid "No such group."
|
||||
msgstr "N'eus ket eus ar strollad-se."
|
||||
|
||||
#. TRANS: Client error.
|
||||
#: actions/groupsalmon.php:53
|
||||
#: actions/groupsalmon.php:56
|
||||
msgid "Can't accept remote posts for a remote group."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client error.
|
||||
#: actions/groupsalmon.php:127
|
||||
#: actions/groupsalmon.php:130
|
||||
msgid "Can't read profile to set up group membership."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client error.
|
||||
#: actions/groupsalmon.php:131 actions/groupsalmon.php:174
|
||||
#: actions/groupsalmon.php:134 actions/groupsalmon.php:177
|
||||
msgid "Groups can't join groups."
|
||||
msgstr ""
|
||||
msgstr "Ne c'hell ket strolladoù mont e strolladoù."
|
||||
|
||||
#: actions/groupsalmon.php:144
|
||||
#: actions/groupsalmon.php:147
|
||||
msgid "You have been blocked from that group by the admin."
|
||||
msgstr ""
|
||||
msgstr "Stanket oc'h bet eus ar strollad-mañ gant ur merour."
|
||||
|
||||
#. TRANS: Server error. %1$s is a profile URI, %2$s is a group nickname.
|
||||
#: actions/groupsalmon.php:159
|
||||
#: actions/groupsalmon.php:162
|
||||
#, php-format
|
||||
msgid "Could not join remote user %1$s to group %2$s."
|
||||
msgstr ""
|
||||
msgstr "Dibosupl eo distagañ an implijer %1$s deus ar strollad %2$s."
|
||||
|
||||
#: actions/groupsalmon.php:171
|
||||
#: actions/groupsalmon.php:174
|
||||
msgid "Can't read profile to cancel group membership."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Server error. %1$s is a profile URI, %2$s is a group nickname.
|
||||
#: actions/groupsalmon.php:188
|
||||
#: actions/groupsalmon.php:191
|
||||
#, php-format
|
||||
msgid "Could not remove remote user %1$s from group %2$s."
|
||||
msgstr ""
|
||||
|
637
plugins/OStatus/locale/de/LC_MESSAGES/OStatus.po
Normal file
637
plugins/OStatus/locale/de/LC_MESSAGES/OStatus.po
Normal file
@@ -0,0 +1,637 @@
|
||||
# Translation of StatusNet - OStatus to German (Deutsch)
|
||||
# Exported from translatewiki.net
|
||||
#
|
||||
# Author: Fujnky
|
||||
# Author: Michael
|
||||
# --
|
||||
# This file is distributed under the same license as the StatusNet package.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: StatusNet - OStatus\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2011-03-06 02:34+0100\n"
|
||||
"PO-Revision-Date: 2011-03-06 01:37:59+0000\n"
|
||||
"Language-Team: German <http://translatewiki.net/wiki/Portal:de>\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-POT-Import-Date: 2011-03-03 17:49:39+0000\n"
|
||||
"X-Generator: MediaWiki 1.18alpha (r83348); Translate extension (2011-03-04)\n"
|
||||
"X-Translation-Project: translatewiki.net at http://translatewiki.net\n"
|
||||
"X-Language-Code: de\n"
|
||||
"X-Message-Group: #out-statusnet-plugin-ostatus\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
msgid "Feeds"
|
||||
msgstr "Feeds"
|
||||
|
||||
#. TRANS: Link description for link to subscribe to a remote user.
|
||||
#. TRANS: Link text for a user to subscribe to an OStatus user.
|
||||
msgid "Subscribe"
|
||||
msgstr "Abonnieren"
|
||||
|
||||
#. TRANS: Link description for link to join a remote group.
|
||||
msgid "Join"
|
||||
msgstr "Beitreten"
|
||||
|
||||
#. TRANSLATE: %s is a domain.
|
||||
#, php-format
|
||||
msgid "Sent from %s via OStatus"
|
||||
msgstr "Gesendet von %s über OStatus"
|
||||
|
||||
#. TRANS: Exception.
|
||||
msgid "Could not set up remote subscription."
|
||||
msgstr "Konnte Remote-Abonnement nicht einrichten."
|
||||
|
||||
msgid "Unfollow"
|
||||
msgstr "Nicht mehr beachten"
|
||||
|
||||
#. TRANS: Success message for unsubscribe from user attempt through OStatus.
|
||||
#. TRANS: %1$s is the unsubscriber's name, %2$s is the unsubscribed user's name.
|
||||
#, php-format
|
||||
msgid "%1$s stopped following %2$s."
|
||||
msgstr "%1$s folgt %2$s nicht mehr."
|
||||
|
||||
msgid "Could not set up remote group membership."
|
||||
msgstr "Konnte Remotegruppenmitgliedschaft nicht einrichten."
|
||||
|
||||
#. TRANS: Success message for subscribe to group attempt through OStatus.
|
||||
#. TRANS: %1$s is the member name, %2$s is the subscribed group's name.
|
||||
#, php-format
|
||||
msgid "%1$s has joined group %2$s."
|
||||
msgstr "%1$s ist der Gruppe %2$s beigetreten"
|
||||
|
||||
#. TRANS: Exception.
|
||||
msgid "Failed joining remote group."
|
||||
msgstr "Fehler beim Beitreten der Remotegruppe."
|
||||
|
||||
msgid "Leave"
|
||||
msgstr "Verlassen"
|
||||
|
||||
#. TRANS: Success message for unsubscribe from group attempt through OStatus.
|
||||
#. TRANS: %1$s is the member name, %2$s is the unsubscribed group's name.
|
||||
#, php-format
|
||||
msgid "%1$s has left group %2$s."
|
||||
msgstr "%1$s hat die Gruppe %2$s verlassen"
|
||||
|
||||
msgid "Disfavor"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Success message for remove a favorite notice through OStatus.
|
||||
#. TRANS: %1$s is the unfavoring user's name, %2$s is URI to the no longer favored notice.
|
||||
#, php-format
|
||||
msgid "%1$s marked notice %2$s as no longer a favorite."
|
||||
msgstr "%1$s markierte Nachricht %2$s nicht mehr als Favorit."
|
||||
|
||||
#. TRANS: Link text for link to remote subscribe.
|
||||
msgid "Remote"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Title for activity.
|
||||
msgid "Profile update"
|
||||
msgstr "Profil aktualisieren"
|
||||
|
||||
#. TRANS: Ping text for remote profile update through OStatus.
|
||||
#. TRANS: %s is user that updated their profile.
|
||||
#, php-format
|
||||
msgid "%s has updated their profile page."
|
||||
msgstr "%s hat die Profil-Seite aktualisiert."
|
||||
|
||||
#. TRANS: Plugin description.
|
||||
msgid ""
|
||||
"Follow people across social networks that implement <a href=\"http://ostatus."
|
||||
"org/\">OStatus</a>."
|
||||
msgstr ""
|
||||
"Folge Leuten quer durch die sozialen Netzwerke, die <a href=\"http://ostatus."
|
||||
"org/\">OStatus</a> implementieren."
|
||||
|
||||
#. TRANS: Client exception.
|
||||
msgid "Publishing outside feeds not supported."
|
||||
msgstr "Veröffentlichung von äußeren Feeds nicht unterstützt."
|
||||
|
||||
#. TRANS: Client exception. %s is a mode.
|
||||
#, php-format
|
||||
msgid "Unrecognized mode \"%s\"."
|
||||
msgstr "Unbekannter Modus \"%s\"."
|
||||
|
||||
#. TRANS: Client exception. %s is a topic.
|
||||
#, php-format
|
||||
msgid ""
|
||||
"Unsupported hub.topic %s this hub only serves local user and group Atom "
|
||||
"feeds."
|
||||
msgstr ""
|
||||
"Nicht unterstütztes hub.topic %s. Dieser Hub stellt nur Atom-Feeds lokaler "
|
||||
"Benutzer und Gruppen zur verfügung."
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#, php-format
|
||||
msgid "Invalid hub.verify \"%s\". It must be sync or async."
|
||||
msgstr "Ungültiger hub.verify „%s“. Es muss sync oder async sein."
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#, php-format
|
||||
msgid "Invalid hub.lease \"%s\". It must be empty or positive integer."
|
||||
msgstr ""
|
||||
"Ungültiger hub.lease „%s“. Es muss eine leere oder positive Ganzzahl sein."
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#, php-format
|
||||
msgid "Invalid hub.secret \"%s\". It must be under 200 bytes."
|
||||
msgstr "Ungültiges hub.secret „%s“. Es muss kleiner als 200 Bytes sein."
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#, php-format
|
||||
msgid "Invalid hub.topic \"%s\". User doesn't exist."
|
||||
msgstr "Ungültiges hub.topic „%s“. Benutzer existiert nicht."
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#, php-format
|
||||
msgid "Invalid hub.topic \"%s\". Group doesn't exist."
|
||||
msgstr "Ungültiges hub.topic „%s“. Gruppe existiert nicht."
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#. TRANS: %1$s is this argument to the method this exception occurs in, %2$s is a URL.
|
||||
#, php-format
|
||||
msgid "Invalid URL passed for %1$s: \"%2$s\""
|
||||
msgstr "Ungültiger URL für %1$s übergeben: „%2$s“"
|
||||
|
||||
msgid "Empty or invalid feed id."
|
||||
msgstr "Leere oder ungültige Feed-ID."
|
||||
|
||||
#. TRANS: Server exception. %s is a feed ID.
|
||||
#, php-format
|
||||
msgid "Unknown PuSH feed id %s"
|
||||
msgstr "Unbekannte PuSH Feed-ID %s"
|
||||
|
||||
#. TRANS: Client exception. %s is an invalid feed name.
|
||||
#, php-format
|
||||
msgid "Bad hub.topic feed \"%s\"."
|
||||
msgstr "Ungültiger hub.topic-Feed „%s“."
|
||||
|
||||
#. TRANS: Client exception. %1$s the invalid token, %2$s is the topic for which the invalid token was given.
|
||||
#, php-format
|
||||
msgid "Bad hub.verify_token %1$s for %2$s."
|
||||
msgstr "Ungültiger hub.verify_token %1$s für %2$s."
|
||||
|
||||
#. TRANS: Client exception. %s is an invalid topic.
|
||||
#, php-format
|
||||
msgid "Unexpected subscribe request for %s."
|
||||
msgstr "Unerwartete Deabonnement-Anfrage für %s."
|
||||
|
||||
#. TRANS: Client exception. %s is an invalid topic.
|
||||
#, php-format
|
||||
msgid "Unexpected unsubscribe request for %s."
|
||||
msgstr "Unerwartete Deabonnement-Anfrage für %s."
|
||||
|
||||
msgid "No such user."
|
||||
msgstr "Unbekannter Benutzer."
|
||||
|
||||
#. TRANS: Field label for a field that takes an OStatus user address.
|
||||
msgid "Subscribe to"
|
||||
msgstr "Abonniere"
|
||||
|
||||
#. TRANS: Tooltip for field label "Subscribe to".
|
||||
msgid ""
|
||||
"OStatus user's address, like nickname@example.com or http://example.net/"
|
||||
"nickname"
|
||||
msgstr ""
|
||||
"Adresse des OStatus-Benutzers, wie nickname@example.com oder http://example."
|
||||
"net/nickname"
|
||||
|
||||
#. TRANS: Button text.
|
||||
msgctxt "BUTTON"
|
||||
msgid "Continue"
|
||||
msgstr "Weiter"
|
||||
|
||||
#. TRANS: Button text.
|
||||
#. TRANS: Tooltip for button "Join".
|
||||
msgctxt "BUTTON"
|
||||
msgid "Join this group"
|
||||
msgstr "Dieser Gruppe beitreten"
|
||||
|
||||
#. TRANS: Button text.
|
||||
msgctxt "BUTTON"
|
||||
msgid "Confirm"
|
||||
msgstr "Bestätigen"
|
||||
|
||||
#. TRANS: Tooltip for button "Confirm".
|
||||
msgid "Subscribe to this user"
|
||||
msgstr "Abonniere diesen Benutzer"
|
||||
|
||||
msgid "You are already subscribed to this user."
|
||||
msgstr "Du hast diesen Benutzer bereits abonniert:"
|
||||
|
||||
#. TRANS: Error text.
|
||||
msgid ""
|
||||
"Sorry, we could not reach that address. Please make sure that the OStatus "
|
||||
"address is like nickname@example.com or http://example.net/nickname."
|
||||
msgstr ""
|
||||
"Entschuldigung, wir konnte diese Adresse nicht erreichen. Bitte überprüfe, "
|
||||
"ob die OStatus-Adresse gültig ist. Beispiele: nickname@example.com oder "
|
||||
"http://example.net/nickname."
|
||||
|
||||
#. TRANS: Error text.
|
||||
msgid ""
|
||||
"Sorry, we could not reach that feed. Please try that OStatus address again "
|
||||
"later."
|
||||
msgstr ""
|
||||
"Entschuldigung, wir konnten diesen Feed nicht erreichen. Bitte versuche "
|
||||
"diese OStatus-Adresse später noch einmal."
|
||||
|
||||
#. TRANS: OStatus remote subscription dialog error.
|
||||
msgid "Already subscribed!"
|
||||
msgstr "Bereits abonniert!"
|
||||
|
||||
#. TRANS: OStatus remote subscription dialog error.
|
||||
msgid "Remote subscription failed!"
|
||||
msgstr "Remoteabonnement fehlgeschlagen!"
|
||||
|
||||
msgid "There was a problem with your session token. Try again, please."
|
||||
msgstr "Es gab ein Problem mit deinem Sitzungstoken. Bitte versuche es erneut."
|
||||
|
||||
#. TRANS: Form title.
|
||||
msgid "Subscribe to user"
|
||||
msgstr "Abonniere diesen Benutzer"
|
||||
|
||||
#. TRANS: Page title for OStatus remote subscription form
|
||||
msgid "Confirm"
|
||||
msgstr "Bestätigen"
|
||||
|
||||
#. TRANS: Instructions.
|
||||
msgid ""
|
||||
"You can subscribe to users from other supported sites. Paste their address "
|
||||
"or profile URI below:"
|
||||
msgstr ""
|
||||
"Du kannst Benutzer von anderen unterstützten Websites abonnieren. Füge ihre "
|
||||
"Adresse oder Profil-URI unten ein:"
|
||||
|
||||
#. TRANS: Field label.
|
||||
msgid "Join group"
|
||||
msgstr "Gruppe beitreten"
|
||||
|
||||
#. TRANS: Tooltip for field label "Join group".
|
||||
msgid "OStatus group's address, like http://example.net/group/nickname."
|
||||
msgstr ""
|
||||
"OStatus-Adresse der Gruppe. Beispiel: http://example.net/group/nickname."
|
||||
|
||||
msgid "You are already a member of this group."
|
||||
msgstr "Du bist bereits Mitglied dieser Gruppe."
|
||||
|
||||
#. TRANS: OStatus remote group subscription dialog error.
|
||||
msgid "Already a member!"
|
||||
msgstr "Bereits Mitglied!"
|
||||
|
||||
#. TRANS: OStatus remote group subscription dialog error.
|
||||
msgid "Remote group join failed!"
|
||||
msgstr "Beitritt in Remote-Gruppe fehlgeschlagen!"
|
||||
|
||||
#. TRANS: OStatus remote group subscription dialog error.
|
||||
msgid "Remote group join aborted!"
|
||||
msgstr "Beitritt in Remote-Gruppe abgebrochen!"
|
||||
|
||||
#. TRANS: Page title for OStatus remote group join form
|
||||
msgid "Confirm joining remote group"
|
||||
msgstr "Bestätige das Beitreten einer Remotegruppe"
|
||||
|
||||
#. TRANS: Instructions.
|
||||
msgid ""
|
||||
"You can subscribe to groups from other supported sites. Paste the group's "
|
||||
"profile URI below:"
|
||||
msgstr ""
|
||||
"Du kannst Gruppen von anderen unterstützten Websites abonnieren. Füge die "
|
||||
"URI der Gruppe unten ein:"
|
||||
|
||||
#. TRANS: Client error.
|
||||
msgid "No ID."
|
||||
msgstr "Keine ID"
|
||||
|
||||
#. TRANS: Client exception.
|
||||
msgid "In reply to unknown notice."
|
||||
msgstr "In der Antwort auf unbekannte Nachricht."
|
||||
|
||||
#. TRANS: Client exception.
|
||||
msgid "In reply to a notice not by this user and not mentioning this user."
|
||||
msgstr ""
|
||||
"In einer Antowrt auf eine Nachricht, die nicht von diesem Benutzer stammt "
|
||||
"und diesen Benutzer nicht erwähnt."
|
||||
|
||||
#. TRANS: Client exception.
|
||||
msgid "Could not save new favorite."
|
||||
msgstr "Neuer Favorit konnte nicht gespeichert werden."
|
||||
|
||||
#. TRANS: Client exception.
|
||||
msgid "Can't favorite/unfavorite without an object."
|
||||
msgstr "Kann nicht ohne Objekt (ent)favorisieren."
|
||||
|
||||
#. TRANS: Client exception.
|
||||
msgid "Can't handle that kind of object for liking/faving."
|
||||
msgstr "Kann diese Art von Objekt nicht für mögen/favorisieren verarbeiten."
|
||||
|
||||
#. TRANS: Client exception. %s is an object ID.
|
||||
#, php-format
|
||||
msgid "Notice with ID %s unknown."
|
||||
msgstr "Nachricht mit ID %s unbekannt."
|
||||
|
||||
#. TRANS: Client exception. %1$s is a notice ID, %2$s is a user ID.
|
||||
#, php-format
|
||||
msgid "Notice with ID %1$s not posted by %2$s."
|
||||
msgstr "Nachricht mit ID %1$s wurde nicht von %2$s geschrieben."
|
||||
|
||||
#. TRANS: Client error.
|
||||
msgid "No such group."
|
||||
msgstr "Keine derartige Gruppe."
|
||||
|
||||
#. TRANS: Client error.
|
||||
msgid "Can't accept remote posts for a remote group."
|
||||
msgstr "Kann Remoteposts für Remotegruppen nicht akzeptieren."
|
||||
|
||||
#. TRANS: Client error.
|
||||
msgid "Can't read profile to set up group membership."
|
||||
msgstr "Kann Profil nicht lesen, um die Gruppenmitgliedschaft einzurichten."
|
||||
|
||||
#. TRANS: Client error.
|
||||
msgid "Groups can't join groups."
|
||||
msgstr "Gruppen können Remotegruppen nicht beitreten."
|
||||
|
||||
msgid "You have been blocked from that group by the admin."
|
||||
msgstr "Der Admin dieser Gruppe hat dich blockiert."
|
||||
|
||||
#. TRANS: Server error. %1$s is a profile URI, %2$s is a group nickname.
|
||||
#, php-format
|
||||
msgid "Could not join remote user %1$s to group %2$s."
|
||||
msgstr "Konnte Remotebenutzer %1$s nicht der Gruppe %2$s hinzufügen."
|
||||
|
||||
msgid "Can't read profile to cancel group membership."
|
||||
msgstr "Kann Profil nicht lesen, um die Gruppenmitgliedschaft zu kündigen."
|
||||
|
||||
#. TRANS: Server error. %1$s is a profile URI, %2$s is a group nickname.
|
||||
#, php-format
|
||||
msgid "Could not remove remote user %1$s from group %2$s."
|
||||
msgstr "Konnte Remotebenutzer %1$s nicht aus der Gruppe %2$s entfernen."
|
||||
|
||||
#. TRANS: Client error.
|
||||
msgid "You can use the local subscription!"
|
||||
msgstr "Du kannst ein lokales Abonnement erstellen!"
|
||||
|
||||
#. TRANS: Form legend.
|
||||
#, php-format
|
||||
msgid "Join group %s"
|
||||
msgstr "Gruppe %s beitreten"
|
||||
|
||||
#. TRANS: Button text.
|
||||
msgctxt "BUTTON"
|
||||
msgid "Join"
|
||||
msgstr "Beitreten"
|
||||
|
||||
#. TRANS: Form legend.
|
||||
#, php-format
|
||||
msgid "Subscribe to %s"
|
||||
msgstr "Abonniere %s"
|
||||
|
||||
#. TRANS: Button text.
|
||||
msgctxt "BUTTON"
|
||||
msgid "Subscribe"
|
||||
msgstr "Abonnieren"
|
||||
|
||||
#. TRANS: Field label.
|
||||
msgid "Group nickname"
|
||||
msgstr "Gruppe-Nickname"
|
||||
|
||||
msgid "Nickname of the group you want to join."
|
||||
msgstr "Spitzname der Gruppe, der Sie beitreten möchten."
|
||||
|
||||
#. TRANS: Field label.
|
||||
msgid "User nickname"
|
||||
msgstr "Benutzername"
|
||||
|
||||
msgid "Nickname of the user you want to follow."
|
||||
msgstr "Name des Benutzers, dem du folgen möchtest"
|
||||
|
||||
#. TRANS: Field label.
|
||||
msgid "Profile Account"
|
||||
msgstr "Profil-Konto"
|
||||
|
||||
#. TRANS: Tooltip for field label "Profile Account".
|
||||
msgid "Your account id (e.g. user@identi.ca)."
|
||||
msgstr "Deine Konto-ID (z.B. user@identi.ca)."
|
||||
|
||||
#. TRANS: Client error.
|
||||
msgid "Must provide a remote profile."
|
||||
msgstr "Du musst ein Remoteprofil angeben."
|
||||
|
||||
#. TRANS: Client error.
|
||||
msgid "Couldn't look up OStatus account profile."
|
||||
msgstr "Konnte OStatus-Konto-Profil nicht nachschauen."
|
||||
|
||||
#. TRANS: Client error.
|
||||
msgid "Couldn't confirm remote profile address."
|
||||
msgstr "Konnte Remoteprofiladresse nicht bestätigen."
|
||||
|
||||
#. TRANS: Page title.
|
||||
msgid "OStatus Connect"
|
||||
msgstr "OStatus-Verbindung"
|
||||
|
||||
msgid "Attempting to start PuSH subscription for feed with no hub."
|
||||
msgstr ""
|
||||
"Es wird versucht, ein PuSH-Abonnemont für einen Feed ohne Hub zu starten."
|
||||
|
||||
msgid "Attempting to end PuSH subscription for feed with no hub."
|
||||
msgstr ""
|
||||
"Es wird versucht, ein PuSH-Abonnemont für einen Feed ohne Hub zu beenden."
|
||||
|
||||
#. TRANS: Server exception. %s is a URI.
|
||||
#, php-format
|
||||
msgid "Invalid ostatus_profile state: both group and profile IDs set for %s."
|
||||
msgstr ""
|
||||
"Ungültiger ostatus_profile-Zustand: Sowohl Gruppen- als auch Profil-ID für %"
|
||||
"s gesetzt."
|
||||
|
||||
#. TRANS: Server exception. %s is a URI.
|
||||
#, php-format
|
||||
msgid "Invalid ostatus_profile state: both group and profile IDs empty for %s."
|
||||
msgstr ""
|
||||
"Ungültiger ostatus_profile-Zustand: Sowohl Gruppen- als auch Profil-ID für %"
|
||||
"s sind leer."
|
||||
|
||||
#. TRANS: Server exception.
|
||||
#. TRANS: %1$s is the method name the exception occured in, %2$s is the actor type.
|
||||
#, php-format
|
||||
msgid "Invalid actor passed to %1$s: %2$s."
|
||||
msgstr "Ungültiger actor an %1$s übergeben: %2$s."
|
||||
|
||||
#. TRANS: Server exception.
|
||||
msgid ""
|
||||
"Invalid type passed to Ostatus_profile::notify. It must be XML string or "
|
||||
"Activity entry."
|
||||
msgstr ""
|
||||
"Ungültiger Typ an Ostatus_profile::notify übergeben. Es muss ein XML-String "
|
||||
"oder ein Activity-Eintrag sein."
|
||||
|
||||
#. TRANS: Exception.
|
||||
msgid "Unknown feed format."
|
||||
msgstr "Unbekanntes Feed-Format."
|
||||
|
||||
#. TRANS: Exception.
|
||||
msgid "RSS feed without a channel."
|
||||
msgstr "RSS-Feed ohne einen Kanal."
|
||||
|
||||
#. TRANS: Client exception.
|
||||
msgid "Can't handle that kind of post."
|
||||
msgstr "Kann diese Art von Post nicht verarbeiten."
|
||||
|
||||
#. TRANS: Client exception. %s is a source URI.
|
||||
#, php-format
|
||||
msgid "No content for notice %s."
|
||||
msgstr "Kein Inhalt für Nachricht %s."
|
||||
|
||||
#. TRANS: Shown when a notice is longer than supported and/or when attachments are present. At runtime
|
||||
#. TRANS: this will usually be replaced with localised text from StatusNet core messages.
|
||||
msgid "Show more"
|
||||
msgstr "Mehr anzeigen"
|
||||
|
||||
#. TRANS: Exception. %s is a profile URL.
|
||||
#, php-format
|
||||
msgid "Could not reach profile page %s."
|
||||
msgstr "Konnte Profilseite %s nicht erreichen."
|
||||
|
||||
#. TRANS: Exception. %s is a URL.
|
||||
#, php-format
|
||||
msgid "Could not find a feed URL for profile page %s."
|
||||
msgstr "Konnte keinen Feed-URL für die Profilseite %s finden."
|
||||
|
||||
#. TRANS: Feed sub exception.
|
||||
msgid "Can't find enough profile information to make a feed."
|
||||
msgstr ""
|
||||
"Kann nicht genug Profilinformationen finden, um einen Feed zu erstellen."
|
||||
|
||||
#. TRANS: Server exception. %s is a URL.
|
||||
#, php-format
|
||||
msgid "Invalid avatar URL %s."
|
||||
msgstr "Ungültiger Avatar-URL %s."
|
||||
|
||||
#. TRANS: Server exception. %s is a URI.
|
||||
#, php-format
|
||||
msgid "Tried to update avatar for unsaved remote profile %s."
|
||||
msgstr ""
|
||||
"Versuchte den Avatar für ein ungespeichertes Remoteprofil %s zu "
|
||||
"aktualisieren."
|
||||
|
||||
#. TRANS: Server exception. %s is a URL.
|
||||
#, php-format
|
||||
msgid "Unable to fetch avatar from %s."
|
||||
msgstr "Kann den Avatar von %s nicht abrufen."
|
||||
|
||||
#. TRANS: Exception.
|
||||
msgid "Local user can't be referenced as remote."
|
||||
msgstr "Lokaler Benutzer kann nicht als remote verwiesen werden."
|
||||
|
||||
#. TRANS: Exception.
|
||||
msgid "Local group can't be referenced as remote."
|
||||
msgstr "Lokale Gruppe kann nicht als remote verwiesen werden."
|
||||
|
||||
#. TRANS: Server exception.
|
||||
msgid "Can't save local profile."
|
||||
msgstr "Lokales Profil kann nicht gespeichert werden."
|
||||
|
||||
#. TRANS: Server exception.
|
||||
msgid "Can't save OStatus profile."
|
||||
msgstr "OStatus-Profil kann nicht gespeichert werden."
|
||||
|
||||
#. TRANS: Exception.
|
||||
msgid "Not a valid webfinger address."
|
||||
msgstr "Ungültige Webfinger-Adresse."
|
||||
|
||||
#. TRANS: Exception. %s is a webfinger address.
|
||||
#, php-format
|
||||
msgid "Couldn't save profile for \"%s\"."
|
||||
msgstr "Profil für „%s“ konnte nicht gespeichert werden."
|
||||
|
||||
#. TRANS: Exception. %s is a webfinger address.
|
||||
#, php-format
|
||||
msgid "Couldn't save ostatus_profile for \"%s\"."
|
||||
msgstr "Ostatus_profile für „%s“ konnte nicht gespeichert werden."
|
||||
|
||||
#. TRANS: Exception. %s is a webfinger address.
|
||||
#, php-format
|
||||
msgid "Couldn't find a valid profile for \"%s\"."
|
||||
msgstr "Es konnte kein gültiges Profil für „%s“ gefunden werden."
|
||||
|
||||
#. TRANS: Server exception.
|
||||
msgid "Could not store HTML content of long post as file."
|
||||
msgstr ""
|
||||
"HTML-Inhalt eines langen Posts konnte nicht als Datei nicht gespeichert "
|
||||
"werden."
|
||||
|
||||
#. TRANS: Client exception. %s is a HTTP status code.
|
||||
#, php-format
|
||||
msgid "Hub subscriber verification returned HTTP %s."
|
||||
msgstr "Hub-Abonnenten-Überprüfung gab HTTP %s zurück."
|
||||
|
||||
#. TRANS: Exception. %1$s is a response status code, %2$s is the body of the response.
|
||||
#, php-format
|
||||
msgid "Callback returned status: %1$s. Body: %2$s"
|
||||
msgstr "Der Aufruf gab folgenden Status zurück: %1$s. Body: %2$s"
|
||||
|
||||
#. TRANS: Exception.
|
||||
msgid "Unable to locate signer public key."
|
||||
msgstr "Konnte den öffentlichen Schlüssel des Unterzeichners nicht finden."
|
||||
|
||||
#. TRANS: Exception.
|
||||
msgid "Salmon invalid actor for signing."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client error. POST is a HTTP command. It should not be translated.
|
||||
msgid "This method requires a POST."
|
||||
msgstr "Diese Methode benötigt ein POST."
|
||||
|
||||
#. TRANS: Client error. Do not translate "application/magic-envelope+xml"
|
||||
msgid "Salmon requires \"application/magic-envelope+xml\"."
|
||||
msgstr "Salmon erfordert „application/magic-envelope+xml“."
|
||||
|
||||
#. TRANS: Client error.
|
||||
msgid "Salmon signature verification failed."
|
||||
msgstr "Salmon-Signaturpfüung fehlgeschlagen."
|
||||
|
||||
#. TRANS: Client error.
|
||||
msgid "Salmon post must be an Atom entry."
|
||||
msgstr "Salmon-Post muss ein Atom-Eintrag sein."
|
||||
|
||||
#. TRANS: Client exception.
|
||||
msgid "Unrecognized activity type."
|
||||
msgstr "Unbekannter Aktivitätstyp."
|
||||
|
||||
#. TRANS: Client exception.
|
||||
msgid "This target doesn't understand posts."
|
||||
msgstr "Dieses Ziel versteht keine Posts."
|
||||
|
||||
#. TRANS: Client exception.
|
||||
msgid "This target doesn't understand follows."
|
||||
msgstr "Dieses Ziel versteht keine Follows."
|
||||
|
||||
#. TRANS: Client exception.
|
||||
msgid "This target doesn't understand unfollows."
|
||||
msgstr "Dieses Ziel versteht keine Unfollows."
|
||||
|
||||
#. TRANS: Client exception.
|
||||
msgid "This target doesn't understand favorites."
|
||||
msgstr "Dieses Ziel versteht keine Favoriten."
|
||||
|
||||
#. TRANS: Client exception.
|
||||
msgid "This target doesn't understand unfavorites."
|
||||
msgstr "Dieses Ziel versteht keine Unfavorites."
|
||||
|
||||
#. TRANS: Client exception.
|
||||
msgid "This target doesn't understand share events."
|
||||
msgstr "Dieses Ziel versteht das Teilen von Events nicht."
|
||||
|
||||
#. TRANS: Client exception.
|
||||
msgid "This target doesn't understand joins."
|
||||
msgstr "Dieses Ziel versteht keine Joins."
|
||||
|
||||
#. TRANS: Client exception.
|
||||
msgid "This target doesn't understand leave events."
|
||||
msgstr "Dieses Ziel versteht das Verlassen von Events nicht."
|
||||
|
||||
#. TRANS: Exception.
|
||||
msgid "Received a salmon slap from unidentified actor."
|
||||
msgstr "Einen Salmon-Slap von einem unidentifizierten Aktor empfangen."
|
File diff suppressed because it is too large
Load Diff
@@ -9,13 +9,13 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: StatusNet - OStatus\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2010-12-16 15:08+0000\n"
|
||||
"PO-Revision-Date: 2010-12-16 15:12:44+0000\n"
|
||||
"POT-Creation-Date: 2011-01-14 10:29+0000\n"
|
||||
"PO-Revision-Date: 2011-01-14 10:33:50+0000\n"
|
||||
"Language-Team: Galician <http://translatewiki.net/wiki/Portal:gl>\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-POT-Import-Date: 2010-11-30 20:43:51+0000\n"
|
||||
"X-Generator: MediaWiki 1.18alpha (r78478); Translate extension (2010-09-17)\n"
|
||||
"X-POT-Import-Date: 2011-01-10 18:26:06+0000\n"
|
||||
"X-Generator: MediaWiki 1.18alpha (r80246); Translate extension (2010-09-17)\n"
|
||||
"X-Translation-Project: translatewiki.net at http://translatewiki.net\n"
|
||||
"X-Language-Code: gl\n"
|
||||
"X-Message-Group: #out-statusnet-plugin-ostatus\n"
|
||||
@@ -23,94 +23,94 @@ msgstr ""
|
||||
|
||||
#. TRANS: Link description for link to subscribe to a remote user.
|
||||
#. TRANS: Link text for a user to subscribe to an OStatus user.
|
||||
#: OStatusPlugin.php:225 OStatusPlugin.php:935
|
||||
#: OStatusPlugin.php:223 OStatusPlugin.php:933
|
||||
msgid "Subscribe"
|
||||
msgstr "Subscribirse"
|
||||
|
||||
#. TRANS: Link description for link to join a remote group.
|
||||
#: OStatusPlugin.php:244 OStatusPlugin.php:653 actions/ostatussub.php:109
|
||||
#: OStatusPlugin.php:242 OStatusPlugin.php:651 actions/ostatussub.php:109
|
||||
msgid "Join"
|
||||
msgstr "Unirse"
|
||||
|
||||
#. TRANSLATE: %s is a domain.
|
||||
#: OStatusPlugin.php:457
|
||||
#: OStatusPlugin.php:455
|
||||
#, php-format
|
||||
msgid "Sent from %s via OStatus"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception.
|
||||
#: OStatusPlugin.php:529
|
||||
#: OStatusPlugin.php:527
|
||||
msgid "Could not set up remote subscription."
|
||||
msgstr ""
|
||||
|
||||
#: OStatusPlugin.php:603
|
||||
#: OStatusPlugin.php:601
|
||||
msgid "Unfollow"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Success message for unsubscribe from user attempt through OStatus.
|
||||
#. TRANS: %1$s is the unsubscriber's name, %2$s is the unsubscribed user's name.
|
||||
#: OStatusPlugin.php:606
|
||||
#: OStatusPlugin.php:604
|
||||
#, php-format
|
||||
msgid "%1$s stopped following %2$s."
|
||||
msgstr ""
|
||||
|
||||
#: OStatusPlugin.php:634
|
||||
#: OStatusPlugin.php:632
|
||||
msgid "Could not set up remote group membership."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Success message for subscribe to group attempt through OStatus.
|
||||
#. TRANS: %1$s is the member name, %2$s is the subscribed group's name.
|
||||
#: OStatusPlugin.php:656
|
||||
#: OStatusPlugin.php:654
|
||||
#, php-format
|
||||
msgid "%1$s has joined group %2$s."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception.
|
||||
#: OStatusPlugin.php:665
|
||||
#: OStatusPlugin.php:663
|
||||
msgid "Failed joining remote group."
|
||||
msgstr ""
|
||||
|
||||
#: OStatusPlugin.php:705
|
||||
#: OStatusPlugin.php:703
|
||||
msgid "Leave"
|
||||
msgstr "Deixar"
|
||||
|
||||
#. TRANS: Success message for unsubscribe from group attempt through OStatus.
|
||||
#. TRANS: %1$s is the member name, %2$s is the unsubscribed group's name.
|
||||
#: OStatusPlugin.php:708
|
||||
#: OStatusPlugin.php:706
|
||||
#, php-format
|
||||
msgid "%1$s has left group %2$s."
|
||||
msgstr ""
|
||||
|
||||
#: OStatusPlugin.php:783
|
||||
#: OStatusPlugin.php:781
|
||||
msgid "Disfavor"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Success message for remove a favorite notice through OStatus.
|
||||
#. TRANS: %1$s is the unfavoring user's name, %2$s is URI to the no longer favored notice.
|
||||
#: OStatusPlugin.php:786
|
||||
#: OStatusPlugin.php:784
|
||||
#, php-format
|
||||
msgid "%1$s marked notice %2$s as no longer a favorite."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Link text for link to remote subscribe.
|
||||
#: OStatusPlugin.php:862
|
||||
#: OStatusPlugin.php:860
|
||||
msgid "Remote"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Title for activity.
|
||||
#: OStatusPlugin.php:902
|
||||
#: OStatusPlugin.php:900
|
||||
msgid "Profile update"
|
||||
msgstr "Actualización do perfil"
|
||||
|
||||
#. TRANS: Ping text for remote profile update through OStatus.
|
||||
#. TRANS: %s is user that updated their profile.
|
||||
#: OStatusPlugin.php:905
|
||||
#: OStatusPlugin.php:903
|
||||
#, php-format
|
||||
msgid "%s has updated their profile page."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Plugin description.
|
||||
#: OStatusPlugin.php:950
|
||||
#: OStatusPlugin.php:948
|
||||
msgid ""
|
||||
"Follow people across social networks that implement <a href=\"http://ostatus."
|
||||
"org/\">OStatus</a>."
|
||||
@@ -161,102 +161,102 @@ msgid "RSS feed without a channel."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: classes/Ostatus_profile.php:478
|
||||
#: classes/Ostatus_profile.php:479
|
||||
msgid "Can't handle that kind of post."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception. %s is a source URI.
|
||||
#: classes/Ostatus_profile.php:561
|
||||
#: classes/Ostatus_profile.php:537
|
||||
#, php-format
|
||||
msgid "No content for notice %s."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Shown when a notice is longer than supported and/or when attachments are present. At runtime
|
||||
#. TRANS: this will usually be replaced with localised text from StatusNet core messages.
|
||||
#: classes/Ostatus_profile.php:596
|
||||
#: classes/Ostatus_profile.php:572
|
||||
msgid "Show more"
|
||||
msgstr "Mostrar máis"
|
||||
|
||||
#. TRANS: Exception. %s is a profile URL.
|
||||
#: classes/Ostatus_profile.php:789
|
||||
#: classes/Ostatus_profile.php:765
|
||||
#, php-format
|
||||
msgid "Could not reach profile page %s."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception. %s is a URL.
|
||||
#: classes/Ostatus_profile.php:847
|
||||
#: classes/Ostatus_profile.php:823
|
||||
#, php-format
|
||||
msgid "Could not find a feed URL for profile page %s."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Feed sub exception.
|
||||
#: classes/Ostatus_profile.php:985
|
||||
#: classes/Ostatus_profile.php:922
|
||||
msgid "Can't find enough profile information to make a feed."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Server exception. %s is a URL.
|
||||
#: classes/Ostatus_profile.php:1045
|
||||
#: classes/Ostatus_profile.php:986
|
||||
#, php-format
|
||||
msgid "Invalid avatar URL %s."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Server exception. %s is a URI.
|
||||
#: classes/Ostatus_profile.php:1056
|
||||
#: classes/Ostatus_profile.php:997
|
||||
#, php-format
|
||||
msgid "Tried to update avatar for unsaved remote profile %s."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Server exception. %s is a URL.
|
||||
#: classes/Ostatus_profile.php:1066
|
||||
#: classes/Ostatus_profile.php:1007
|
||||
#, php-format
|
||||
msgid "Unable to fetch avatar from %s."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception.
|
||||
#: classes/Ostatus_profile.php:1292
|
||||
#: classes/Ostatus_profile.php:1233
|
||||
msgid "Local user can't be referenced as remote."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception.
|
||||
#: classes/Ostatus_profile.php:1297
|
||||
#: classes/Ostatus_profile.php:1238
|
||||
msgid "Local group can't be referenced as remote."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Server exception.
|
||||
#: classes/Ostatus_profile.php:1349 classes/Ostatus_profile.php:1360
|
||||
#: classes/Ostatus_profile.php:1290 classes/Ostatus_profile.php:1301
|
||||
msgid "Can't save local profile."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Server exception.
|
||||
#: classes/Ostatus_profile.php:1368
|
||||
#: classes/Ostatus_profile.php:1309
|
||||
msgid "Can't save OStatus profile."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception.
|
||||
#: classes/Ostatus_profile.php:1632 classes/Ostatus_profile.php:1660
|
||||
#: classes/Ostatus_profile.php:1573 classes/Ostatus_profile.php:1601
|
||||
msgid "Not a valid webfinger address."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception. %s is a webfinger address.
|
||||
#: classes/Ostatus_profile.php:1742
|
||||
#: classes/Ostatus_profile.php:1683
|
||||
#, php-format
|
||||
msgid "Couldn't save profile for \"%s\"."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception. %s is a webfinger address.
|
||||
#: classes/Ostatus_profile.php:1761
|
||||
#: classes/Ostatus_profile.php:1702
|
||||
#, php-format
|
||||
msgid "Couldn't save ostatus_profile for \"%s\"."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception. %s is a webfinger address.
|
||||
#: classes/Ostatus_profile.php:1769
|
||||
#: classes/Ostatus_profile.php:1710
|
||||
#, php-format
|
||||
msgid "Couldn't find a valid profile for \"%s\"."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Server exception.
|
||||
#: classes/Ostatus_profile.php:1812
|
||||
#: classes/Ostatus_profile.php:1753
|
||||
msgid "Could not store HTML content of long post as file."
|
||||
msgstr ""
|
||||
|
||||
@@ -273,72 +273,72 @@ msgid "Callback returned status: %1$s. Body: %2$s"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client error. POST is a HTTP command. It should not be translated.
|
||||
#: lib/salmonaction.php:42
|
||||
#: lib/salmonaction.php:43
|
||||
msgid "This method requires a POST."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client error. Do not translate "application/magic-envelope+xml"
|
||||
#: lib/salmonaction.php:47
|
||||
#: lib/salmonaction.php:48
|
||||
msgid "Salmon requires \"application/magic-envelope+xml\"."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client error.
|
||||
#: lib/salmonaction.php:57
|
||||
#: lib/salmonaction.php:58
|
||||
msgid "Salmon signature verification failed."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client error.
|
||||
#: lib/salmonaction.php:69
|
||||
#: lib/salmonaction.php:70
|
||||
msgid "Salmon post must be an Atom entry."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: lib/salmonaction.php:118
|
||||
#: lib/salmonaction.php:120
|
||||
msgid "Unrecognized activity type."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: lib/salmonaction.php:127
|
||||
#: lib/salmonaction.php:130
|
||||
msgid "This target doesn't understand posts."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: lib/salmonaction.php:133
|
||||
#: lib/salmonaction.php:136
|
||||
msgid "This target doesn't understand follows."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: lib/salmonaction.php:139
|
||||
#: lib/salmonaction.php:142
|
||||
msgid "This target doesn't understand unfollows."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: lib/salmonaction.php:145
|
||||
#: lib/salmonaction.php:148
|
||||
msgid "This target doesn't understand favorites."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: lib/salmonaction.php:151
|
||||
#: lib/salmonaction.php:154
|
||||
msgid "This target doesn't understand unfavorites."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: lib/salmonaction.php:157
|
||||
#: lib/salmonaction.php:160
|
||||
msgid "This target doesn't understand share events."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: lib/salmonaction.php:163
|
||||
#: lib/salmonaction.php:166
|
||||
msgid "This target doesn't understand joins."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: lib/salmonaction.php:169
|
||||
#: lib/salmonaction.php:172
|
||||
msgid "This target doesn't understand leave events."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception.
|
||||
#: lib/salmonaction.php:197
|
||||
#: lib/salmonaction.php:200
|
||||
msgid "Received a salmon slap from unidentified actor."
|
||||
msgstr ""
|
||||
|
||||
@@ -428,38 +428,38 @@ msgid "No ID."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: actions/usersalmon.php:81
|
||||
#: actions/usersalmon.php:83
|
||||
msgid "In reply to unknown notice."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: actions/usersalmon.php:86
|
||||
#: actions/usersalmon.php:88
|
||||
msgid "In reply to a notice not by this user and not mentioning this user."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: actions/usersalmon.php:163
|
||||
#: actions/usersalmon.php:165
|
||||
msgid "Could not save new favorite."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: actions/usersalmon.php:195
|
||||
#: actions/usersalmon.php:197
|
||||
msgid "Can't favorite/unfavorite without an object."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: actions/usersalmon.php:207
|
||||
#: actions/usersalmon.php:209
|
||||
msgid "Can't handle that kind of object for liking/faving."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception. %s is an object ID.
|
||||
#: actions/usersalmon.php:214
|
||||
#: actions/usersalmon.php:216
|
||||
#, php-format
|
||||
msgid "Notice with ID %s unknown."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception. %1$s is a notice ID, %2$s is a user ID.
|
||||
#: actions/usersalmon.php:219
|
||||
#: actions/usersalmon.php:221
|
||||
#, php-format
|
||||
msgid "Notice with ID %1$s not posted by %2$s."
|
||||
msgstr ""
|
||||
@@ -517,36 +517,36 @@ msgid "No such group."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client error.
|
||||
#: actions/groupsalmon.php:53
|
||||
#: actions/groupsalmon.php:56
|
||||
msgid "Can't accept remote posts for a remote group."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client error.
|
||||
#: actions/groupsalmon.php:127
|
||||
#: actions/groupsalmon.php:130
|
||||
msgid "Can't read profile to set up group membership."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client error.
|
||||
#: actions/groupsalmon.php:131 actions/groupsalmon.php:174
|
||||
#: actions/groupsalmon.php:134 actions/groupsalmon.php:177
|
||||
msgid "Groups can't join groups."
|
||||
msgstr ""
|
||||
|
||||
#: actions/groupsalmon.php:144
|
||||
#: actions/groupsalmon.php:147
|
||||
msgid "You have been blocked from that group by the admin."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Server error. %1$s is a profile URI, %2$s is a group nickname.
|
||||
#: actions/groupsalmon.php:159
|
||||
#: actions/groupsalmon.php:162
|
||||
#, php-format
|
||||
msgid "Could not join remote user %1$s to group %2$s."
|
||||
msgstr ""
|
||||
|
||||
#: actions/groupsalmon.php:171
|
||||
#: actions/groupsalmon.php:174
|
||||
msgid "Can't read profile to cancel group membership."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Server error. %1$s is a profile URI, %2$s is a group nickname.
|
||||
#: actions/groupsalmon.php:188
|
||||
#: actions/groupsalmon.php:191
|
||||
#, php-format
|
||||
msgid "Could not remove remote user %1$s from group %2$s."
|
||||
msgstr ""
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
758
plugins/OStatus/locale/zh_CN/LC_MESSAGES/OStatus.po
Normal file
758
plugins/OStatus/locale/zh_CN/LC_MESSAGES/OStatus.po
Normal file
@@ -0,0 +1,758 @@
|
||||
# Translation of StatusNet - OStatus to Simplified Chinese (中文(简体))
|
||||
# Expored from translatewiki.net
|
||||
#
|
||||
# Author: ZhengYiFeng
|
||||
# --
|
||||
# This file is distributed under the same license as the StatusNet package.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: StatusNet - OStatus\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2011-01-15 00:20+0000\n"
|
||||
"PO-Revision-Date: 2011-01-15 00:24:30+0000\n"
|
||||
"Language-Team: Simplified Chinese <http://translatewiki.net/wiki/Portal:zh-"
|
||||
"hans>\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-POT-Import-Date: 2011-01-14 13:21:17+0000\n"
|
||||
"X-Generator: MediaWiki 1.18alpha (r80364); Translate extension (2010-09-17)\n"
|
||||
"X-Translation-Project: translatewiki.net at http://translatewiki.net\n"
|
||||
"X-Language-Code: zh-hans\n"
|
||||
"X-Message-Group: #out-statusnet-plugin-ostatus\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
|
||||
#. TRANS: Link description for link to subscribe to a remote user.
|
||||
#. TRANS: Link text for a user to subscribe to an OStatus user.
|
||||
#: OStatusPlugin.php:223 OStatusPlugin.php:933
|
||||
msgid "Subscribe"
|
||||
msgstr "关注"
|
||||
|
||||
#. TRANS: Link description for link to join a remote group.
|
||||
#: OStatusPlugin.php:242 OStatusPlugin.php:651 actions/ostatussub.php:109
|
||||
msgid "Join"
|
||||
msgstr "加入"
|
||||
|
||||
#. TRANSLATE: %s is a domain.
|
||||
#: OStatusPlugin.php:455
|
||||
#, php-format
|
||||
msgid "Sent from %s via OStatus"
|
||||
msgstr "从 %s 通过 OStatus 发布"
|
||||
|
||||
#. TRANS: Exception.
|
||||
#: OStatusPlugin.php:527
|
||||
msgid "Could not set up remote subscription."
|
||||
msgstr "无法设置远程关注。"
|
||||
|
||||
#: OStatusPlugin.php:601
|
||||
msgid "Unfollow"
|
||||
msgstr "取消关注"
|
||||
|
||||
#. TRANS: Success message for unsubscribe from user attempt through OStatus.
|
||||
#. TRANS: %1$s is the unsubscriber's name, %2$s is the unsubscribed user's name.
|
||||
#: OStatusPlugin.php:604
|
||||
#, php-format
|
||||
msgid "%1$s stopped following %2$s."
|
||||
msgstr "%1$s 取消了对 %2$s 的关注。"
|
||||
|
||||
#: OStatusPlugin.php:632
|
||||
msgid "Could not set up remote group membership."
|
||||
msgstr "无法设置远程的小组成员。"
|
||||
|
||||
#. TRANS: Success message for subscribe to group attempt through OStatus.
|
||||
#. TRANS: %1$s is the member name, %2$s is the subscribed group's name.
|
||||
#: OStatusPlugin.php:654
|
||||
#, php-format
|
||||
msgid "%1$s has joined group %2$s."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception.
|
||||
#: OStatusPlugin.php:663
|
||||
msgid "Failed joining remote group."
|
||||
msgstr "加入远程小组失败。"
|
||||
|
||||
#: OStatusPlugin.php:703
|
||||
msgid "Leave"
|
||||
msgstr "离开"
|
||||
|
||||
#. TRANS: Success message for unsubscribe from group attempt through OStatus.
|
||||
#. TRANS: %1$s is the member name, %2$s is the unsubscribed group's name.
|
||||
#: OStatusPlugin.php:706
|
||||
#, php-format
|
||||
msgid "%1$s has left group %2$s."
|
||||
msgstr ""
|
||||
|
||||
#: OStatusPlugin.php:781
|
||||
msgid "Disfavor"
|
||||
msgstr "取消收藏"
|
||||
|
||||
#. TRANS: Success message for remove a favorite notice through OStatus.
|
||||
#. TRANS: %1$s is the unfavoring user's name, %2$s is URI to the no longer favored notice.
|
||||
#: OStatusPlugin.php:784
|
||||
#, php-format
|
||||
msgid "%1$s marked notice %2$s as no longer a favorite."
|
||||
msgstr "%1$s 将消息 %2$s 取消了收藏。"
|
||||
|
||||
#. TRANS: Link text for link to remote subscribe.
|
||||
#: OStatusPlugin.php:860
|
||||
msgid "Remote"
|
||||
msgstr "远程"
|
||||
|
||||
#. TRANS: Title for activity.
|
||||
#: OStatusPlugin.php:900
|
||||
msgid "Profile update"
|
||||
msgstr "个人信息更新"
|
||||
|
||||
#. TRANS: Ping text for remote profile update through OStatus.
|
||||
#. TRANS: %s is user that updated their profile.
|
||||
#: OStatusPlugin.php:903
|
||||
#, php-format
|
||||
msgid "%s has updated their profile page."
|
||||
msgstr "%s 更新了他/她的个人信息页。"
|
||||
|
||||
#. TRANS: Plugin description.
|
||||
#: OStatusPlugin.php:948
|
||||
msgid ""
|
||||
"Follow people across social networks that implement <a href=\"http://ostatus."
|
||||
"org/\">OStatus</a>."
|
||||
msgstr ""
|
||||
|
||||
#: classes/FeedSub.php:252
|
||||
msgid "Attempting to start PuSH subscription for feed with no hub."
|
||||
msgstr ""
|
||||
|
||||
#: classes/FeedSub.php:282
|
||||
msgid "Attempting to end PuSH subscription for feed with no hub."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Server exception. %s is a URI.
|
||||
#: classes/Ostatus_profile.php:192
|
||||
#, php-format
|
||||
msgid "Invalid ostatus_profile state: both group and profile IDs set for %s."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Server exception. %s is a URI.
|
||||
#: classes/Ostatus_profile.php:195
|
||||
#, php-format
|
||||
msgid "Invalid ostatus_profile state: both group and profile IDs empty for %s."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Server exception.
|
||||
#. TRANS: %1$s is the method name the exception occured in, %2$s is the actor type.
|
||||
#: classes/Ostatus_profile.php:285
|
||||
#, php-format
|
||||
msgid "Invalid actor passed to %1$s: %2$s."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Server exception.
|
||||
#: classes/Ostatus_profile.php:378
|
||||
msgid ""
|
||||
"Invalid type passed to Ostatus_profile::notify. It must be XML string or "
|
||||
"Activity entry."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception.
|
||||
#: classes/Ostatus_profile.php:409
|
||||
msgid "Unknown feed format."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception.
|
||||
#: classes/Ostatus_profile.php:433
|
||||
msgid "RSS feed without a channel."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: classes/Ostatus_profile.php:479
|
||||
msgid "Can't handle that kind of post."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception. %s is a source URI.
|
||||
#: classes/Ostatus_profile.php:537
|
||||
#, php-format
|
||||
msgid "No content for notice %s."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Shown when a notice is longer than supported and/or when attachments are present. At runtime
|
||||
#. TRANS: this will usually be replaced with localised text from StatusNet core messages.
|
||||
#: classes/Ostatus_profile.php:572
|
||||
msgid "Show more"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception. %s is a profile URL.
|
||||
#: classes/Ostatus_profile.php:765
|
||||
#, php-format
|
||||
msgid "Could not reach profile page %s."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception. %s is a URL.
|
||||
#: classes/Ostatus_profile.php:823
|
||||
#, php-format
|
||||
msgid "Could not find a feed URL for profile page %s."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Feed sub exception.
|
||||
#: classes/Ostatus_profile.php:922
|
||||
msgid "Can't find enough profile information to make a feed."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Server exception. %s is a URL.
|
||||
#: classes/Ostatus_profile.php:986
|
||||
#, php-format
|
||||
msgid "Invalid avatar URL %s."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Server exception. %s is a URI.
|
||||
#: classes/Ostatus_profile.php:997
|
||||
#, php-format
|
||||
msgid "Tried to update avatar for unsaved remote profile %s."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Server exception. %s is a URL.
|
||||
#: classes/Ostatus_profile.php:1007
|
||||
#, php-format
|
||||
msgid "Unable to fetch avatar from %s."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception.
|
||||
#: classes/Ostatus_profile.php:1233
|
||||
msgid "Local user can't be referenced as remote."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception.
|
||||
#: classes/Ostatus_profile.php:1238
|
||||
msgid "Local group can't be referenced as remote."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Server exception.
|
||||
#: classes/Ostatus_profile.php:1290 classes/Ostatus_profile.php:1301
|
||||
msgid "Can't save local profile."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Server exception.
|
||||
#: classes/Ostatus_profile.php:1309
|
||||
msgid "Can't save OStatus profile."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception.
|
||||
#: classes/Ostatus_profile.php:1573 classes/Ostatus_profile.php:1601
|
||||
msgid "Not a valid webfinger address."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception. %s is a webfinger address.
|
||||
#: classes/Ostatus_profile.php:1683
|
||||
#, php-format
|
||||
msgid "Couldn't save profile for \"%s\"."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception. %s is a webfinger address.
|
||||
#: classes/Ostatus_profile.php:1702
|
||||
#, php-format
|
||||
msgid "Couldn't save ostatus_profile for \"%s\"."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception. %s is a webfinger address.
|
||||
#: classes/Ostatus_profile.php:1710
|
||||
#, php-format
|
||||
msgid "Couldn't find a valid profile for \"%s\"."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Server exception.
|
||||
#: classes/Ostatus_profile.php:1753
|
||||
msgid "Could not store HTML content of long post as file."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception. %s is a HTTP status code.
|
||||
#: classes/HubSub.php:212
|
||||
#, php-format
|
||||
msgid "Hub subscriber verification returned HTTP %s."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception. %1$s is a response status code, %2$s is the body of the response.
|
||||
#: classes/HubSub.php:359
|
||||
#, php-format
|
||||
msgid "Callback returned status: %1$s. Body: %2$s"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client error. POST is a HTTP command. It should not be translated.
|
||||
#: lib/salmonaction.php:43
|
||||
msgid "This method requires a POST."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client error. Do not translate "application/magic-envelope+xml"
|
||||
#: lib/salmonaction.php:48
|
||||
msgid "Salmon requires \"application/magic-envelope+xml\"."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client error.
|
||||
#: lib/salmonaction.php:58
|
||||
msgid "Salmon signature verification failed."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client error.
|
||||
#: lib/salmonaction.php:70
|
||||
msgid "Salmon post must be an Atom entry."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: lib/salmonaction.php:120
|
||||
msgid "Unrecognized activity type."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: lib/salmonaction.php:130
|
||||
msgid "This target doesn't understand posts."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: lib/salmonaction.php:136
|
||||
msgid "This target doesn't understand follows."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: lib/salmonaction.php:142
|
||||
msgid "This target doesn't understand unfollows."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: lib/salmonaction.php:148
|
||||
msgid "This target doesn't understand favorites."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: lib/salmonaction.php:154
|
||||
msgid "This target doesn't understand unfavorites."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: lib/salmonaction.php:160
|
||||
msgid "This target doesn't understand share events."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: lib/salmonaction.php:166
|
||||
msgid "This target doesn't understand joins."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: lib/salmonaction.php:172
|
||||
msgid "This target doesn't understand leave events."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception.
|
||||
#: lib/salmonaction.php:200
|
||||
msgid "Received a salmon slap from unidentified actor."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception.
|
||||
#: lib/discovery.php:110
|
||||
#, php-format
|
||||
msgid "Unable to find services for %s."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception.
|
||||
#: lib/magicenvelope.php:80
|
||||
msgid "Unable to locate signer public key."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Exception.
|
||||
#: lib/salmon.php:93
|
||||
msgid "Salmon invalid actor for signing."
|
||||
msgstr ""
|
||||
|
||||
#: tests/gettext-speedtest.php:57
|
||||
msgid "Feeds"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: actions/pushhub.php:70
|
||||
msgid "Publishing outside feeds not supported."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception. %s is a mode.
|
||||
#: actions/pushhub.php:73
|
||||
#, php-format
|
||||
msgid "Unrecognized mode \"%s\"."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception. %s is a topic.
|
||||
#: actions/pushhub.php:93
|
||||
#, php-format
|
||||
msgid ""
|
||||
"Unsupported hub.topic %s this hub only serves local user and group Atom "
|
||||
"feeds."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: actions/pushhub.php:99
|
||||
#, php-format
|
||||
msgid "Invalid hub.verify \"%s\". It must be sync or async."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: actions/pushhub.php:105
|
||||
#, php-format
|
||||
msgid "Invalid hub.lease \"%s\". It must be empty or positive integer."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: actions/pushhub.php:113
|
||||
#, php-format
|
||||
msgid "Invalid hub.secret \"%s\". It must be under 200 bytes."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: actions/pushhub.php:165
|
||||
#, php-format
|
||||
msgid "Invalid hub.topic \"%s\". User doesn't exist."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: actions/pushhub.php:174
|
||||
#, php-format
|
||||
msgid "Invalid hub.topic \"%s\". Group doesn't exist."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#. TRANS: %1$s is this argument to the method this exception occurs in, %2$s is a URL.
|
||||
#: actions/pushhub.php:199
|
||||
#, php-format
|
||||
msgid "Invalid URL passed for %1$s: \"%2$s\""
|
||||
msgstr ""
|
||||
|
||||
#: actions/ownerxrd.php:39 actions/usersalmon.php:43
|
||||
msgid "No such user."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client error.
|
||||
#: actions/usersalmon.php:37 actions/groupsalmon.php:40
|
||||
msgid "No ID."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: actions/usersalmon.php:83
|
||||
msgid "In reply to unknown notice."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: actions/usersalmon.php:88
|
||||
msgid "In reply to a notice not by this user and not mentioning this user."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: actions/usersalmon.php:165
|
||||
msgid "Could not save new favorite."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: actions/usersalmon.php:197
|
||||
msgid "Can't favorite/unfavorite without an object."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception.
|
||||
#: actions/usersalmon.php:209
|
||||
msgid "Can't handle that kind of object for liking/faving."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception. %s is an object ID.
|
||||
#: actions/usersalmon.php:216
|
||||
#, php-format
|
||||
msgid "Notice with ID %s unknown."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception. %1$s is a notice ID, %2$s is a user ID.
|
||||
#: actions/usersalmon.php:221
|
||||
#, php-format
|
||||
msgid "Notice with ID %1$s not posted by %2$s."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Field label.
|
||||
#: actions/ostatusgroup.php:78
|
||||
msgid "Join group"
|
||||
msgstr "加入小组"
|
||||
|
||||
#. TRANS: Tooltip for field label "Join group".
|
||||
#: actions/ostatusgroup.php:81
|
||||
msgid "OStatus group's address, like http://example.net/group/nickname."
|
||||
msgstr "OStatus 小组的地址,例如 http://example.net/group/nickname。"
|
||||
|
||||
#. TRANS: Button text.
|
||||
#: actions/ostatusgroup.php:86 actions/ostatussub.php:75
|
||||
msgctxt "BUTTON"
|
||||
msgid "Continue"
|
||||
msgstr "继续"
|
||||
|
||||
#: actions/ostatusgroup.php:105
|
||||
msgid "You are already a member of this group."
|
||||
msgstr "你已经是该小组成员。"
|
||||
|
||||
#. TRANS: OStatus remote group subscription dialog error.
|
||||
#: actions/ostatusgroup.php:140
|
||||
msgid "Already a member!"
|
||||
msgstr "已经是成员了!"
|
||||
|
||||
#. TRANS: OStatus remote group subscription dialog error.
|
||||
#: actions/ostatusgroup.php:151
|
||||
msgid "Remote group join failed!"
|
||||
msgstr "加入远程小组失败!"
|
||||
|
||||
#. TRANS: OStatus remote group subscription dialog error.
|
||||
#: actions/ostatusgroup.php:155
|
||||
msgid "Remote group join aborted!"
|
||||
msgstr "加入远程小组取消!"
|
||||
|
||||
#. TRANS: Page title for OStatus remote group join form
|
||||
#: actions/ostatusgroup.php:167
|
||||
msgid "Confirm joining remote group"
|
||||
msgstr "确认加入远程小组"
|
||||
|
||||
#. TRANS: Instructions.
|
||||
#: actions/ostatusgroup.php:178
|
||||
msgid ""
|
||||
"You can subscribe to groups from other supported sites. Paste the group's "
|
||||
"profile URI below:"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client error.
|
||||
#: actions/groupsalmon.php:47
|
||||
msgid "No such group."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client error.
|
||||
#: actions/groupsalmon.php:56
|
||||
msgid "Can't accept remote posts for a remote group."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client error.
|
||||
#: actions/groupsalmon.php:130
|
||||
msgid "Can't read profile to set up group membership."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client error.
|
||||
#: actions/groupsalmon.php:134 actions/groupsalmon.php:177
|
||||
msgid "Groups can't join groups."
|
||||
msgstr ""
|
||||
|
||||
#: actions/groupsalmon.php:147
|
||||
msgid "You have been blocked from that group by the admin."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Server error. %1$s is a profile URI, %2$s is a group nickname.
|
||||
#: actions/groupsalmon.php:162
|
||||
#, php-format
|
||||
msgid "Could not join remote user %1$s to group %2$s."
|
||||
msgstr ""
|
||||
|
||||
#: actions/groupsalmon.php:174
|
||||
msgid "Can't read profile to cancel group membership."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Server error. %1$s is a profile URI, %2$s is a group nickname.
|
||||
#: actions/groupsalmon.php:191
|
||||
#, php-format
|
||||
msgid "Could not remove remote user %1$s from group %2$s."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Field label for a field that takes an OStatus user address.
|
||||
#: actions/ostatussub.php:68
|
||||
msgid "Subscribe to"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Tooltip for field label "Subscribe to".
|
||||
#: actions/ostatussub.php:71
|
||||
msgid ""
|
||||
"OStatus user's address, like nickname@example.com or http://example.net/"
|
||||
"nickname"
|
||||
msgstr ""
|
||||
"OStatus 用户的地址,例如 nickname@example.com 或 http://example.net/nickname"
|
||||
|
||||
#. TRANS: Button text.
|
||||
#. TRANS: Tooltip for button "Join".
|
||||
#: actions/ostatussub.php:112
|
||||
msgctxt "BUTTON"
|
||||
msgid "Join this group"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Button text.
|
||||
#: actions/ostatussub.php:115
|
||||
msgctxt "BUTTON"
|
||||
msgid "Confirm"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Tooltip for button "Confirm".
|
||||
#: actions/ostatussub.php:117
|
||||
msgid "Subscribe to this user"
|
||||
msgstr ""
|
||||
|
||||
#: actions/ostatussub.php:138
|
||||
msgid "You are already subscribed to this user."
|
||||
msgstr ""
|
||||
|
||||
#: actions/ostatussub.php:167
|
||||
msgid "Photo"
|
||||
msgstr ""
|
||||
|
||||
#: actions/ostatussub.php:178
|
||||
msgid "Nickname"
|
||||
msgstr ""
|
||||
|
||||
#: actions/ostatussub.php:199
|
||||
msgid "Location"
|
||||
msgstr ""
|
||||
|
||||
#: actions/ostatussub.php:208
|
||||
msgid "URL"
|
||||
msgstr ""
|
||||
|
||||
#: actions/ostatussub.php:220
|
||||
msgid "Note"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Error text.
|
||||
#: actions/ostatussub.php:256 actions/ostatussub.php:263
|
||||
#: actions/ostatussub.php:288
|
||||
msgid ""
|
||||
"Sorry, we could not reach that address. Please make sure that the OStatus "
|
||||
"address is like nickname@example.com or http://example.net/nickname."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Error text.
|
||||
#: actions/ostatussub.php:267 actions/ostatussub.php:271
|
||||
#: actions/ostatussub.php:275 actions/ostatussub.php:279
|
||||
#: actions/ostatussub.php:283
|
||||
msgid ""
|
||||
"Sorry, we could not reach that feed. Please try that OStatus address again "
|
||||
"later."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: OStatus remote subscription dialog error.
|
||||
#: actions/ostatussub.php:317
|
||||
msgid "Already subscribed!"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: OStatus remote subscription dialog error.
|
||||
#: actions/ostatussub.php:322
|
||||
msgid "Remote subscription failed!"
|
||||
msgstr ""
|
||||
|
||||
#: actions/ostatussub.php:369 actions/ostatusinit.php:64
|
||||
msgid "There was a problem with your session token. Try again, please."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Form title.
|
||||
#: actions/ostatussub.php:397 actions/ostatusinit.php:83
|
||||
msgid "Subscribe to user"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Page title for OStatus remote subscription form
|
||||
#: actions/ostatussub.php:417
|
||||
msgid "Confirm"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Instructions.
|
||||
#: actions/ostatussub.php:429
|
||||
msgid ""
|
||||
"You can subscribe to users from other supported sites. Paste their address "
|
||||
"or profile URI below:"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client error.
|
||||
#: actions/ostatusinit.php:42
|
||||
msgid "You can use the local subscription!"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Form legend.
|
||||
#: actions/ostatusinit.php:98
|
||||
#, php-format
|
||||
msgid "Join group %s"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Button text.
|
||||
#: actions/ostatusinit.php:100
|
||||
msgctxt "BUTTON"
|
||||
msgid "Join"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Form legend.
|
||||
#: actions/ostatusinit.php:103
|
||||
#, php-format
|
||||
msgid "Subscribe to %s"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Button text.
|
||||
#: actions/ostatusinit.php:105
|
||||
msgctxt "BUTTON"
|
||||
msgid "Subscribe"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Field label.
|
||||
#: actions/ostatusinit.php:118
|
||||
msgid "User nickname"
|
||||
msgstr ""
|
||||
|
||||
#: actions/ostatusinit.php:119
|
||||
msgid "Nickname of the user you want to follow."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Field label.
|
||||
#: actions/ostatusinit.php:124
|
||||
msgid "Profile Account"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Tooltip for field label "Profile Account".
|
||||
#: actions/ostatusinit.php:126
|
||||
msgid "Your account id (e.g. user@identi.ca)."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client error.
|
||||
#: actions/ostatusinit.php:148
|
||||
msgid "Must provide a remote profile."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client error.
|
||||
#: actions/ostatusinit.php:160
|
||||
msgid "Couldn't look up OStatus account profile."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client error.
|
||||
#: actions/ostatusinit.php:173
|
||||
msgid "Couldn't confirm remote profile address."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Page title.
|
||||
#: actions/ostatusinit.php:218
|
||||
msgid "OStatus Connect"
|
||||
msgstr ""
|
||||
|
||||
#: actions/pushcallback.php:50
|
||||
msgid "Empty or invalid feed id."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Server exception. %s is a feed ID.
|
||||
#: actions/pushcallback.php:56
|
||||
#, php-format
|
||||
msgid "Unknown PuSH feed id %s"
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception. %s is an invalid feed name.
|
||||
#: actions/pushcallback.php:96
|
||||
#, php-format
|
||||
msgid "Bad hub.topic feed \"%s\"."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception. %1$s the invalid token, %2$s is the topic for which the invalid token was given.
|
||||
#: actions/pushcallback.php:101
|
||||
#, php-format
|
||||
msgid "Bad hub.verify_token %1$s for %2$s."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception. %s is an invalid topic.
|
||||
#: actions/pushcallback.php:108
|
||||
#, php-format
|
||||
msgid "Unexpected subscribe request for %s."
|
||||
msgstr ""
|
||||
|
||||
#. TRANS: Client exception. %s is an invalid topic.
|
||||
#: actions/pushcallback.php:113
|
||||
#, php-format
|
||||
msgid "Unexpected unsubscribe request for %s."
|
||||
msgstr ""
|
121
plugins/OStatus/scripts/update-profile-data.php
Normal file
121
plugins/OStatus/scripts/update-profile-data.php
Normal file
@@ -0,0 +1,121 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/*
|
||||
* StatusNet - a distributed open-source microblogging tool
|
||||
* Copyright (C) 2010, StatusNet, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..'));
|
||||
|
||||
$longoptions = array('all', 'suspicious', 'quiet');
|
||||
|
||||
$helptext = <<<END_OF_HELP
|
||||
update-profile-data.php [options] [http://example.com/profile/url]
|
||||
|
||||
Rerun profile discovery for the given OStatus remote profile, and save the
|
||||
updated profile data (nickname, avatar, bio, etc). Doesn't touch feed state.
|
||||
Can be used to clean up after breakages.
|
||||
|
||||
Options:
|
||||
--all Run for all known OStatus profiles
|
||||
--suspicious Run for OStatus profiles with all-numeric nicknames
|
||||
(fixes 0.9.7 prerelease back-compatibility bug)
|
||||
|
||||
END_OF_HELP;
|
||||
|
||||
require_once INSTALLDIR.'/scripts/commandline.inc';
|
||||
|
||||
function showProfileInfo($oprofile) {
|
||||
if ($oprofile->isGroup()) {
|
||||
echo "group\n";
|
||||
} else {
|
||||
$profile = $oprofile->localProfile();
|
||||
foreach (array('nickname', 'bio', 'homepage', 'location') as $field) {
|
||||
print " $field: {$profile->$field}\n";
|
||||
}
|
||||
}
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
function fixProfile($uri) {
|
||||
$oprofile = Ostatus_profile::staticGet('uri', $uri);
|
||||
|
||||
if (!$oprofile) {
|
||||
print "No OStatus remote profile known for URI $uri\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
echo "Before:\n";
|
||||
showProfileInfo($oprofile);
|
||||
|
||||
$feedurl = $oprofile->feeduri;
|
||||
$client = new HttpClient();
|
||||
$response = $client->get($feedurl);
|
||||
if ($response->isOk()) {
|
||||
echo "Updating profile from feed: $feedurl\n";
|
||||
$dom = new DOMDocument();
|
||||
if ($dom->loadXML($response->getBody())) {
|
||||
$feed = $dom->documentElement;
|
||||
$entries = $dom->getElementsByTagNameNS(Activity::ATOM, 'entry');
|
||||
if ($entries->length) {
|
||||
$entry = $entries->item(0);
|
||||
$activity = new Activity($entry, $feed);
|
||||
$oprofile->checkAuthorship($activity);
|
||||
echo " (ok)\n";
|
||||
} else {
|
||||
echo " (no entry; skipping)\n";
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
echo " (bad feed; skipping)\n";
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
echo "Failed feed fetch: {$response->getStatus()} for $feedurl\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
echo "After:\n";
|
||||
showProfileInfo($oprofile);
|
||||
return true;
|
||||
}
|
||||
|
||||
$ok = true;
|
||||
if (have_option('all')) {
|
||||
$oprofile = new Ostatus_profile();
|
||||
$oprofile->find();
|
||||
echo "Found $oprofile->N profiles:\n\n";
|
||||
while ($oprofile->fetch()) {
|
||||
$ok = fixProfile($oprofile->uri) && $ok;
|
||||
}
|
||||
} else if (have_option('suspicious')) {
|
||||
$oprofile = new Ostatus_profile();
|
||||
$oprofile->joinAdd(array('profile_id', 'profile:id'));
|
||||
$oprofile->whereAdd("nickname rlike '^[0-9]$'");
|
||||
$oprofile->find();
|
||||
echo "Found $oprofile->N matching profiles:\n\n";
|
||||
while ($oprofile->fetch()) {
|
||||
$ok = fixProfile($oprofile->uri) && $ok;
|
||||
}
|
||||
} else if (!empty($args[0]) && Validate::uri($args[0])) {
|
||||
$uri = $args[0];
|
||||
$ok = fixProfile($uri);
|
||||
} else {
|
||||
print "$helptext";
|
||||
$ok = false;
|
||||
}
|
||||
|
||||
exit($ok ? 0 : 1);
|
60
plugins/OStatus/tests/MagicEnvelopeTest.php
Normal file
60
plugins/OStatus/tests/MagicEnvelopeTest.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) {
|
||||
print "This script must be run from the command line\n";
|
||||
exit();
|
||||
}
|
||||
|
||||
define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..'));
|
||||
define('STATUSNET', true);
|
||||
|
||||
require_once INSTALLDIR . '/lib/common.php';
|
||||
|
||||
class MagicEnvelopeTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* Test that MagicEnvelope builds the correct plaintext for signing.
|
||||
* @dataProvider provider
|
||||
*/
|
||||
public function testSignatureText($env, $expected)
|
||||
{
|
||||
$magic = new MagicEnvelope;
|
||||
$text = $magic->signingText($env);
|
||||
|
||||
$this->assertEquals($expected, $text, "'$text' should be '$expected'");
|
||||
}
|
||||
|
||||
static public function provider()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
// Sample case given in spec:
|
||||
// http://salmon-protocol.googlecode.com/svn/trunk/draft-panzer-magicsig-00.html#signing
|
||||
array(
|
||||
'data' => 'Tm90IHJlYWxseSBBdG9t',
|
||||
'data_type' => 'application/atom+xml',
|
||||
'encoding' => 'base64url',
|
||||
'alg' => 'RSA-SHA256'
|
||||
),
|
||||
'Tm90IHJlYWxseSBBdG9t.YXBwbGljYXRpb24vYXRvbSt4bWw=.YmFzZTY0dXJs.UlNBLVNIQTI1Ng=='
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test that MagicEnvelope builds the correct plaintext for signing.
|
||||
* @dataProvider provider
|
||||
*/
|
||||
public function testSignatureTextCompat($env, $expected)
|
||||
{
|
||||
// Our old code didn't add the extra fields, just used the armored text.
|
||||
$alt = $env['data'];
|
||||
|
||||
$magic = new MagicEnvelopeCompat;
|
||||
$text = $magic->signingText($env);
|
||||
|
||||
$this->assertEquals($alt, $text, "'$text' should be '$alt'");
|
||||
}
|
||||
|
||||
}
|
@@ -72,6 +72,8 @@ class OStatusTester extends TestBase
|
||||
$base = 'test' . mt_rand(1, 1000000);
|
||||
$this->pub = new SNTestClient($this->a, 'pub' . $base, 'pw-' . mt_rand(1, 1000000), $timeout);
|
||||
$this->sub = new SNTestClient($this->b, 'sub' . $base, 'pw-' . mt_rand(1, 1000000), $timeout);
|
||||
|
||||
$this->group = 'group' . $base;
|
||||
}
|
||||
|
||||
function run()
|
||||
@@ -163,6 +165,39 @@ class OStatusTester extends TestBase
|
||||
$this->assertFalse($this->pub->hasSubscriber($this->sub->getProfileUri()));
|
||||
}
|
||||
|
||||
function testCreateGroup()
|
||||
{
|
||||
$this->groupUrl = $this->pub->createGroup($this->group);
|
||||
$this->assertTrue(!empty($this->groupUrl));
|
||||
}
|
||||
|
||||
function testJoinGroup()
|
||||
{
|
||||
#$this->assertFalse($this->sub->inGroup($this->groupUrl));
|
||||
$this->sub->joinGroup($this->groupUrl);
|
||||
#$this->assertTrue($this->sub->inGroup($this->groupUrl));
|
||||
}
|
||||
|
||||
function testLocalGroupPost()
|
||||
{
|
||||
$post = $this->pub->post("Group post from local to !{$this->group}, should go out over push.");
|
||||
$this->assertNotEqual('', $post);
|
||||
$this->sub->assertReceived($post);
|
||||
}
|
||||
|
||||
function testRemoteGroupPost()
|
||||
{
|
||||
$post = $this->sub->post("Group post from remote to !{$this->group}, should come in over salmon.");
|
||||
$this->assertNotEqual('', $post);
|
||||
$this->pub->assertReceived($post);
|
||||
}
|
||||
|
||||
function testLeaveGroup()
|
||||
{
|
||||
#$this->assertTrue($this->sub->inGroup($this->groupUrl));
|
||||
$this->sub->leaveGroup($this->groupUrl);
|
||||
#$this->assertFalse($this->sub->inGroup($this->groupUrl));
|
||||
}
|
||||
}
|
||||
|
||||
class SNTestClient extends TestBase
|
||||
@@ -534,6 +569,63 @@ class SNTestClient extends TestBase
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a group on this site.
|
||||
*
|
||||
* @param string $nickname
|
||||
* @param array $options
|
||||
* @return string: profile URL for the group
|
||||
*/
|
||||
function createGroup($nickname, $options=array()) {
|
||||
$this->log("Creating group as %s on %s: %s",
|
||||
$this->username,
|
||||
$this->basepath,
|
||||
$nickname);
|
||||
|
||||
$data = $this->api('statusnet/groups/create', 'json',
|
||||
array_merge(array('nickname' => $nickname), $options));
|
||||
$url = $data['url'];
|
||||
|
||||
if ($url) {
|
||||
$this->log(' created as %s', $url);
|
||||
} else {
|
||||
$this->log(' failed? %s', var_export($data, true));
|
||||
}
|
||||
return $url;
|
||||
}
|
||||
|
||||
function groupInfo($nickname) {
|
||||
$data = $this->api('statusnet/groups/show', 'json', array(
|
||||
'id' => $nickname
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Join a group.
|
||||
*
|
||||
* @param string $group nickname or URL
|
||||
*/
|
||||
function joinGroup($group) {
|
||||
$this->post('join ' . $group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Leave a group.
|
||||
*
|
||||
* @param string $group nickname or URL
|
||||
*/
|
||||
function leaveGroup($group) {
|
||||
$this->post('drop ' . $group);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $nickname
|
||||
* @return
|
||||
*/
|
||||
function inGroup($nickname) {
|
||||
// @todo
|
||||
}
|
||||
}
|
||||
|
||||
// @fixme switch to commandline.inc?
|
||||
|
92
plugins/OStatus/tests/slap.php
Normal file
92
plugins/OStatus/tests/slap.php
Normal file
@@ -0,0 +1,92 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/*
|
||||
* StatusNet - a distributed open-source microblogging tool
|
||||
* Copyright (C) 2010, StatusNet, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..'));
|
||||
|
||||
$longoptions = array('verify', 'slap=', 'notice=');
|
||||
|
||||
$helptext = <<<END_OF_HELP
|
||||
slap.php [options]
|
||||
|
||||
Test generation and sending of magic envelopes for Salmon slaps.
|
||||
|
||||
--notice=N generate entry for this notice number
|
||||
--verify send signed magic envelope to Tuomas Koski's test service
|
||||
--slap=<url> send signed Salmon slap to the destination endpoint
|
||||
|
||||
|
||||
END_OF_HELP;
|
||||
|
||||
require_once INSTALLDIR.'/scripts/commandline.inc';
|
||||
|
||||
if (!have_option('--notice')) {
|
||||
print "$helptext";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$notice_id = get_option_value('--notice');
|
||||
|
||||
$notice = Notice::staticGet('id', $notice_id);
|
||||
$profile = $notice->getProfile();
|
||||
$entry = $notice->asAtomEntry(true);
|
||||
|
||||
echo "== Original entry ==\n\n";
|
||||
print $entry;
|
||||
print "\n\n";
|
||||
|
||||
$salmon = new Salmon();
|
||||
$envelope = $salmon->createMagicEnv($entry, $profile);
|
||||
|
||||
echo "== Signed envelope ==\n\n";
|
||||
print $envelope;
|
||||
print "\n\n";
|
||||
|
||||
echo "== Testing local verification ==\n\n";
|
||||
$ok = $salmon->verifyMagicEnv($envelope);
|
||||
if ($ok) {
|
||||
print "OK\n\n";
|
||||
} else {
|
||||
print "FAIL\n\n";
|
||||
}
|
||||
|
||||
if (have_option('--verify')) {
|
||||
$url = 'http://www.madebymonsieur.com/ostatus_discovery/magic_env/validate/';
|
||||
echo "== Testing remote verification ==\n\n";
|
||||
print "Sending for verification to $url ...\n";
|
||||
|
||||
$client = new HTTPClient();
|
||||
$response = $client->post($url, array(), array('magic_env' => $envelope));
|
||||
|
||||
print $response->getStatus() . "\n\n";
|
||||
print $response->getBody() . "\n\n";
|
||||
}
|
||||
|
||||
if (have_option('--slap')) {
|
||||
$url = get_option_value('--slap');
|
||||
echo "== Remote salmon slap ==\n\n";
|
||||
print "Sending signed Salmon slap to $url ...\n";
|
||||
|
||||
$ok = $salmon->post($url, $entry, $profile);
|
||||
if ($ok) {
|
||||
print "OK\n\n";
|
||||
} else {
|
||||
print "FAIL\n\n";
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user