<NME> TestDriver.php
<BEF> <?php

/**
 * A driver for the PHP OpenID unit tests.
 *
 * PHP versions 4 and 5
 *
 * LICENSE: See the COPYING file included in this distribution.
 *
 * @package OpenID
 * @author JanRain, Inc. <openid@janrain.com>
 * @copyright 2005-2008 Janrain, Inc.
 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
 */

require_once 'PHPUnit/Framework.php';
//require_once 'PHPUnit/GUI/HTML.php';

error_reporting(E_ALL | E_STRICT);

global $__test_errors;
$__test_errors = [];

function __handler($code, $message)
{
    global $__test_errors;

    if ($code == E_USER_WARNING) {
        $__test_errors[] = $message;
    }
}

function __raiseError($message)
{
    set_error_handler('__handler');
    trigger_error($message, E_USER_WARNING);
    restore_error_handler();
}

function __getError()
{
    global $__test_errors;
    if ($__test_errors) {
        return array_pop($__test_errors);
    }
    return null;
}

/**
 * Load the tests that are defined in the named modules.
 *
 * If you have Tests/Foo.php which defines a test class called
 * Tests_Foo, the call would look like:
 *
 * loadTests('Tests/', array('Foo'))
 *
 * @param string $test_dir The root of the test hierarchy. Must end
 * with a /
 *
 * @param array $test_names The names of the modules in which the
 * tests are defined. This should not include the root of the test
 * hierarchy.
 */
function loadTests($test_dir, $test_names)
{
    global $_tests;
    $suites = [];

    foreach ($test_names as $filename) {
        $filename = $test_dir . $filename . '.php';

        if (!global_require_once($filename)) {
            continue;
        }

        $class_name = str_replace('/', '_', $filename);
        $class_name = basename($class_name, '.php');

        $suites[] = makeSuite($class_name);
    }

    return $suites;
}

function makeSuite($class_name) {
    $test = new $class_name($class_name);

    if (is_a($test, 'PHPUnit_Framework_TestCase')) {
        $s = new PHPUnit_Framework_TestSuite();
        $s->setName($class_name);
        $s->addTestSuite($class_name);
        $test = $s;
    }

    $tc_array_name = $class_name . '_other';
    if (array_key_exists($tc_array_name, $GLOBALS) &&
        is_array($GLOBALS[$tc_array_name])) {

        foreach ($GLOBALS[$tc_array_name] as $tc) {
            $test->addTestSuite(get_class($tc));
        }
    }

    return $test;
}


function global_require_once($name)
{
    $f = include_once $name;
    if (!$f) {
        print("global require once skipping $name\n");
        return false;
    }
    foreach (get_defined_vars() as $k => $v) {
        if (!in_array($k, ['name', 'GLOBALS'])) {
            $GLOBALS[$k] = $v;
        }
    }
    return true;
}

$_tests = [
    [
        'dir' => 'Tests/Auth/OpenID/',
        'files' => [
            'Association',
            'AssociationResponse',
            'AuthRequest',
                                       'OpenID_Yadis',
                                       'Parse',
                                       'Server',
                                       'StoreTest',
                                       'TrustRoot',
                                       'URINorm',
            'HMAC',
            'KVForm',
            'Message',
            'Negotiation',
            'Nonce',
            'OpenID_Yadis',
            'PAPE',
            'Parse',
            'RPVerify',
            'Server',
            'SReg',
            'StoreTest',
            'TrustRoot',
            'URINorm',
            'Util',
            'VerifyDisco',
        ],
    ],
    [
        'dir' => 'Tests/Auth/Yadis/',
        'files' => [
            'ParseHTML',
            'XRDS',
            'Yadis',
            'Discover_Yadis',
            'XRI',
        ],
    ],
];

function selectTests($package, $names)
{
    global $_tests;
    $lnames = array_map('strtolower', $names);
    $include = [];
    $exclude = [];
    foreach ($package['files'] as $t) {
        $l = strtolower($t);
        if (in_array($l, $lnames)) {
            $include[] = $t;
        }

        if (in_array("/$l", $lnames)) {
            $exclude[] = $t;
        }
    }

    return array_diff($include, $exclude);
}

// Load OpenID library tests
function loadSuite($names=null)
{
    global $_tests;
    $result = [];
    foreach ($_tests as $package) {
        if (!$names) {
            $selected = $package['files'];
        } else {
            $selected = selectTests($package, $names);
        }
        $result = array_merge($result, loadTests($package['dir'], $selected));
    }

    return $result;
}


<MSG> [project @ Added new Sreg module, extension code, and tests]

<DFF> @@ -130,6 +130,7 @@ $_tests = array(
                                        'OpenID_Yadis',
                                        'Parse',
                                        'Server',
+                                       'SReg',
                                        'StoreTest',
                                        'TrustRoot',
                                        'URINorm',

{'commit': 'diff --git a/Auth/OpenID/Extension.php b/Auth/OpenID/Extension.php\nnew file mode 100644\nindex 0000000..6f943c2\n--- /dev/null\n+++ b/Auth/OpenID/Extension.php\n@@ -0,0 +1,47 @@\n+<?php\n+\n+/**\n+ * An interface for OpenID extensions.\n+ */\n+\n+require_once \'Auth/OpenID/Message.php\';\n+\n+class Auth_OpenID_Extension {\n+    /**\n+     * ns_uri: The namespace to which to add the arguments for this\n+     * extension\n+     */\n+    var $ns_uri = null;\n+    var $ns_alias = null;\n+\n+    /**\n+     * Get the string arguments that should be added to an OpenID\n+     * message for this extension.\n+     */\n+    function getExtensionArgs()\n+    {\n+        return null;\n+    }\n+\n+    /**\n+     * Add the arguments from this extension to the provided message.\n+     *\n+     * Returns the message with the extension arguments added.\n+     */\n+    function toMessage(&$message)\n+    {\n+        if ($message->namespaces->addAlias($this->ns_uri,\n+                                           $this->ns_alias) === null) {\n+            if ($message->namespaces->getAlias($this->ns_uri) !=\n+                $this->ns_alias) {\n+                return null;\n+            }\n+        }\n+\n+        $message->updateArgs($this->ns_uri,\n+                             $this->getExtensionArgs());\n+        return $message;\n+    }\n+}\n+\n+?>\n\\ No newline at end of file\ndiff --git a/Auth/OpenID/Message.php b/Auth/OpenID/Message.php\nindex a9a7d21..cdc4d65 100644\n--- a/Auth/OpenID/Message.php\n+++ b/Auth/OpenID/Message.php\n@@ -74,7 +74,7 @@ function Auth_OpenID_registerNamespaceAlias($namespace_uri, $alias)\n         return false;\n     }\n \n-    if (in_array($alias, $Auth_OpenID_registered_aliases)) {\n+    if (in_array($alias, array_keys($Auth_OpenID_registered_aliases))) {\n         return false;\n     }\n \n@@ -82,6 +82,24 @@ function Auth_OpenID_registerNamespaceAlias($namespace_uri, $alias)\n     return true;\n }\n \n+/**\n+ * Removes a (namespace_uri, alias) registration from the global\n+ * namespace alias map.  Returns true if the removal succeeded; false\n+ * if not (if the mapping did not exist).\n+ */\n+function Auth_OpenID_removeNamespaceAlias($namespace_uri, $alias)\n+{\n+    global $Auth_OpenID_registered_aliases;\n+\n+    if (Auth_OpenID::arrayGet($Auth_OpenID_registered_aliases,\n+                              $alias) === $namespace_uri) {\n+        unset($Auth_OpenID_registered_aliases[$alias]);\n+        return true;\n+    }\n+\n+    return false;\n+}\n+\n /**\n  * An Auth_OpenID_Mapping maintains a mapping from arbitrary keys to\n  * arbitrary values.  (This is unlike an ordinary PHP array, whose\ndiff --git a/Auth/OpenID/SReg.php b/Auth/OpenID/SReg.php\nnew file mode 100644\nindex 0000000..e7051e1\n--- /dev/null\n+++ b/Auth/OpenID/SReg.php\n@@ -0,0 +1,530 @@\n+<?php\n+\n+/**\n+ * Simple registration request and response parsing and object\n+ * representation\n+ *\n+ * This module contains objects representing simple registration\n+ * requests and responses that can be used with both OpenID relying\n+ * parties and OpenID providers.\n+ *\n+ * 1. The relying party creates a request object and adds it to the\n+ *    C{L{AuthRequest<openid.consumer.consumer.AuthRequest>}} object\n+ *    before making the C{checkid_} request to the OpenID provider::\n+ *\n+ *     auth_request.addExtension(SRegRequest(required=[\'email\']))\n+ *\n+ * 2. The OpenID provider extracts the simple registration request from\n+ *    the OpenID request using C{L{SRegRequest.fromOpenIDRequest}},\n+ *    gets the user\'s approval and data, creates a C{L{SRegResponse}}\n+ *    object and adds it to the C{id_res} response::\n+ *\n+ *    sreg_req = SRegRequest.fromOpenIDRequest(checkid_request.message)\n+ *    // [ get the user\'s approval and data, informing the user that\n+ *    //   the fields in sreg_response were requested ]\n+ *    sreg_resp = SRegResponse.extractResponse(sreg_req, user_data)\n+ *    sreg_resp.addToOpenIDResponse(openid_response)\n+ *\n+ * 3. The relying party uses C{L{SRegResponse.fromSuccessResponse}} to\n+ *    extract the data from the OpenID response::\n+ *\n+ *     sreg_resp = SRegResponse.fromSuccessResponse(success_response)\n+ */\n+\n+require_once \'Auth/OpenID/Message.php\';\n+require_once \'Auth/OpenID/Extension.php\';\n+\n+// The data fields that are listed in the sreg spec\n+global $Auth_OpenID_sreg_data_fields;\n+$Auth_OpenID_sreg_data_fields = array(\n+                                      \'fullname\' => \'Full Name\',\n+                                      \'nickname\' => \'Nickname\',\n+                                      \'dob\' => \'Date of Birth\',\n+                                      \'email\' => \'E-mail Address\',\n+                                      \'gender\' => \'Gender\',\n+                                      \'postcode\' => \'Postal Code\',\n+                                      \'country\' => \'Country\',\n+                                      \'language\' => \'Language\',\n+                                      \'timezone\' => \'Time Zone\');\n+\n+/**\n+ * Check to see that the given value is a valid simple registration\n+ * data field name.  Return true if so, false if not.\n+ */\n+function Auth_OpenID_checkFieldName($field_name)\n+{\n+    global $Auth_OpenID_sreg_data_fields;\n+\n+    if (!in_array($field_name, array_keys($Auth_OpenID_sreg_data_fields))) {\n+        return false;\n+    }\n+    return true;\n+}\n+\n+// URI used in the wild for Yadis documents advertising simple\n+// registration support\n+define(\'Auth_OpenID_SREG_NS_URI_1_0\', \'http://openid.net/sreg/1.0\');\n+\n+// URI in the draft specification for simple registration 1.1\n+// <http://openid.net/specs/openid-simple-registration-extension-1_1-01.html>\n+define(\'Auth_OpenID_SREG_NS_URI_1_1\', \'http://openid.net/extensions/sreg/1.1\');\n+\n+// This attribute will always hold the preferred URI to use when\n+// adding sreg support to an XRDS file or in an OpenID namespace\n+// declaration.\n+define(\'Auth_OpenID_SREG_NS_URI\', Auth_OpenID_SREG_NS_URI_1_1);\n+\n+Auth_OpenID_registerNamespaceAlias(Auth_OpenID_SREG_NS_URI_1_1, \'sreg\');\n+\n+/**\n+ * Does the given endpoint advertise support for simple\n+ * registration?\n+ *\n+ * $endpoint: The endpoint object as returned by OpenID discovery.\n+ * returns whether an sreg type was advertised by the endpoint\n+ */\n+function Auth_OpenID_supportsSReg($endpoint)\n+{\n+    return ($endpoint->usesExtension(Auth_OpenID_SREG_NS_URI_1_1) ||\n+            $endpoint->usesExtension(Auth_OpenID_SREG_NS_URI_1_0));\n+}\n+\n+class Auth_OpenID_SRegBase extends Auth_OpenID_Extension {\n+    /**\n+     * Extract the simple registration namespace URI from the given\n+     * OpenID message. Handles OpenID 1 and 2, as well as both sreg\n+     * namespace URIs found in the wild, as well as missing namespace\n+     * definitions (for OpenID 1)\n+     *\n+     * $message: The OpenID message from which to parse simple\n+     * registration fields. This may be a request or response message.\n+     *\n+     * Returns the sreg namespace URI for the supplied message. The\n+     * message may be modified to define a simple registration\n+     * namespace.\n+     */\n+    function _getSRegNS(&$message)\n+    {\n+        $alias = null;\n+        $found_ns_uri = null;\n+\n+        // See if there exists an alias for one of the two defined\n+        // simple registration types.\n+        foreach (array(Auth_OpenID_SREG_NS_URI_1_1,\n+                       Auth_OpenID_SREG_NS_URI_1_0) as $sreg_ns_uri) {\n+            $alias = $message->namespaces->getAlias($sreg_ns_uri);\n+            if ($alias !== null) {\n+                $found_ns_uri = $sreg_ns_uri;\n+                break;\n+            }\n+        }\n+\n+        if ($alias === null) {\n+            // There is no alias for either of the types, so try to\n+            // add one. We default to using the modern value (1.1)\n+            $found_ns_uri = Auth_OpenID_SREG_NS_URI_1_1;\n+            if ($message->namespaces->addAlias(Auth_OpenID_SREG_NS_URI_1_1,\n+                                               \'sreg\') === null) {\n+                // An alias for the string \'sreg\' already exists, but\n+                // it\'s defined for something other than simple\n+                // registration\n+                return null;\n+            }\n+        }\n+\n+        return $found_ns_uri;\n+    }\n+}\n+\n+/**\n+ * An object to hold the state of a simple registration request.\n+ *\n+ * required: A list of the required fields in this simple registration\n+ * request\n+ *\n+ * optional: A list of the optional fields in this simple registration\n+ * request\n+ *\n+ * @ivar policy_url: The policy URL that was provided with the request\n+ */\n+class Auth_OpenID_SRegRequest extends Auth_OpenID_SRegBase {\n+\n+    var $ns_alias = \'sreg\';\n+\n+    /**\n+     * Initialize an empty simple registration request\n+     */\n+    function build($required=null, $optional=null,\n+                   $policy_url=null,\n+                   $sreg_ns_uri=Auth_OpenID_SREG_NS_URI)\n+    {\n+        $obj = new Auth_OpenID_SRegRequest();\n+\n+        $obj->required = array();\n+        $obj->optional = array();\n+        $obj->policy_url = $policy_url;\n+        $obj->ns_uri = $sreg_ns_uri;\n+\n+        if ($required) {\n+            if (!$obj->requestFields($required, true, true)) {\n+                return null;\n+            }\n+        }\n+\n+        if ($optional) {\n+            if (!$obj->requestFields($optional, false, true)) {\n+                return null;\n+            }\n+        }\n+\n+        return $obj;\n+    }\n+\n+    /**\n+     * Create a simple registration request that contains the fields\n+     * that were requested in the OpenID request with the given\n+     * arguments\n+     *\n+     * $message: The arguments that were given for this OpenID\n+     * authentication request\n+     *\n+     * Returns the newly created simple registration request\n+     */\n+    function fromOpenIDRequest($message)\n+    {\n+        $obj = Auth_OpenID_SRegRequest::build();\n+\n+        // Since we\'re going to mess with namespace URI mapping, don\'t\n+        // mutate the object that was passed in.\n+        $m = $message;\n+\n+        $obj->ns_uri = $obj->_getSRegNS($m);\n+        $args = $m->getArgs($obj->ns_uri);\n+\n+        if ($args === null) {\n+            return null;\n+        }\n+\n+        $obj->parseExtensionArgs($args);\n+\n+        return $obj;\n+    }\n+\n+    /**\n+     * Parse the unqualified simple registration request parameters\n+     * and add them to this object.\n+     *\n+     * This method is essentially the inverse of\n+     * C{L{getExtensionArgs}}. This method restores the serialized\n+     * simple registration request fields.\n+     *\n+     * If you are extracting arguments from a standard OpenID\n+     * checkid_* request, you probably want to use\n+     * C{L{fromOpenIDRequest}}, which will extract the sreg namespace\n+     * and arguments from the OpenID request. This method is intended\n+     * for cases where the OpenID server needs more control over how\n+     * the arguments are parsed than that method provides.\n+     *\n+     * >>> args = message.getArgs(ns_uri)\n+     * >>> request.parseExtensionArgs(args)\n+     *\n+     * $args: The unqualified simple registration arguments\n+     *\n+     * strict: Whether requests with fields that are not defined in\n+     * the simple registration specification should be tolerated (and\n+     * ignored)\n+     */\n+    function parseExtensionArgs($args, $strict=false)\n+    {\n+        foreach (array(\'required\', \'optional\') as $list_name) {\n+            $required = ($list_name == \'required\');\n+            $items = Auth_OpenID::arrayGet($args, $list_name);\n+            if ($items) {\n+                foreach (explode(\',\', $items) as $field_name) {\n+                    if (!$this->requestField($field_name, $required, $strict)) {\n+                        if ($strict) {\n+                            return false;\n+                        }\n+                    }\n+                }\n+            }\n+        }\n+\n+        $this->policy_url = Auth_OpenID::arrayGet($args, \'policy_url\');\n+\n+        return true;\n+    }\n+\n+    /**\n+     * A list of all of the simple registration fields that were\n+     * requested, whether they were required or optional.\n+     */\n+    function allRequestedFields()\n+    {\n+        return array_merge($this->required, $this->optional);\n+    }\n+\n+    /**\n+     * Have any simple registration fields been requested?\n+     */\n+    function wereFieldsRequested()\n+    {\n+        return count($this->allRequestedFields());\n+    }\n+\n+    /**\n+     * Was this field in the request?\n+     */\n+    function contains($field_name)\n+    {\n+        return (in_array($field_name, $this->required) ||\n+                in_array($field_name, $this->optional));\n+    }\n+\n+    /**\n+     * Request the specified field from the OpenID user\n+     *\n+     * $field_name: the unqualified simple registration field name\n+     *\n+     * required: whether the given field should be presented to the\n+     * user as being a required to successfully complete the request\n+     *\n+     * strict: whether to raise an exception when a field is added to\n+     * a request more than once\n+     */\n+    function requestField($field_name,\n+                          $required=false, $strict=false)\n+    {\n+        if (!Auth_OpenID_checkFieldName($field_name)) {\n+            return false;\n+        }\n+\n+        if ($strict) {\n+            if ($this->contains($field_name)) {\n+                return false;\n+            }\n+        } else {\n+            if (in_array($field_name, $this->required)) {\n+                return true;\n+            }\n+\n+            if (in_array($field_name, $this->optional)) {\n+                if ($required) {\n+                    unset($this->optional[array_search($field_name,\n+                                                       $this->optional)]);\n+                } else {\n+                    return true;\n+                }\n+            }\n+        }\n+\n+        if ($required) {\n+            $this->required[] = $field_name;\n+        } else {\n+            $this->optional[] = $field_name;\n+        }\n+\n+        return true;\n+    }\n+\n+    /**\n+     * Add the given list of fields to the request\n+     *\n+     * field_names: The simple registration data fields to request\n+     *\n+     * required: Whether these values should be presented to the user\n+     * as required\n+     *\n+     * strict: whether to raise an exception when a field is added to\n+     * a request more than once\n+     */\n+    function requestFields($field_names, $required=false, $strict=false)\n+    {\n+        if (!is_array($field_names)) {\n+            return false;\n+        }\n+\n+        foreach ($field_names as $field_name) {\n+            if (!$this->requestField($field_name, $required, $strict=$strict)) {\n+                return false;\n+            }\n+        }\n+\n+        return true;\n+    }\n+\n+    /**\n+     * Get a dictionary of unqualified simple registration arguments\n+     * representing this request.\n+     *\n+     * This method is essentially the inverse of\n+     * C{L{parseExtensionArgs}}. This method serializes the simple\n+     * registration request fields.\n+     */\n+    function getExtensionArgs()\n+    {\n+        $args = array();\n+\n+        if ($this->required) {\n+            $args[\'required\'] = implode(\',\', $this->required);\n+        }\n+\n+        if ($this->optional) {\n+            $args[\'optional\'] = implode(\',\', $this->optional);\n+        }\n+\n+        if ($this->policy_url) {\n+            $args[\'policy_url\'] = $this->policy_url;\n+        }\n+\n+        return $args;\n+    }\n+}\n+\n+/**\n+ * Represents the data returned in a simple registration response\n+ * inside of an OpenID C{id_res} response. This object will be created\n+ * by the OpenID server, added to the C{id_res} response object, and\n+ * then extracted from the C{id_res} message by the Consumer.\n+ */\n+class Auth_OpenID_SRegResponse extends Auth_OpenID_SRegBase {\n+\n+    var $ns_alias = \'sreg\';\n+\n+    function Auth_OpenID_SRegResponse($data=null,\n+                                      $sreg_ns_uri=Auth_OpenID_SREG_NS_URI)\n+    {\n+        if ($data === null) {\n+            $this->data = array();\n+        } else {\n+            $this->data = $data;\n+        }\n+\n+        $this->ns_uri = $sreg_ns_uri;\n+    }\n+\n+    /**\n+     * Take a C{L{SRegRequest}} and a dictionary of simple\n+     * registration values and create a C{L{SRegResponse}} object\n+     * containing that data.\n+     *\n+     * request: The simple registration request object\n+     *\n+     * data: The simple registration data for this response, as a\n+     * dictionary from unqualified simple registration field name to\n+     * string (unicode) value. For instance, the nickname should be\n+     * stored under the key \'nickname\'.\n+     *\n+     */\n+    function extractResponse($request, $data)\n+    {\n+        $obj = new Auth_OpenID_SRegResponse();\n+        $obj->ns_uri = $request->ns_uri;\n+\n+        foreach ($request->allRequestedFields() as $field) {\n+            $value = Auth_OpenID::arrayGet($data, $field);\n+            if ($value !== null) {\n+                $obj->data[$field] = $value;\n+            }\n+        }\n+\n+        return $obj;\n+    }\n+\n+    /**\n+     * Create a C{L{SRegResponse}} object from a successful OpenID\n+     * library response\n+     * (C{L{openid.consumer.consumer.SuccessResponse}}) response\n+     * message\n+     *\n+     * success_response: A SuccessResponse from consumer.complete()\n+     *\n+     * signed_only: Whether to process only data that was\n+     * signed in the id_res message from the server.\n+     *\n+     * Returns a simple registration response containing the data that\n+     * was supplied with the C{id_res} response.\n+     */\n+    function fromSuccessResponse($success_response, $signed_only=true)\n+    {\n+        global $Auth_OpenID_sreg_data_fields;\n+\n+        $obj = new Auth_OpenID_SRegResponse();\n+        $obj->ns_uri = $obj->_getSRegNS($success_response->message);\n+\n+        if ($signed_only) {\n+            $args = $success_response->getSignedNS($obj->ns_uri);\n+        } else {\n+            $args = $success_response->message->getArgs($obj->ns_uri);\n+        }\n+\n+        if ($args === null) {\n+            return null;\n+        }\n+\n+        foreach ($Auth_OpenID_sreg_data_fields as $field_name => $desc) {\n+            if (in_array($field_name, array_keys($args))) {\n+                $obj->data[$field_name] = $args[$field_name];\n+            }\n+        }\n+\n+        return $obj;\n+    }\n+\n+    /**\n+     * Add the data fields contained in this simple registration\n+     * response to the supplied message, in the appropriate namespace.\n+     *\n+     * response_message: The OpenID id_res response message that will\n+     * be returned to the relying party\n+     *\n+     * Returns nothing; updates the response_message\n+     */\n+    function addToOpenIDResponse(&$response_message)\n+    {\n+        $response_message->updateArgs($this->ns_uri, $this->data);\n+    }\n+\n+    // Read-only dictionary interface\n+    function get($field_name, $default=null)\n+    {\n+        if (!Auth_OpenID_checkFieldName($field_name)) {\n+            return null;\n+        }\n+\n+        return Auth_OpenID::arrayGet($this->data, $field_name, $default);\n+    }\n+\n+    function contents()\n+    {\n+        return $this->data;\n+    }\n+}\n+\n+/**\n+ * Convenience function for copying all the sreg data that was\n+ * requested from a supplied set of sreg data into the response\n+ * message. If no data were requested, no data will be sent.\n+ *\n+ * openid_request: The OpenID (checkid_*) request that may be\n+ * requesting sreg data.\n+ *\n+ * data: The simple registration data to send. All requested fields\n+ * that are present in this dictionary will be added to the response\n+ * message.\n+ *\n+ * openid_response: The OpenID C{id_res} response to which the simple\n+ * registration data should be added\n+ *\n+ * Does not return a value; updates the openid_response instead.\n+ */\n+function Auth_OpenID_sendSRegFields(&$openid_request, $data, &$openid_response)\n+{\n+    $sreg_request = Auth_OpenID_SRegRequest::fromOpenIDRequest(\n+                                                   $openid_request->message);\n+    $sreg_response = Auth_OpenID_SRegResponse::extractResponse(\n+                                                   $sreg_request, $data);\n+    $sreg_response->addToOpenIDResponse($openid_response->fields);\n+}\n+\n+?>\n\\ No newline at end of file\ndiff --git a/Tests/Auth/OpenID/Consumer.php b/Tests/Auth/OpenID/Consumer.php\nindex 249886a..fae98aa 100644\n--- a/Tests/Auth/OpenID/Consumer.php\n+++ b/Tests/Auth/OpenID/Consumer.php\n@@ -23,6 +23,7 @@ require_once \'Auth/OpenID/KVForm.php\';\n require_once \'Auth/OpenID/Consumer.php\';\n require_once \'Auth/OpenID/Server.php\';\n require_once \'Auth/OpenID/Nonce.php\';\n+require_once \'Auth/OpenID/SReg.php\';\n require_once \'Auth/OpenID/Message.php\';\n require_once \'Auth/OpenID/HMACSHA1.php\';\n require_once \'Tests/Auth/OpenID/MemStore.php\';\n@@ -1450,15 +1451,12 @@ class Tests_Auth_OpenID_SuccessResponse extends PHPUnit_TestCase {\n             \'openid.sreg.nickname\' => \'j3h\',\n             \'openid.return_to\' => \'return_to\');\n \n-        $temp_sreg_uri = \'bogus\';\n-        $this->assertTrue(Auth_OpenID_registerNamespaceAlias($temp_sreg_uri, \'sreg\'));\n-\n         $message = Auth_OpenID_Message::fromPostArgs($query);\n         $resp = new Auth_OpenID_SuccessResponse($this->endpoint, $message);\n \n         $utargs = $resp->extensionResponse($uri, false);\n         $this->assertEquals($utargs, array(\'one\' => \'1\', \'two\' => \'2\'));\n-        $sregargs = $resp->extensionResponse($temp_sreg_uri, false);\n+        $sregargs = $resp->extensionResponse(Auth_OpenID_SREG_NS_URI, false);\n         $this->assertEquals($sregargs, array(\'nickname\' => \'j3h\'));\n     }\n \ndiff --git a/Tests/Auth/OpenID/SReg.php b/Tests/Auth/OpenID/SReg.php\nnew file mode 100644\nindex 0000000..f807aa6\n--- /dev/null\n+++ b/Tests/Auth/OpenID/SReg.php\n@@ -0,0 +1,642 @@\n+<?php\n+\n+/**\n+ * SReg.php testing code.\n+ */\n+\n+require_once \'Auth/OpenID/SReg.php\';\n+require_once \'Auth/OpenID/Message.php\';\n+require_once \'Auth/OpenID/Server.php\';\n+\n+require_once \'PHPUnit.php\';\n+\n+class SRegURITest extends PHPUnit_TestCase {\n+    function test_is11()\n+    {\n+        $this->assertEquals(Auth_OpenID_SREG_NS_URI_1_1,\n+                            Auth_OpenID_SREG_NS_URI);\n+    }\n+}\n+\n+class CheckFieldNameTest extends PHPUnit_TestCase {\n+    function test_goodNamePasses()\n+    {\n+        global $Auth_OpenID_sreg_data_fields;\n+\n+        foreach ($Auth_OpenID_sreg_data_fields as $field_name => $desc) {\n+            $this->assertTrue(Auth_OpenID_checkFieldName($field_name));\n+        }\n+    }\n+\n+    function test_badNameFails()\n+    {\n+        $this->assertfalse(Auth_OpenID_checkFieldName(\'INVALID\'));\n+    }\n+\n+    function test_badTypeFails()\n+    {\n+        $this->assertfalse(Auth_OpenID_checkFieldName(null));\n+    }\n+}\n+\n+// For supportsSReg test\n+class FakeEndpoint {\n+    function FakeEndpoint($supported)\n+    {\n+        $this->supported = $supported;\n+        $this->checked_uris = array();\n+    }\n+\n+    function usesExtension($namespace_uri)\n+    {\n+        $this->checked_uris[] = $namespace_uri;\n+        return in_array($namespace_uri, $this->supported);\n+    }\n+}\n+\n+class SupportsSRegTest extends PHPUnit_TestCase {\n+    function test_unsupported()\n+    {\n+        $endpoint = new FakeEndpoint(array());\n+        $this->assertfalse(Auth_OpenID_supportsSReg($endpoint));\n+        $this->assertEquals(array(Auth_OpenID_SREG_NS_URI_1_1,\n+                                  Auth_OpenID_SREG_NS_URI_1_0),\n+                            $endpoint->checked_uris);\n+    }\n+\n+    function test_supported_1_1()\n+    {\n+        $endpoint = new FakeEndpoint(array(Auth_OpenID_SREG_NS_URI_1_1));\n+        $this->assertTrue(Auth_OpenID_supportsSReg($endpoint));\n+        $this->assertEquals(array(Auth_OpenID_SREG_NS_URI_1_1),\n+                            $endpoint->checked_uris);\n+    }\n+\n+    function test_supported_1_0()\n+    {\n+        $endpoint = new FakeEndpoint(array(Auth_OpenID_SREG_NS_URI_1_0));\n+        $this->assertTrue(Auth_OpenID_supportsSReg($endpoint));\n+        $this->assertEquals(array(Auth_OpenID_SREG_NS_URI_1_1,\n+                                     Auth_OpenID_SREG_NS_URI_1_0),\n+                               $endpoint->checked_uris);\n+    }\n+}\n+\n+class FakeMessage {\n+    function FakeMessage()\n+    {\n+        $this->openid1 = false;\n+        $this->namespaces = new Auth_OpenID_NamespaceMap();\n+    }\n+\n+    function isOpenID1()\n+    {\n+        return $this->openid1;\n+    }\n+}\n+\n+class GetNSTest extends PHPUnit_TestCase {\n+    function setUp()\n+    {\n+        $this->msg = new FakeMessage();\n+    }\n+\n+    function test_openID2Empty()\n+    {\n+        $ns_uri = Auth_OpenID_SRegBase::_getSRegNS($this->msg);\n+        $this->assertEquals($this->msg->namespaces->getAlias($ns_uri), \'sreg\');\n+        $this->assertEquals(Auth_OpenID_SREG_NS_URI, $ns_uri);\n+    }\n+\n+    function test_openID1Empty()\n+    {\n+        $this->msg->openid1 = true;\n+        $ns_uri = Auth_OpenID_SRegBase::_getSRegNS($this->msg);\n+        $this->assertEquals($this->msg->namespaces->getAlias($ns_uri), \'sreg\');\n+        $this->assertEquals(Auth_OpenID_SREG_NS_URI, $ns_uri);\n+    }\n+\n+    function test_openID1Defined_1_0()\n+    {\n+        $this->msg->openid1 = true;\n+        $this->msg->namespaces->add(Auth_OpenID_SREG_NS_URI_1_0);\n+        $ns_uri = Auth_OpenID_SRegBase::_getSRegNS($this->msg);\n+        $this->assertEquals(Auth_OpenID_SREG_NS_URI_1_0, $ns_uri);\n+    }\n+\n+    function test_openID1Defined_1_0_overrideAlias()\n+    {\n+        foreach (array(true, false) as $openid_version) {\n+            foreach (array(Auth_OpenID_SREG_NS_URI_1_0,\n+                           Auth_OpenID_SREG_NS_URI_1_1) as $sreg_version) {\n+                foreach (array(\'sreg\', \'bogus\') as $alias) {\n+                    $this->setUp();\n+\n+                    $this->msg->openid1 = $openid_version;\n+                    $this->assertTrue($this->msg->namespaces->addAlias($sreg_version, $alias) !== null);\n+                    $ns_uri = Auth_OpenID_SRegBase::_getSRegNS($this->msg);\n+                    $this->assertEquals($this->msg->namespaces->getAlias($ns_uri), $alias);\n+                    $this->assertEquals($sreg_version, $ns_uri);\n+                }\n+            }\n+        }\n+    }\n+\n+    function test_openID1DefinedBadly()\n+    {\n+        $this->msg->openid1 = true;\n+        $this->msg->namespaces->addAlias(\'http://invalid/\', \'sreg\');\n+        $this->assertTrue(Auth_OpenID_SRegBase::_getSRegNS($this->msg) === null);\n+    }\n+\n+    function test_openID2DefinedBadly()\n+    {\n+        $this->msg->openid1 = false;\n+        $this->msg->namespaces->addAlias(\'http://invalid/\', \'sreg\');\n+        $this->assertTrue(Auth_OpenID_SRegBase::_getSRegNS($this->msg) === null);\n+    }\n+\n+    function test_openID2Defined_1_0()\n+    {\n+        $this->msg->namespaces->add(Auth_OpenID_SREG_NS_URI_1_0);\n+        $ns_uri = Auth_OpenID_SRegBase::_getSRegNS($this->msg);\n+        $this->assertEquals(Auth_OpenID_SREG_NS_URI_1_0, $ns_uri);\n+    }\n+\n+    function test_openID1_sregNSfromArgs()\n+    {\n+        $args = array(\n+            \'sreg.optional\' => \'nickname\',\n+            \'sreg.required\' => \'dob\');\n+\n+        $m = Auth_OpenID_Message::fromOpenIDArgs($args);\n+\n+        $this->assertTrue($m->getArg(Auth_OpenID_SREG_NS_URI_1_1, \'optional\') == \'nickname\');\n+        $this->assertTrue($m->getArg(Auth_OpenID_SREG_NS_URI_1_1, \'required\') == \'dob\');\n+    }\n+}\n+\n+class SentinelFakeMessage {\n+    var $args_sentinel = \'args_sentinel\';\n+\n+    function SentinelFakeMessage(&$test_case)\n+    {\n+        $this->test_case =& $test_case;\n+    }\n+\n+    function getArgs($ns_uri)\n+    {\n+        $this->test_case->assertEquals($ns_sentinel, $ns_uri);\n+        return $this->args_sentinel;\n+    }\n+}\n+\n+class TestingReq extends Auth_OpenID_SRegRequest {\n+    var $ns_sentinel = \'ns_sentinel\';\n+\n+    function fromOpenIDRequest($message, &$test_case)\n+    {\n+        parent::fromOpenIDRequest($message);\n+        $this->test_case =& $test_case;\n+    }\n+\n+    function _getSRegNS($unused)\n+    {\n+        return $this->ns_sentinel;\n+    }\n+\n+    function parseExtensionArgs($args)\n+    {\n+        $this->test_case->assertEquals($args_sentinel, $args);\n+    }\n+}\n+\n+class SRegRequestTest extends PHPUnit_TestCase {\n+    function test_constructEmpty()\n+    {\n+        $req = Auth_OpenID_SRegRequest::build();\n+        $this->assertEquals(array(), $req->optional);\n+        $this->assertEquals(array(), $req->required);\n+        $this->assertEquals(null, $req->policy_url);\n+        $this->assertEquals(Auth_OpenID_SREG_NS_URI, $req->ns_uri);\n+    }\n+\n+    function test_constructFields()\n+    {\n+        $req = Auth_OpenID_SRegRequest::build(\n+                                              array(\'nickname\'),\n+                                              array(\'gender\'),\n+                                              \'http://policy\',\n+                                              \'http://sreg.ns_uri\');\n+        $this->assertEquals(array(\'gender\'), $req->optional);\n+        $this->assertEquals(array(\'nickname\'), $req->required);\n+        $this->assertEquals(\'http://policy\', $req->policy_url);\n+        $this->assertEquals(\'http://sreg.ns_uri\', $req->ns_uri);\n+    }\n+\n+    function test_constructBadFields()\n+    {\n+        $this->assertTrue(Auth_OpenID_SRegRequest::build(array(\'elvis\')) === null);\n+    }\n+\n+    /*\n+    function test_fromOpenIDResponse()\n+    {\n+        $msg = new SentinelFakeMessage($this);\n+        $req = TestingReq::fromOpenIDRequest($msg, $this);\n+    }\n+    */\n+\n+    function test_parseExtensionArgs_empty()\n+    {\n+        $req = Auth_OpenID_SRegRequest::build();\n+        $this->assertTrue($req->parseExtensionArgs(array()));\n+    }\n+\n+    function test_parseExtensionArgs_extraIgnored()\n+    {\n+        $req = Auth_OpenID_SRegRequest::build();\n+        $this->assertTrue($req->parseExtensionArgs(array(\'janrain\' => \'inc\')));\n+    }\n+\n+    function test_parseExtensionArgs_nonStrict()\n+    {\n+        $req = Auth_OpenID_SRegRequest::build();\n+        $this->assertTrue($req->parseExtensionArgs(array(\'required\' => \'beans\')));\n+        $this->assertEquals(array(), $req->required);\n+    }\n+\n+    function test_parseExtensionArgs_strict()\n+    {\n+        $req = Auth_OpenID_SRegRequest::build();\n+        $this->assertFalse($req->parseExtensionArgs(array(\'required\' => \'beans\'),\n+                                                    true));\n+    }\n+\n+    function test_parseExtensionArgs_policy()\n+    {\n+        $req = Auth_OpenID_SRegRequest::build();\n+        $this->assertTrue($req->parseExtensionArgs(\n+                                array(\'policy_url\' => \'http://policy\'), true));\n+        $this->assertEquals(\'http://policy\', $req->policy_url);\n+    }\n+\n+    function test_parseExtensionArgs_requiredEmpty()\n+    {\n+        $req = Auth_OpenID_SRegRequest::build();\n+        $this->assertTrue($req->parseExtensionArgs(array(\'required\' => \'\'), true));\n+        $this->assertEquals(array(), $req->required);\n+    }\n+\n+    function test_parseExtensionArgs_optionalEmpty()\n+    {\n+        $req = Auth_OpenID_SRegRequest::build();\n+        $this->assertTrue($req->parseExtensionArgs(array(\'optional\' => \'\'), true));\n+        $this->assertEquals(array(), $req->optional);\n+    }\n+\n+    function test_parseExtensionArgs_optionalSingle()\n+    {\n+        $req = Auth_OpenID_SRegRequest::build();\n+        $this->assertTrue($req->parseExtensionArgs(array(\'optional\' => \'nickname\'), true));\n+        $this->assertEquals(array(\'nickname\'), $req->optional);\n+    }\n+\n+    function test_parseExtensionArgs_optionalList()\n+    {\n+        $req = Auth_OpenID_SRegRequest::build();\n+        $this->assertTrue($req->parseExtensionArgs(array(\'optional\' => \'nickname,email\'), true));\n+        $this->assertEquals(array(\'nickname\',\'email\'), $req->optional);\n+    }\n+\n+    function test_parseExtensionArgs_optionalListBadNonStrict()\n+    {\n+        $req = Auth_OpenID_SRegRequest::build();\n+        $this->assertTrue($req->parseExtensionArgs(array(\'optional\' => \'nickname,email,beer\')));\n+        $this->assertEquals(array(\'nickname\',\'email\'), $req->optional);\n+    }\n+\n+    function test_parseExtensionArgs_optionalListBadStrict()\n+    {\n+        $req = Auth_OpenID_SRegRequest::build();\n+        $this->assertFalse($req->parseExtensionArgs(array(\'optional\' => \'nickname,email,beer\'),\n+                                                    true));\n+    }\n+\n+    function test_parseExtensionArgs_bothNonStrict()\n+    {\n+        $req = Auth_OpenID_SRegRequest::build();\n+        $this->assertTrue($req->parseExtensionArgs(array(\'optional\' => \'nickname\',\n+                                                         \'required\' => \'nickname\')));\n+        $this->assertEquals(array(), $req->optional);\n+        $this->assertEquals(array(\'nickname\'), $req->required);\n+    }\n+\n+    function test_parseExtensionArgs_bothStrict()\n+    {\n+        $req = Auth_OpenID_SRegRequest::build();\n+        $this->assertFalse($req->parseExtensionArgs(\n+                                                    array(\'optional\' => \'nickname\',\n+                                                          \'required\' => \'nickname\'),\n+                                                    true));\n+    }\n+\n+    function test_parseExtensionArgs_bothList()\n+    {\n+        $req = Auth_OpenID_SRegRequest::build();\n+        $this->assertTrue($req->parseExtensionArgs(array(\'optional\' => \'nickname,email\',\n+                                                         \'required\' => \'country,postcode\'),\n+                                                   true));\n+        $this->assertEquals(array(\'nickname\',\'email\'), $req->optional);\n+        $this->assertEquals(array(\'country\',\'postcode\'), $req->required);\n+    }\n+\n+    function test_allRequestedFields()\n+    {\n+        $req = Auth_OpenID_SRegRequest::build();\n+        $this->assertEquals(array(), $req->allRequestedFields());\n+        $req->requestField(\'nickname\');\n+        $this->assertEquals(array(\'nickname\'), $req->allRequestedFields());\n+        $req->requestField(\'gender\', true);\n+        $requested = $req->allRequestedFields();\n+        sort($requested);\n+        $this->assertEquals(array(\'gender\', \'nickname\'), $requested);\n+    }\n+\n+    function test_wereFieldsRequested()\n+    {\n+        $req = Auth_OpenID_SRegRequest::build();\n+        $this->assertFalse($req->wereFieldsRequested());\n+        $req->requestField(\'gender\');\n+        $this->assertTrue($req->wereFieldsRequested());\n+    }\n+\n+    function test_contains()\n+    {\n+        global $Auth_OpenID_sreg_data_fields;\n+\n+        $req = Auth_OpenID_SRegRequest::build();\n+        foreach ($Auth_OpenID_sreg_data_fields as $field_name => $desc) {\n+            $this->assertFalse($req->contains($field_name));\n+        }\n+\n+        $this->assertFalse($req->contains(\'something else\'));\n+\n+        $req->requestField(\'nickname\');\n+        foreach ($Auth_OpenID_sreg_data_fields as $field_name => $desc) {\n+            if ($field_name == \'nickname\') {\n+                $this->assertTrue($req->contains($field_name));\n+            } else {\n+                $this->assertFalse($req->contains($field_name));\n+            }\n+        }\n+    }\n+\n+    function test_requestField_bogus()\n+    {\n+        $req = Auth_OpenID_SRegRequest::build();\n+        $this->assertFalse($req->requestField(\'something else\'));\n+        $this->assertFalse($req->requestField(\'something else\', true));\n+    }\n+\n+    function test_requestField()\n+    {\n+        global $Auth_OpenID_sreg_data_fields;\n+\n+        // Add all of the fields, one at a time\n+        $req = Auth_OpenID_SRegRequest::build();\n+        $fields = array_keys($Auth_OpenID_sreg_data_fields);\n+        foreach ($fields as $field_name) {\n+            $req->requestField($field_name);\n+        }\n+\n+        $this->assertEquals($fields, $req->optional);\n+        $this->assertEquals(array(), $req->required);\n+\n+        // By default, adding the same fields over again has no effect\n+        foreach ($fields as $field_name) {\n+            $req->requestField($field_name);\n+        }\n+\n+        $this->assertEquals($fields, $req->optional);\n+        $this->assertEquals(array(), $req->required);\n+\n+        // Requesting a field as required overrides requesting it as\n+        // optional\n+        $expected = $fields;\n+        $overridden = array_pop($expected);\n+\n+        $this->assertTrue($req->requestField($overridden, true));\n+\n+        $this->assertEquals($expected, $req->optional);\n+        $this->assertEquals(array($overridden), $req->required);\n+\n+        // Requesting a field as required overrides requesting it as\n+        // optional\n+        foreach ($fields as $field_name) {\n+            $this->assertTrue($req->requestField($field_name, true));\n+        }\n+\n+        $this->assertEquals(array(), $req->optional);\n+        foreach ($fields as $f) {\n+            $this->assertTrue(in_array($f, $req->required));\n+        }\n+\n+        // Requesting it as optional does not downgrade it to optional\n+        foreach ($fields as $field_name) {\n+            $req->requestField($field_name);\n+        }\n+\n+        $this->assertEquals(array(), $req->optional);\n+\n+        foreach ($fields as $f) {\n+            $this->assertTrue(in_array($f, $req->required));\n+        }\n+    }\n+\n+    function test_requestFields_type()\n+    {\n+        $req = Auth_OpenID_SRegRequest::build();\n+        $this->assertFalse($req->requestFields(\'nickname\'));\n+    }\n+\n+    function test_requestFields()\n+    {\n+        global $Auth_OpenID_sreg_data_fields;\n+\n+        // Add all of the fields\n+        $req = Auth_OpenID_SRegRequest::build();\n+\n+        $fields = array_keys($Auth_OpenID_sreg_data_fields);\n+        $req->requestFields($fields);\n+\n+        $this->assertEquals($fields, $req->optional);\n+        $this->assertEquals(array(), $req->required);\n+\n+        // By default, adding the same fields over again has no effect\n+        $req->requestFields($fields);\n+\n+        $this->assertEquals($fields, $req->optional);\n+        $this->assertEquals(array(), $req->required);\n+\n+        // Requesting a field as required overrides requesting it as\n+        // optional\n+        $expected = $fields;\n+        $overridden = array_shift($expected);\n+        $req->requestFields(array($overridden), true);\n+\n+        foreach ($expected as $f) {\n+            $this->assertTrue(in_array($f, $req->optional));\n+        }\n+\n+        $this->assertEquals(array($overridden), $req->required);\n+\n+        // Requesting a field as required overrides requesting it as\n+        // optional\n+        $req->requestFields($fields, true);\n+\n+        $this->assertEquals(array(), $req->optional);\n+        $this->assertEquals($fields, $req->required);\n+\n+        // Requesting it as optional does not downgrade it to optional\n+        $req->requestFields($fields);\n+\n+        $this->assertEquals(array(), $req->optional);\n+        $this->assertEquals($fields, $req->required);\n+    }\n+\n+    function test_getExtensionArgs()\n+    {\n+        $req = Auth_OpenID_SRegRequest::build();\n+        $this->assertEquals(array(), $req->getExtensionArgs());\n+\n+        $this->assertTrue($req->requestField(\'nickname\'));\n+        $this->assertEquals(array(\'optional\' => \'nickname\'),\n+                            $req->getExtensionArgs());\n+\n+        $this->assertTrue($req->requestField(\'email\'));\n+        $this->assertEquals(array(\'optional\' => \'nickname,email\'),\n+                            $req->getExtensionArgs());\n+\n+        $this->assertTrue($req->requestField(\'gender\', true));\n+        $this->assertEquals(array(\'optional\' => \'nickname,email\',\n+                                  \'required\' => \'gender\'),\n+                            $req->getExtensionArgs());\n+\n+        $this->assertTrue($req->requestField(\'postcode\', true));\n+        $this->assertEquals(array(\'optional\' => \'nickname,email\',\n+                                  \'required\' => \'gender,postcode\'),\n+                            $req->getExtensionArgs());\n+\n+        $req->policy_url = \'http://policy.invalid/\';\n+        $this->assertEquals(array(\'optional\' => \'nickname,email\',\n+                                  \'required\' => \'gender,postcode\',\n+                                  \'policy_url\' => \'http://policy.invalid/\'),\n+                            $req->getExtensionArgs());\n+    }\n+}\n+\n+class DummySuccessResponse {\n+    function DummySuccessResponse($message, $signed_stuff)\n+    {\n+        $this->message = $message;\n+        $this->signed_stuff = $signed_stuff;\n+    }\n+\n+    function getSignedNS($ns_uri)\n+    {\n+        return $this->signed_stuff;\n+    }\n+}\n+\n+class SRegResponseTest extends PHPUnit_TestCase {\n+    function test_fromSuccessResponse_signed()\n+    {\n+        $message = Auth_OpenID_Message::fromOpenIDArgs(array(\n+            \'sreg.nickname\' => \'The Mad Stork\',\n+            ));\n+        $success_resp = new DummySuccessResponse($message, array());\n+        $sreg_resp = Auth_OpenID_SRegResponse::fromSuccessResponse($success_resp);\n+        $this->assertTrue(count($sreg_resp->contents()) === 0);\n+    }\n+\n+    function test_fromSuccessResponse_unsigned()\n+    {\n+        $message = Auth_OpenID_Message::fromOpenIDArgs(array(\n+            \'sreg.nickname\' => \'The Mad Stork\',\n+            ));\n+\n+        $success_resp = new DummySuccessResponse($message, array());\n+        $sreg_resp = Auth_OpenID_SRegResponse::fromSuccessResponse($success_resp,\n+                                                                   false);\n+\n+        $this->assertEquals(array(\'nickname\' => \'The Mad Stork\'),\n+                            $sreg_resp->contents());\n+    }\n+}\n+\n+class SendFieldsTest extends PHPUnit_TestCase {\n+    function test()\n+    {\n+        // Create a request message with simple registration fields\n+        $sreg_req = Auth_OpenID_SRegRequest::build(array(\'nickname\', \'email\'),\n+                                                   array(\'fullname\'));\n+        $req_msg = new Auth_OpenID_Message();\n+        $req_msg->updateArgs(Auth_OpenID_SREG_NS_URI,\n+                             $sreg_req->getExtensionArgs());\n+\n+        $req = new Auth_OpenID_Request();\n+        $req->message = $req_msg;\n+        $req->namespace = $req_msg->getOpenIDNamespace();\n+\n+        // -> send checkid_* request\n+\n+        // Create an empty response message\n+        $resp_msg = new Auth_OpenID_Message();\n+        $resp = new Auth_OpenID_ServerResponse($req);\n+        $resp->fields = $resp_msg;\n+\n+        $data = array(\n+                      \'nickname\' => \'linusaur\',\n+                      \'postcode\' => \'12345\',\n+                      \'country\' => \'US\',\n+                      \'gender\' => \'M\',\n+                      \'fullname\' => \'Leonhard Euler\',\n+                      \'email\' => \'president@whitehouse.gov\',\n+                      \'dob\' => \'0000-00-00\',\n+                      \'language\' => \'en-us\');\n+\n+        // Put the requested data fields in the response message\n+        Auth_OpenID_sendSRegFields($req, $data, $resp);\n+\n+        // <- send id_res response\n+\n+        // Extract the fields that were sent\n+        $sreg_data_resp = $resp->fields->getArgs(Auth_OpenID_SREG_NS_URI);\n+        $this->assertEquals(\n+                            array(\'nickname\' => \'linusaur\',\n+                                  \'email\' => \'president@whitehouse.gov\',\n+                                  \'fullname\' => \'Leonhard Euler\'),\n+                            $sreg_data_resp);\n+    }\n+}\n+\n+class Tests_Auth_OpenID_SReg extends PHPUnit_TestSuite {\n+    function getName()\n+    {\n+        return "Tests_Auth_OpenID_SReg";\n+    }\n+\n+    function Tests_Auth_OpenID_SReg()\n+    {\n+        $this->addTestSuite(\'SRegURITest\');\n+        $this->addTestSuite(\'CheckFieldNameTest\');\n+        $this->addTestSuite(\'SupportsSRegTest\');\n+        $this->addTestSuite(\'GetNSTest\');\n+        $this->addTestSuite(\'SRegRequestTest\');\n+        $this->addTestSuite(\'SRegResponseTest\');\n+        $this->addTestSuite(\'SendFieldsTest\');\n+    }\n+}\n+\n+?>\n\\ No newline at end of file\ndiff --git a/Tests/TestDriver.php b/Tests/TestDriver.php\nindex c88d525..69b69ce 100644\n--- a/Tests/TestDriver.php\n+++ b/Tests/TestDriver.php\n@@ -130,6 +130,7 @@ $_tests = array(\n                                        \'OpenID_Yadis\',\n                                        \'Parse\',\n                                        \'Server\',\n+                                       \'SReg\',\n                                        \'StoreTest\',\n                                        \'TrustRoot\',\n                                        \'URINorm\',\n', 'commit_subject': '[project @ Added new Sreg module, extension code, and tests]', 'repo_name': 'openid/php-openid', 'committer': {'name': 'tailor', 'email': 'accb97da9354700c57994830e28e7373de06287c@janrain.com', 'time_sec': '1175206868', 'tz_offset': '0', 'date': {'seconds': '1175206868'}}, 'commit_tree': '005a376ab6bb748b4d0b39c30fe4ee2a16895d33', 'commit_message': '[project @ Added new Sreg module, extension code, and tests]\n', 'language_name': 'HTML', 'license': 'apache-2.0', 'hunks': "@@ -130,6 +130,7 @@ $_tests = array(\n                                        'OpenID_Yadis',\n                                        'Parse',\n                                        'Server',\n+                                       'SReg',\n                                        'StoreTest',\n                                        'TrustRoot',\n                                        'URINorm',\n", 'addition_count': 1, 'deletion_count': 0, 'src_file': 'a/Tests/TestDriver.php', 'tgt_file': 'b/Tests/TestDriver.php', 'file_extension': '.php', 'before_file': '<?php\n\n/**\n * A driver for the PHP OpenID unit tests.\n *\n * PHP versions 4 and 5\n *\n * LICENSE: See the COPYING file included in this distribution.\n *\n * @package OpenID\n * @author JanRain, Inc. <openid@janrain.com>\n * @copyright 2005-2008 Janrain, Inc.\n * @license http://www.apache.org/licenses/LICENSE-2.0 Apache\n */\n\nrequire_once \'PHPUnit/Framework.php\';\n//require_once \'PHPUnit/GUI/HTML.php\';\n\nerror_reporting(E_ALL | E_STRICT);\n\nglobal $__test_errors;\n$__test_errors = [];\n\nfunction __handler($code, $message)\n{\n    global $__test_errors;\n\n    if ($code == E_USER_WARNING) {\n        $__test_errors[] = $message;\n    }\n}\n\nfunction __raiseError($message)\n{\n    set_error_handler(\'__handler\');\n    trigger_error($message, E_USER_WARNING);\n    restore_error_handler();\n}\n\nfunction __getError()\n{\n    global $__test_errors;\n    if ($__test_errors) {\n        return array_pop($__test_errors);\n    }\n    return null;\n}\n\n/**\n * Load the tests that are defined in the named modules.\n *\n * If you have Tests/Foo.php which defines a test class called\n * Tests_Foo, the call would look like:\n *\n * loadTests(\'Tests/\', array(\'Foo\'))\n *\n * @param string $test_dir The root of the test hierarchy. Must end\n * with a /\n *\n * @param array $test_names The names of the modules in which the\n * tests are defined. This should not include the root of the test\n * hierarchy.\n */\nfunction loadTests($test_dir, $test_names)\n{\n    global $_tests;\n    $suites = [];\n\n    foreach ($test_names as $filename) {\n        $filename = $test_dir . $filename . \'.php\';\n\n        if (!global_require_once($filename)) {\n            continue;\n        }\n\n        $class_name = str_replace(\'/\', \'_\', $filename);\n        $class_name = basename($class_name, \'.php\');\n\n        $suites[] = makeSuite($class_name);\n    }\n\n    return $suites;\n}\n\nfunction makeSuite($class_name) {\n    $test = new $class_name($class_name);\n\n    if (is_a($test, \'PHPUnit_Framework_TestCase\')) {\n        $s = new PHPUnit_Framework_TestSuite();\n        $s->setName($class_name);\n        $s->addTestSuite($class_name);\n        $test = $s;\n    }\n\n    $tc_array_name = $class_name . \'_other\';\n    if (array_key_exists($tc_array_name, $GLOBALS) &&\n        is_array($GLOBALS[$tc_array_name])) {\n\n        foreach ($GLOBALS[$tc_array_name] as $tc) {\n            $test->addTestSuite(get_class($tc));\n        }\n    }\n\n    return $test;\n}\n\n\nfunction global_require_once($name)\n{\n    $f = include_once $name;\n    if (!$f) {\n        print("global require once skipping $name\\n");\n        return false;\n    }\n    foreach (get_defined_vars() as $k => $v) {\n        if (!in_array($k, [\'name\', \'GLOBALS\'])) {\n            $GLOBALS[$k] = $v;\n        }\n    }\n    return true;\n}\n\n$_tests = [\n    [\n        \'dir\' => \'Tests/Auth/OpenID/\',\n        \'files\' => [\n            \'Association\',\n            \'AssociationResponse\',\n            \'AuthRequest\',\n                                       \'OpenID_Yadis\',\n                                       \'Parse\',\n                                       \'Server\',\n                                       \'StoreTest\',\n                                       \'TrustRoot\',\n                                       \'URINorm\',\n            \'HMAC\',\n            \'KVForm\',\n            \'Message\',\n            \'Negotiation\',\n            \'Nonce\',\n            \'OpenID_Yadis\',\n            \'PAPE\',\n            \'Parse\',\n            \'RPVerify\',\n            \'Server\',\n            \'SReg\',\n            \'StoreTest\',\n            \'TrustRoot\',\n            \'URINorm\',\n            \'Util\',\n            \'VerifyDisco\',\n        ],\n    ],\n    [\n        \'dir\' => \'Tests/Auth/Yadis/\',\n        \'files\' => [\n            \'ParseHTML\',\n            \'XRDS\',\n            \'Yadis\',\n            \'Discover_Yadis\',\n            \'XRI\',\n        ],\n    ],\n];\n\nfunction selectTests($package, $names)\n{\n    global $_tests;\n    $lnames = array_map(\'strtolower\', $names);\n    $include = [];\n    $exclude = [];\n    foreach ($package[\'files\'] as $t) {\n        $l = strtolower($t);\n        if (in_array($l, $lnames)) {\n            $include[] = $t;\n        }\n\n        if (in_array("/$l", $lnames)) {\n            $exclude[] = $t;\n        }\n    }\n\n    return array_diff($include, $exclude);\n}\n\n// Load OpenID library tests\nfunction loadSuite($names=null)\n{\n    global $_tests;\n    $result = [];\n    foreach ($_tests as $package) {\n        if (!$names) {\n            $selected = $package[\'files\'];\n        } else {\n            $selected = selectTests($package, $names);\n        }\n        $result = array_merge($result, loadTests($package[\'dir\'], $selected));\n    }\n\n    return $result;\n}\n\n', 'message': '[project @ Added new Sreg module, extension code, and tests]\n', 'author_name': 'tailor', 'lang': 'php'}