From 0c2134f9ad323bdf3630eebe7c96e43e677a1505 Mon Sep 17 00:00:00 2001 From: Mikael Nordfeldth Date: Sat, 31 May 2014 11:29:55 +0200 Subject: [PATCH] Last objectification of MagicEnvelope. Smarter SalmonAction --- plugins/OStatus/lib/magicenvelope.php | 84 +++++++++++++-------------- plugins/OStatus/lib/salmonaction.php | 20 ++----- 2 files changed, 46 insertions(+), 58 deletions(-) diff --git a/plugins/OStatus/lib/magicenvelope.php b/plugins/OStatus/lib/magicenvelope.php index b49a8b4d3a..9990053904 100644 --- a/plugins/OStatus/lib/magicenvelope.php +++ b/plugins/OStatus/lib/magicenvelope.php @@ -162,63 +162,64 @@ class MagicEnvelope return $string; } - /** + /* * Extract the contained XML payload, and insert a copy of the envelope * signature data as an 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 */ - public function unfold() + public function getPayload() { $dom = new DOMDocument(); - $dom->loadXML(Magicsig::base64_url_decode($this->data)); - - if ($dom->documentElement->tagName != 'entry') { - return false; + if (!$dom->loadXML(Magicsig::base64_url_decode($this->data))) { + throw new ServerException('Malformed XML in Salmon payload'); } - $prov = $dom->createElementNS(self::NS, 'me:provenance'); - $prov->setAttribute('xmlns:me', self::NS); - $data = $dom->createElementNS(self::NS, 'me:data', $this->data); - $data->setAttribute('type', $this->data_type); - $prov->appendChild($data); - $enc = $dom->createElementNS(self::NS, 'me:encoding', $this->encoding); - $prov->appendChild($enc); - $alg = $dom->createElementNS(self::NS, 'me:alg', $this->alg); - $prov->appendChild($alg); - $sig = $dom->createElementNS(self::NS, 'me:sig', $this->sig); - $prov->appendChild($sig); - - $dom->documentElement->appendChild($prov); - - return $dom->saveXML(); + switch ($this->data_type) { + case 'application/atom+xml': + if ($dom->documentElement->namespaceURI !== Activity::ATOM + || $dom->documentElement->tagName !== 'entry') { + throw new ServerException(_m('Salmon post must be an Atom entry.')); + } + $prov = $dom->createElementNS(self::NS, 'me:provenance'); + $prov->setAttribute('xmlns:me', self::NS); + $data = $dom->createElementNS(self::NS, 'me:data', $this->data); + $data->setAttribute('type', $this->data_type); + $prov->appendChild($data); + $enc = $dom->createElementNS(self::NS, 'me:encoding', $this->encoding); + $prov->appendChild($enc); + $alg = $dom->createElementNS(self::NS, 'me:alg', $this->alg); + $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 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 + * @return string URI for author + * @throws ServerException on failure */ - public function getAuthorUri($text) { - $doc = new DOMDocument(); - if (!$doc->loadXML($text)) { - return FALSE; - } + public function getAuthorUri() { + $doc = $this->getPayload(); - if ($doc->documentElement->tagName == 'entry') { - $authors = $doc->documentElement->getElementsByTagName('author'); - foreach ($authors as $author) { - $uris = $author->getElementsByTagName('uri'); - foreach ($uris as $uri) { - return $uri->nodeValue; - } + $authors = $doc->documentElement->getElementsByTagName('author'); + foreach ($authors as $author) { + $uris = $author->getElementsByTagName('uri'); + foreach ($uris as $uri) { + return $uri->nodeValue; } } + throw new ServerException('No author URI found in Salmon payload data'); } /** @@ -241,11 +242,8 @@ class MagicEnvelope 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 { + $signer_uri = $this->getAuthorUri(); $magicsig = $this->getKeyPair($signer_uri); } catch (Exception $e) { common_log(LOG_DEBUG, "Salmon error: ".$e->getMessage()); diff --git a/plugins/OStatus/lib/salmonaction.php b/plugins/OStatus/lib/salmonaction.php index dcd7f00fd1..4366822ffd 100644 --- a/plugins/OStatus/lib/salmonaction.php +++ b/plugins/OStatus/lib/salmonaction.php @@ -26,6 +26,8 @@ if (!defined('GNUSOCIAL')) { exit(1); } class SalmonAction extends Action { + protected $needPost = true; + var $xml = null; var $activity = null; var $target = null; @@ -36,12 +38,7 @@ class SalmonAction extends Action parent::prepare($args); - if ($_SERVER['REQUEST_METHOD'] != 'POST') { - // 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') { + if (!isset($_SERVER['CONTENT_TYPE']) || $_SERVER['CONTENT_TYPE'] != 'application/magic-envelope+xml') { // TRANS: Client error. Do not translate "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.')); } - $xml = $magic_env->unfold(); // return the enveloped XML (the actual data) - $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.')); - } + $entry = $magic_env->getPayload(); - $this->activity = new Activity($dom->documentElement); + $this->activity = new Activity($entry->documentElement); return true; }