Last objectification of MagicEnvelope. Smarter SalmonAction

This commit is contained in:
Mikael Nordfeldth 2014-05-31 11:29:55 +02:00
parent 120e5c685a
commit 0c2134f9ad
2 changed files with 46 additions and 58 deletions

View File

@ -162,63 +162,64 @@ class MagicEnvelope
return $string; return $string;
} }
/** /*
* Extract the contained XML payload, and insert a copy of the envelope * Extract the contained XML payload, and insert a copy of the envelope
* signature data as an <me:provenance> section. * signature data as an <me:provenance> section.
* *
* @return string representation of modified XML document * @return DOMDocument of Atom entry
* *
* @fixme in case of XML parsing errors, this will spew to the error log or output * @fixme in case of XML parsing errors, this will spew to the error log or output
*/ */
public function unfold() public function getPayload()
{ {
$dom = new DOMDocument(); $dom = new DOMDocument();
$dom->loadXML(Magicsig::base64_url_decode($this->data)); if (!$dom->loadXML(Magicsig::base64_url_decode($this->data))) {
throw new ServerException('Malformed XML in Salmon payload');
if ($dom->documentElement->tagName != 'entry') {
return false;
} }
$prov = $dom->createElementNS(self::NS, 'me:provenance'); switch ($this->data_type) {
$prov->setAttribute('xmlns:me', self::NS); case 'application/atom+xml':
$data = $dom->createElementNS(self::NS, 'me:data', $this->data); if ($dom->documentElement->namespaceURI !== Activity::ATOM
$data->setAttribute('type', $this->data_type); || $dom->documentElement->tagName !== 'entry') {
$prov->appendChild($data); throw new ServerException(_m('Salmon post must be an Atom entry.'));
$enc = $dom->createElementNS(self::NS, 'me:encoding', $this->encoding); }
$prov->appendChild($enc); $prov = $dom->createElementNS(self::NS, 'me:provenance');
$alg = $dom->createElementNS(self::NS, 'me:alg', $this->alg); $prov->setAttribute('xmlns:me', self::NS);
$prov->appendChild($alg); $data = $dom->createElementNS(self::NS, 'me:data', $this->data);
$sig = $dom->createElementNS(self::NS, 'me:sig', $this->sig); $data->setAttribute('type', $this->data_type);
$prov->appendChild($sig); $prov->appendChild($data);
$enc = $dom->createElementNS(self::NS, 'me:encoding', $this->encoding);
$dom->documentElement->appendChild($prov); $prov->appendChild($enc);
$alg = $dom->createElementNS(self::NS, 'me:alg', $this->alg);
return $dom->saveXML(); $prov->appendChild($alg);
$sig = $dom->createElementNS(self::NS, 'me:sig', $this->sig);
$prov->appendChild($sig);
$dom->documentElement->appendChild($prov);
break;
default:
throw new ServerException('Unknown Salmon payload data type');
}
return $dom;
} }
/** /**
* Find the author URI referenced in the given Atom entry. * Find the author URI referenced in the payload Atom entry.
* *
* @param string $text string containing Atom entry XML * @return string URI for author
* @return mixed URI string or false if XML parsing fails, or null if no author URI can be found * @throws ServerException on failure
*
* @fixme XML parsing failures will spew to error logs/output
*/ */
public function getAuthorUri($text) { public function getAuthorUri() {
$doc = new DOMDocument(); $doc = $this->getPayload();
if (!$doc->loadXML($text)) {
return FALSE;
}
if ($doc->documentElement->tagName == 'entry') { $authors = $doc->documentElement->getElementsByTagName('author');
$authors = $doc->documentElement->getElementsByTagName('author'); foreach ($authors as $author) {
foreach ($authors as $author) { $uris = $author->getElementsByTagName('uri');
$uris = $author->getElementsByTagName('uri'); foreach ($uris as $uri) {
foreach ($uris as $uri) { return $uri->nodeValue;
return $uri->nodeValue;
}
} }
} }
throw new ServerException('No author URI found in Salmon payload data');
} }
/** /**
@ -241,11 +242,8 @@ class MagicEnvelope
return false; return false;
} }
// $this->data is base64_url_encoded and should contain XML which is passed to getAuthorUri
$text = Magicsig::base64_url_decode($this->data);
$signer_uri = $this->getAuthorUri($text);
try { try {
$signer_uri = $this->getAuthorUri();
$magicsig = $this->getKeyPair($signer_uri); $magicsig = $this->getKeyPair($signer_uri);
} catch (Exception $e) { } catch (Exception $e) {
common_log(LOG_DEBUG, "Salmon error: ".$e->getMessage()); common_log(LOG_DEBUG, "Salmon error: ".$e->getMessage());

View File

@ -26,6 +26,8 @@ if (!defined('GNUSOCIAL')) { exit(1); }
class SalmonAction extends Action class SalmonAction extends Action
{ {
protected $needPost = true;
var $xml = null; var $xml = null;
var $activity = null; var $activity = null;
var $target = null; var $target = null;
@ -36,12 +38,7 @@ class SalmonAction extends Action
parent::prepare($args); parent::prepare($args);
if ($_SERVER['REQUEST_METHOD'] != 'POST') { if (!isset($_SERVER['CONTENT_TYPE']) || $_SERVER['CONTENT_TYPE'] != 'application/magic-envelope+xml') {
// TRANS: Client error. POST is a HTTP command. It should not be translated.
$this->clientError(_m('This method requires a POST.'));
}
if (empty($_SERVER['CONTENT_TYPE']) || $_SERVER['CONTENT_TYPE'] != 'application/magic-envelope+xml') {
// TRANS: Client error. Do not translate "application/magic-envelope+xml". // TRANS: Client error. Do not translate "application/magic-envelope+xml".
$this->clientError(_m('Salmon requires "application/magic-envelope+xml".')); $this->clientError(_m('Salmon requires "application/magic-envelope+xml".'));
} }
@ -54,16 +51,9 @@ class SalmonAction extends Action
$this->clientError(_m('Salmon signature verification failed.')); $this->clientError(_m('Salmon signature verification failed.'));
} }
$xml = $magic_env->unfold(); // return the enveloped XML (the actual data) $entry = $magic_env->getPayload();
$dom = DOMDocument::loadXML($xml);
if ($dom->documentElement->namespaceURI != Activity::ATOM ||
$dom->documentElement->localName != 'entry') {
common_log(LOG_DEBUG, "Got invalid Salmon post: $xml");
// TRANS: Client error.
$this->clientError(_m('Salmon post must be an Atom entry.'));
}
$this->activity = new Activity($dom->documentElement); $this->activity = new Activity($entry->documentElement);
return true; return true;
} }