Message.php 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921
  1. <?php
  2. /**
  3. * Extension argument processing code
  4. *
  5. * @package OpenID
  6. */
  7. /**
  8. * Import tools needed to deal with messages.
  9. */
  10. require_once 'Auth/OpenID.php';
  11. require_once 'Auth/OpenID/KVForm.php';
  12. require_once 'Auth/Yadis/XML.php';
  13. require_once 'Auth/OpenID/Consumer.php'; // For Auth_OpenID_FailureResponse
  14. // This doesn't REALLY belong here, but where is better?
  15. define('Auth_OpenID_IDENTIFIER_SELECT',
  16. "http://specs.openid.net/auth/2.0/identifier_select");
  17. // URI for Simple Registration extension, the only commonly deployed
  18. // OpenID 1.x extension, and so a special case
  19. define('Auth_OpenID_SREG_URI', 'http://openid.net/sreg/1.0');
  20. // The OpenID 1.X namespace URI
  21. define('Auth_OpenID_OPENID1_NS', 'http://openid.net/signon/1.0');
  22. define('Auth_OpenID_THE_OTHER_OPENID1_NS', 'http://openid.net/signon/1.1');
  23. function Auth_OpenID_isOpenID1($ns)
  24. {
  25. return ($ns == Auth_OpenID_THE_OTHER_OPENID1_NS) ||
  26. ($ns == Auth_OpenID_OPENID1_NS);
  27. }
  28. // The OpenID 2.0 namespace URI
  29. define('Auth_OpenID_OPENID2_NS', 'http://specs.openid.net/auth/2.0');
  30. // The namespace consisting of pairs with keys that are prefixed with
  31. // "openid." but not in another namespace.
  32. define('Auth_OpenID_NULL_NAMESPACE', 'Null namespace');
  33. // The null namespace, when it is an allowed OpenID namespace
  34. define('Auth_OpenID_OPENID_NS', 'OpenID namespace');
  35. // The top-level namespace, excluding all pairs with keys that start
  36. // with "openid."
  37. define('Auth_OpenID_BARE_NS', 'Bare namespace');
  38. // Sentinel for Message implementation to indicate that getArg should
  39. // return null instead of returning a default.
  40. define('Auth_OpenID_NO_DEFAULT', 'NO DEFAULT ALLOWED');
  41. // Limit, in bytes, of identity provider and return_to URLs, including
  42. // response payload. See OpenID 1.1 specification, Appendix D.
  43. define('Auth_OpenID_OPENID1_URL_LIMIT', 2047);
  44. // All OpenID protocol fields. Used to check namespace aliases.
  45. global $Auth_OpenID_OPENID_PROTOCOL_FIELDS;
  46. $Auth_OpenID_OPENID_PROTOCOL_FIELDS = array(
  47. 'ns', 'mode', 'error', 'return_to', 'contact', 'reference',
  48. 'signed', 'assoc_type', 'session_type', 'dh_modulus', 'dh_gen',
  49. 'dh_consumer_public', 'claimed_id', 'identity', 'realm',
  50. 'invalidate_handle', 'op_endpoint', 'response_nonce', 'sig',
  51. 'assoc_handle', 'trust_root', 'openid');
  52. // Global namespace / alias registration map. See
  53. // Auth_OpenID_registerNamespaceAlias.
  54. global $Auth_OpenID_registered_aliases;
  55. $Auth_OpenID_registered_aliases = array();
  56. /**
  57. * Registers a (namespace URI, alias) mapping in a global namespace
  58. * alias map. Raises NamespaceAliasRegistrationError if either the
  59. * namespace URI or alias has already been registered with a different
  60. * value. This function is required if you want to use a namespace
  61. * with an OpenID 1 message.
  62. */
  63. function Auth_OpenID_registerNamespaceAlias($namespace_uri, $alias)
  64. {
  65. global $Auth_OpenID_registered_aliases;
  66. if (Auth_OpenID::arrayGet($Auth_OpenID_registered_aliases,
  67. $alias) == $namespace_uri) {
  68. return true;
  69. }
  70. if (in_array($namespace_uri,
  71. array_values($Auth_OpenID_registered_aliases))) {
  72. return false;
  73. }
  74. if (in_array($alias, array_keys($Auth_OpenID_registered_aliases))) {
  75. return false;
  76. }
  77. $Auth_OpenID_registered_aliases[$alias] = $namespace_uri;
  78. return true;
  79. }
  80. /**
  81. * Removes a (namespace_uri, alias) registration from the global
  82. * namespace alias map. Returns true if the removal succeeded; false
  83. * if not (if the mapping did not exist).
  84. */
  85. function Auth_OpenID_removeNamespaceAlias($namespace_uri, $alias)
  86. {
  87. global $Auth_OpenID_registered_aliases;
  88. if (Auth_OpenID::arrayGet($Auth_OpenID_registered_aliases,
  89. $alias) === $namespace_uri) {
  90. unset($Auth_OpenID_registered_aliases[$alias]);
  91. return true;
  92. }
  93. return false;
  94. }
  95. /**
  96. * An Auth_OpenID_Mapping maintains a mapping from arbitrary keys to
  97. * arbitrary values. (This is unlike an ordinary PHP array, whose
  98. * keys may be only simple scalars.)
  99. *
  100. * @package OpenID
  101. */
  102. class Auth_OpenID_Mapping {
  103. /**
  104. * Initialize a mapping. If $classic_array is specified, its keys
  105. * and values are used to populate the mapping.
  106. */
  107. function Auth_OpenID_Mapping($classic_array = null)
  108. {
  109. $this->keys = array();
  110. $this->values = array();
  111. if (is_array($classic_array)) {
  112. foreach ($classic_array as $key => $value) {
  113. $this->set($key, $value);
  114. }
  115. }
  116. }
  117. /**
  118. * Returns true if $thing is an Auth_OpenID_Mapping object; false
  119. * if not.
  120. */
  121. static function isA($thing)
  122. {
  123. return (is_object($thing) &&
  124. strtolower(get_class($thing)) == 'auth_openid_mapping');
  125. }
  126. /**
  127. * Returns an array of the keys in the mapping.
  128. */
  129. function keys()
  130. {
  131. return $this->keys;
  132. }
  133. /**
  134. * Returns an array of values in the mapping.
  135. */
  136. function values()
  137. {
  138. return $this->values;
  139. }
  140. /**
  141. * Returns an array of (key, value) pairs in the mapping.
  142. */
  143. function items()
  144. {
  145. $temp = array();
  146. for ($i = 0; $i < count($this->keys); $i++) {
  147. $temp[] = array($this->keys[$i],
  148. $this->values[$i]);
  149. }
  150. return $temp;
  151. }
  152. /**
  153. * Returns the "length" of the mapping, or the number of keys.
  154. */
  155. function len()
  156. {
  157. return count($this->keys);
  158. }
  159. /**
  160. * Sets a key-value pair in the mapping. If the key already
  161. * exists, its value is replaced with the new value.
  162. */
  163. function set($key, $value)
  164. {
  165. $index = array_search($key, $this->keys);
  166. if ($index !== false) {
  167. $this->values[$index] = $value;
  168. } else {
  169. $this->keys[] = $key;
  170. $this->values[] = $value;
  171. }
  172. }
  173. /**
  174. * Gets a specified value from the mapping, associated with the
  175. * specified key. If the key does not exist in the mapping,
  176. * $default is returned instead.
  177. */
  178. function get($key, $default = null)
  179. {
  180. $index = array_search($key, $this->keys);
  181. if ($index !== false) {
  182. return $this->values[$index];
  183. } else {
  184. return $default;
  185. }
  186. }
  187. /**
  188. * @access private
  189. */
  190. function _reflow()
  191. {
  192. // PHP is broken yet again. Sort the arrays to remove the
  193. // hole in the numeric indexes that make up the array.
  194. $old_keys = $this->keys;
  195. $old_values = $this->values;
  196. $this->keys = array();
  197. $this->values = array();
  198. foreach ($old_keys as $k) {
  199. $this->keys[] = $k;
  200. }
  201. foreach ($old_values as $v) {
  202. $this->values[] = $v;
  203. }
  204. }
  205. /**
  206. * Deletes a key-value pair from the mapping with the specified
  207. * key.
  208. */
  209. function del($key)
  210. {
  211. $index = array_search($key, $this->keys);
  212. if ($index !== false) {
  213. unset($this->keys[$index]);
  214. unset($this->values[$index]);
  215. $this->_reflow();
  216. return true;
  217. }
  218. return false;
  219. }
  220. /**
  221. * Returns true if the specified value has a key in the mapping;
  222. * false if not.
  223. */
  224. function contains($value)
  225. {
  226. return (array_search($value, $this->keys) !== false);
  227. }
  228. }
  229. /**
  230. * Maintains a bijective map between namespace uris and aliases.
  231. *
  232. * @package OpenID
  233. */
  234. class Auth_OpenID_NamespaceMap {
  235. function Auth_OpenID_NamespaceMap()
  236. {
  237. $this->alias_to_namespace = new Auth_OpenID_Mapping();
  238. $this->namespace_to_alias = new Auth_OpenID_Mapping();
  239. $this->implicit_namespaces = array();
  240. }
  241. function getAlias($namespace_uri)
  242. {
  243. return $this->namespace_to_alias->get($namespace_uri);
  244. }
  245. function getNamespaceURI($alias)
  246. {
  247. return $this->alias_to_namespace->get($alias);
  248. }
  249. function iterNamespaceURIs()
  250. {
  251. // Return an iterator over the namespace URIs
  252. return $this->namespace_to_alias->keys();
  253. }
  254. function iterAliases()
  255. {
  256. // Return an iterator over the aliases"""
  257. return $this->alias_to_namespace->keys();
  258. }
  259. function iteritems()
  260. {
  261. return $this->namespace_to_alias->items();
  262. }
  263. function isImplicit($namespace_uri)
  264. {
  265. return in_array($namespace_uri, $this->implicit_namespaces);
  266. }
  267. function addAlias($namespace_uri, $desired_alias, $implicit=false)
  268. {
  269. // Add an alias from this namespace URI to the desired alias
  270. global $Auth_OpenID_OPENID_PROTOCOL_FIELDS;
  271. // Check that desired_alias is not an openid protocol field as
  272. // per the spec.
  273. if (in_array($desired_alias, $Auth_OpenID_OPENID_PROTOCOL_FIELDS)) {
  274. Auth_OpenID::log("\"%s\" is not an allowed namespace alias",
  275. $desired_alias);
  276. return null;
  277. }
  278. // Check that desired_alias does not contain a period as per
  279. // the spec.
  280. if (strpos($desired_alias, '.') !== false) {
  281. Auth_OpenID::log('"%s" must not contain a dot', $desired_alias);
  282. return null;
  283. }
  284. // Check that there is not a namespace already defined for the
  285. // desired alias
  286. $current_namespace_uri =
  287. $this->alias_to_namespace->get($desired_alias);
  288. if (($current_namespace_uri !== null) &&
  289. ($current_namespace_uri != $namespace_uri)) {
  290. Auth_OpenID::log('Cannot map "%s" because previous mapping exists',
  291. $namespace_uri);
  292. return null;
  293. }
  294. // Check that there is not already a (different) alias for
  295. // this namespace URI
  296. $alias = $this->namespace_to_alias->get($namespace_uri);
  297. if (($alias !== null) && ($alias != $desired_alias)) {
  298. Auth_OpenID::log('Cannot map %s to alias %s. ' .
  299. 'It is already mapped to alias %s',
  300. $namespace_uri, $desired_alias, $alias);
  301. return null;
  302. }
  303. assert((Auth_OpenID_NULL_NAMESPACE === $desired_alias) ||
  304. is_string($desired_alias));
  305. $this->alias_to_namespace->set($desired_alias, $namespace_uri);
  306. $this->namespace_to_alias->set($namespace_uri, $desired_alias);
  307. if ($implicit) {
  308. array_push($this->implicit_namespaces, $namespace_uri);
  309. }
  310. return $desired_alias;
  311. }
  312. function add($namespace_uri)
  313. {
  314. // Add this namespace URI to the mapping, without caring what
  315. // alias it ends up with
  316. // See if this namespace is already mapped to an alias
  317. $alias = $this->namespace_to_alias->get($namespace_uri);
  318. if ($alias !== null) {
  319. return $alias;
  320. }
  321. // Fall back to generating a numerical alias
  322. $i = 0;
  323. while (1) {
  324. $alias = 'ext' . strval($i);
  325. if ($this->addAlias($namespace_uri, $alias) === null) {
  326. $i += 1;
  327. } else {
  328. return $alias;
  329. }
  330. }
  331. // Should NEVER be reached!
  332. return null;
  333. }
  334. function contains($namespace_uri)
  335. {
  336. return $this->isDefined($namespace_uri);
  337. }
  338. function isDefined($namespace_uri)
  339. {
  340. return $this->namespace_to_alias->contains($namespace_uri);
  341. }
  342. }
  343. /**
  344. * In the implementation of this object, null represents the global
  345. * namespace as well as a namespace with no key.
  346. *
  347. * @package OpenID
  348. */
  349. class Auth_OpenID_Message {
  350. function Auth_OpenID_Message($openid_namespace = null)
  351. {
  352. // Create an empty Message
  353. $this->allowed_openid_namespaces = array(
  354. Auth_OpenID_OPENID1_NS,
  355. Auth_OpenID_THE_OTHER_OPENID1_NS,
  356. Auth_OpenID_OPENID2_NS);
  357. $this->args = new Auth_OpenID_Mapping();
  358. $this->namespaces = new Auth_OpenID_NamespaceMap();
  359. if ($openid_namespace === null) {
  360. $this->_openid_ns_uri = null;
  361. } else {
  362. $implicit = Auth_OpenID_isOpenID1($openid_namespace);
  363. $this->setOpenIDNamespace($openid_namespace, $implicit);
  364. }
  365. }
  366. function isOpenID1()
  367. {
  368. return Auth_OpenID_isOpenID1($this->getOpenIDNamespace());
  369. }
  370. function isOpenID2()
  371. {
  372. return $this->getOpenIDNamespace() == Auth_OpenID_OPENID2_NS;
  373. }
  374. static function fromPostArgs($args)
  375. {
  376. // Construct a Message containing a set of POST arguments
  377. $obj = new Auth_OpenID_Message();
  378. // Partition into "openid." args and bare args
  379. $openid_args = array();
  380. foreach ($args as $key => $value) {
  381. if (is_array($value)) {
  382. return null;
  383. }
  384. $parts = explode('.', $key, 2);
  385. if (count($parts) == 2) {
  386. list($prefix, $rest) = $parts;
  387. } else {
  388. $prefix = null;
  389. }
  390. if ($prefix != 'openid') {
  391. $obj->args->set(array(Auth_OpenID_BARE_NS, $key), $value);
  392. } else {
  393. $openid_args[$rest] = $value;
  394. }
  395. }
  396. if ($obj->_fromOpenIDArgs($openid_args)) {
  397. return $obj;
  398. } else {
  399. return null;
  400. }
  401. }
  402. static function fromOpenIDArgs($openid_args)
  403. {
  404. // Takes an array.
  405. // Construct a Message from a parsed KVForm message
  406. $obj = new Auth_OpenID_Message();
  407. if ($obj->_fromOpenIDArgs($openid_args)) {
  408. return $obj;
  409. } else {
  410. return null;
  411. }
  412. }
  413. /**
  414. * @access private
  415. */
  416. function _fromOpenIDArgs($openid_args)
  417. {
  418. global $Auth_OpenID_registered_aliases;
  419. // Takes an Auth_OpenID_Mapping instance OR an array.
  420. if (!Auth_OpenID_Mapping::isA($openid_args)) {
  421. $openid_args = new Auth_OpenID_Mapping($openid_args);
  422. }
  423. $ns_args = array();
  424. // Resolve namespaces
  425. foreach ($openid_args->items() as $pair) {
  426. list($rest, $value) = $pair;
  427. $parts = explode('.', $rest, 2);
  428. if (count($parts) == 2) {
  429. list($ns_alias, $ns_key) = $parts;
  430. } else {
  431. $ns_alias = Auth_OpenID_NULL_NAMESPACE;
  432. $ns_key = $rest;
  433. }
  434. if ($ns_alias == 'ns') {
  435. if ($this->namespaces->addAlias($value, $ns_key) === null) {
  436. return false;
  437. }
  438. } else if (($ns_alias == Auth_OpenID_NULL_NAMESPACE) &&
  439. ($ns_key == 'ns')) {
  440. // null namespace
  441. if ($this->setOpenIDNamespace($value, false) === false) {
  442. return false;
  443. }
  444. } else {
  445. $ns_args[] = array($ns_alias, $ns_key, $value);
  446. }
  447. }
  448. if (!$this->getOpenIDNamespace()) {
  449. if ($this->setOpenIDNamespace(Auth_OpenID_OPENID1_NS, true) ===
  450. false) {
  451. return false;
  452. }
  453. }
  454. // Actually put the pairs into the appropriate namespaces
  455. foreach ($ns_args as $triple) {
  456. list($ns_alias, $ns_key, $value) = $triple;
  457. $ns_uri = $this->namespaces->getNamespaceURI($ns_alias);
  458. if ($ns_uri === null) {
  459. $ns_uri = $this->_getDefaultNamespace($ns_alias);
  460. if ($ns_uri === null) {
  461. $ns_uri = Auth_OpenID_OPENID_NS;
  462. $ns_key = sprintf('%s.%s', $ns_alias, $ns_key);
  463. } else {
  464. $this->namespaces->addAlias($ns_uri, $ns_alias, true);
  465. }
  466. }
  467. $this->setArg($ns_uri, $ns_key, $value);
  468. }
  469. return true;
  470. }
  471. function _getDefaultNamespace($mystery_alias)
  472. {
  473. global $Auth_OpenID_registered_aliases;
  474. if ($this->isOpenID1()) {
  475. return @$Auth_OpenID_registered_aliases[$mystery_alias];
  476. }
  477. return null;
  478. }
  479. function setOpenIDNamespace($openid_ns_uri, $implicit)
  480. {
  481. if (!in_array($openid_ns_uri, $this->allowed_openid_namespaces)) {
  482. Auth_OpenID::log('Invalid null namespace: "%s"', $openid_ns_uri);
  483. return false;
  484. }
  485. $succeeded = $this->namespaces->addAlias($openid_ns_uri,
  486. Auth_OpenID_NULL_NAMESPACE,
  487. $implicit);
  488. if ($succeeded === false) {
  489. return false;
  490. }
  491. $this->_openid_ns_uri = $openid_ns_uri;
  492. return true;
  493. }
  494. function getOpenIDNamespace()
  495. {
  496. return $this->_openid_ns_uri;
  497. }
  498. static function fromKVForm($kvform_string)
  499. {
  500. // Create a Message from a KVForm string
  501. return Auth_OpenID_Message::fromOpenIDArgs(
  502. Auth_OpenID_KVForm::toArray($kvform_string));
  503. }
  504. function copy()
  505. {
  506. return $this;
  507. }
  508. function toPostArgs()
  509. {
  510. // Return all arguments with openid. in front of namespaced
  511. // arguments.
  512. $args = array();
  513. // Add namespace definitions to the output
  514. foreach ($this->namespaces->iteritems() as $pair) {
  515. list($ns_uri, $alias) = $pair;
  516. if ($this->namespaces->isImplicit($ns_uri)) {
  517. continue;
  518. }
  519. if ($alias == Auth_OpenID_NULL_NAMESPACE) {
  520. $ns_key = 'openid.ns';
  521. } else {
  522. $ns_key = 'openid.ns.' . $alias;
  523. }
  524. $args[$ns_key] = $ns_uri;
  525. }
  526. foreach ($this->args->items() as $pair) {
  527. list($ns_parts, $value) = $pair;
  528. list($ns_uri, $ns_key) = $ns_parts;
  529. $key = $this->getKey($ns_uri, $ns_key);
  530. $args[$key] = $value;
  531. }
  532. return $args;
  533. }
  534. function toArgs()
  535. {
  536. // Return all namespaced arguments, failing if any
  537. // non-namespaced arguments exist.
  538. $post_args = $this->toPostArgs();
  539. $kvargs = array();
  540. foreach ($post_args as $k => $v) {
  541. if (strpos($k, 'openid.') !== 0) {
  542. // raise ValueError(
  543. // 'This message can only be encoded as a POST, because it '
  544. // 'contains arguments that are not prefixed with "openid."')
  545. return null;
  546. } else {
  547. $kvargs[substr($k, 7)] = $v;
  548. }
  549. }
  550. return $kvargs;
  551. }
  552. function toFormMarkup($action_url, $form_tag_attrs = null,
  553. $submit_text = "Continue")
  554. {
  555. $form = "<form accept-charset=\"UTF-8\" ".
  556. "enctype=\"application/x-www-form-urlencoded\"";
  557. if (!$form_tag_attrs) {
  558. $form_tag_attrs = array();
  559. }
  560. $form_tag_attrs['action'] = $action_url;
  561. $form_tag_attrs['method'] = 'post';
  562. unset($form_tag_attrs['enctype']);
  563. unset($form_tag_attrs['accept-charset']);
  564. if ($form_tag_attrs) {
  565. foreach ($form_tag_attrs as $name => $attr) {
  566. $form .= sprintf(" %s=\"%s\"", $name, htmlspecialchars($attr));
  567. }
  568. }
  569. $form .= ">\n";
  570. foreach ($this->toPostArgs() as $name => $value) {
  571. $form .= sprintf(
  572. "<input type=\"hidden\" name=\"%s\" value=\"%s\" />\n",
  573. htmlspecialchars($name), htmlspecialchars($value));
  574. }
  575. $form .= sprintf("<input type=\"submit\" value=\"%s\" />\n",
  576. htmlspecialchars($submit_text));
  577. $form .= "</form>\n";
  578. return $form;
  579. }
  580. function toURL($base_url)
  581. {
  582. // Generate a GET URL with the parameters in this message
  583. // attached as query parameters.
  584. return Auth_OpenID::appendArgs($base_url, $this->toPostArgs());
  585. }
  586. function toKVForm()
  587. {
  588. // Generate a KVForm string that contains the parameters in
  589. // this message. This will fail if the message contains
  590. // arguments outside of the 'openid.' prefix.
  591. return Auth_OpenID_KVForm::fromArray($this->toArgs());
  592. }
  593. function toURLEncoded()
  594. {
  595. // Generate an x-www-urlencoded string
  596. $args = array();
  597. foreach ($this->toPostArgs() as $k => $v) {
  598. $args[] = array($k, $v);
  599. }
  600. sort($args);
  601. return Auth_OpenID::httpBuildQuery($args);
  602. }
  603. /**
  604. * @access private
  605. */
  606. function _fixNS($namespace)
  607. {
  608. // Convert an input value into the internally used values of
  609. // this object
  610. if ($namespace == Auth_OpenID_OPENID_NS) {
  611. if ($this->_openid_ns_uri === null) {
  612. return new Auth_OpenID_FailureResponse(null,
  613. 'OpenID namespace not set');
  614. } else {
  615. $namespace = $this->_openid_ns_uri;
  616. }
  617. }
  618. if (($namespace != Auth_OpenID_BARE_NS) &&
  619. (!is_string($namespace))) {
  620. //TypeError
  621. $err_msg = sprintf("Namespace must be Auth_OpenID_BARE_NS, ".
  622. "Auth_OpenID_OPENID_NS or a string. got %s",
  623. print_r($namespace, true));
  624. return new Auth_OpenID_FailureResponse(null, $err_msg);
  625. }
  626. if (($namespace != Auth_OpenID_BARE_NS) &&
  627. (strpos($namespace, ':') === false)) {
  628. // fmt = 'OpenID 2.0 namespace identifiers SHOULD be URIs. Got %r'
  629. // warnings.warn(fmt % (namespace,), DeprecationWarning)
  630. if ($namespace == 'sreg') {
  631. // fmt = 'Using %r instead of "sreg" as namespace'
  632. // warnings.warn(fmt % (SREG_URI,), DeprecationWarning,)
  633. return Auth_OpenID_SREG_URI;
  634. }
  635. }
  636. return $namespace;
  637. }
  638. function hasKey($namespace, $ns_key)
  639. {
  640. $namespace = $this->_fixNS($namespace);
  641. if (Auth_OpenID::isFailure($namespace)) {
  642. // XXX log me
  643. return false;
  644. } else {
  645. return $this->args->contains(array($namespace, $ns_key));
  646. }
  647. }
  648. function getKey($namespace, $ns_key)
  649. {
  650. // Get the key for a particular namespaced argument
  651. $namespace = $this->_fixNS($namespace);
  652. if (Auth_OpenID::isFailure($namespace)) {
  653. return $namespace;
  654. }
  655. if ($namespace == Auth_OpenID_BARE_NS) {
  656. return $ns_key;
  657. }
  658. $ns_alias = $this->namespaces->getAlias($namespace);
  659. // No alias is defined, so no key can exist
  660. if ($ns_alias === null) {
  661. return null;
  662. }
  663. if ($ns_alias == Auth_OpenID_NULL_NAMESPACE) {
  664. $tail = $ns_key;
  665. } else {
  666. $tail = sprintf('%s.%s', $ns_alias, $ns_key);
  667. }
  668. return 'openid.' . $tail;
  669. }
  670. function getArg($namespace, $key, $default = null)
  671. {
  672. // Get a value for a namespaced key.
  673. $namespace = $this->_fixNS($namespace);
  674. if (Auth_OpenID::isFailure($namespace)) {
  675. return $namespace;
  676. } else {
  677. if ((!$this->args->contains(array($namespace, $key))) &&
  678. ($default == Auth_OpenID_NO_DEFAULT)) {
  679. $err_msg = sprintf("Namespace %s missing required field %s",
  680. $namespace, $key);
  681. return new Auth_OpenID_FailureResponse(null, $err_msg);
  682. } else {
  683. return $this->args->get(array($namespace, $key), $default);
  684. }
  685. }
  686. }
  687. function getArgs($namespace)
  688. {
  689. // Get the arguments that are defined for this namespace URI
  690. $namespace = $this->_fixNS($namespace);
  691. if (Auth_OpenID::isFailure($namespace)) {
  692. return $namespace;
  693. } else {
  694. $stuff = array();
  695. foreach ($this->args->items() as $pair) {
  696. list($key, $value) = $pair;
  697. list($pair_ns, $ns_key) = $key;
  698. if ($pair_ns == $namespace) {
  699. $stuff[$ns_key] = $value;
  700. }
  701. }
  702. return $stuff;
  703. }
  704. }
  705. function updateArgs($namespace, $updates)
  706. {
  707. // Set multiple key/value pairs in one call
  708. $namespace = $this->_fixNS($namespace);
  709. if (Auth_OpenID::isFailure($namespace)) {
  710. return $namespace;
  711. } else {
  712. foreach ($updates as $k => $v) {
  713. $this->setArg($namespace, $k, $v);
  714. }
  715. return true;
  716. }
  717. }
  718. function setArg($namespace, $key, $value)
  719. {
  720. // Set a single argument in this namespace
  721. $namespace = $this->_fixNS($namespace);
  722. if (Auth_OpenID::isFailure($namespace)) {
  723. return $namespace;
  724. } else {
  725. $this->args->set(array($namespace, $key), $value);
  726. if ($namespace !== Auth_OpenID_BARE_NS) {
  727. $this->namespaces->add($namespace);
  728. }
  729. return true;
  730. }
  731. }
  732. function delArg($namespace, $key)
  733. {
  734. $namespace = $this->_fixNS($namespace);
  735. if (Auth_OpenID::isFailure($namespace)) {
  736. return $namespace;
  737. } else {
  738. return $this->args->del(array($namespace, $key));
  739. }
  740. }
  741. function getAliasedArg($aliased_key, $default = null)
  742. {
  743. if ($aliased_key == 'ns') {
  744. // Return the namespace URI for the OpenID namespace
  745. return $this->getOpenIDNamespace();
  746. }
  747. $parts = explode('.', $aliased_key, 2);
  748. if (count($parts) != 2) {
  749. $ns = null;
  750. } else {
  751. list($alias, $key) = $parts;
  752. if ($alias == 'ns') {
  753. // Return the namespace URI for a namespace alias
  754. // parameter.
  755. return $this->namespaces->getNamespaceURI($key);
  756. } else {
  757. $ns = $this->namespaces->getNamespaceURI($alias);
  758. }
  759. }
  760. if ($ns === null) {
  761. $key = $aliased_key;
  762. $ns = $this->getOpenIDNamespace();
  763. }
  764. return $this->getArg($ns, $key, $default);
  765. }
  766. }