]> source.dussan.org Git - nextcloud-server.git/commitdiff
Experimental OpenID user backend and server.
authorRobin Appelman <icewind1991@gmail.com>
Thu, 23 Jun 2011 15:04:32 +0000 (17:04 +0200)
committerRobin Appelman <icewind1991@gmail.com>
Thu, 23 Jun 2011 15:08:04 +0000 (17:08 +0200)
Currently all users can set one OpenID identity that allows access to the account.

The identity url's for the server is owncloud/apps/user_openid/user.php/$username

apps/user_openid/appinfo/app.php [new file with mode: 0644]
apps/user_openid/appinfo/info.xml [new file with mode: 0644]
apps/user_openid/class.openid.v3.php [new file with mode: 0644]
apps/user_openid/phpmyid.php [new file with mode: 0644]
apps/user_openid/settings.php [new file with mode: 0644]
apps/user_openid/templates/settings.php [new file with mode: 0644]
apps/user_openid/user.php [new file with mode: 0644]
apps/user_openid/user_openid.php [new file with mode: 0644]

diff --git a/apps/user_openid/appinfo/app.php b/apps/user_openid/appinfo/app.php
new file mode 100644 (file)
index 0000000..fb3de10
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+
+require_once 'apps/user_openid/user_openid.php';
+
+OC_APP::addSettingsPage( array( "id" => "user_openid_settings", 'order'=>1, "href" => OC_HELPER::linkTo( "user_openid", "settings.php" ), "name" => "OpenID"));
+
+//active the openid backend
+OC_USER::useBackend('openid');
+
+//check for results from openid requests
+if(isset($_GET['openid_mode']) and $_GET['openid_mode'] == 'id_res'){
+       error_log('openid retured');
+       $openid = new SimpleOpenID;
+       $openid->SetIdentity($_GET['openid_identity']);
+       $openid_validation_result = $openid->ValidateWithServer();
+       if ($openid_validation_result == true){         // OK HERE KEY IS VALID
+               error_log('auth sucessfull');
+               global $WEBROOT;
+               $identity=$openid->GetIdentity();
+               error_log("auth as $identity");
+               $user=OC_USER_OPENID::findUserForIdentity($identity);
+               if($user){
+                       $_SESSION['user_id']=$user;
+                       header("Location: $WEBROOT");
+               }
+       }else if($openid->IsError() == true){            // ON THE WAY, WE GOT SOME ERROR
+               $error = $openid->GetError();
+               error_log("ERROR CODE: " . $error['code']);
+               error_log("ERROR DESCRIPTION: " . $error['description']);
+       }else{                                            // Signature Verification Failed
+               error_log("INVALID AUTHORIZATION");
+       }
+}else if (isset($_GET['openid_mode']) and $_GET['openid_mode'] == 'cancel'){ // User Canceled your Request
+       error_log("USER CANCELED REQUEST");
+       return false;
+}
+
+?>
diff --git a/apps/user_openid/appinfo/info.xml b/apps/user_openid/appinfo/info.xml
new file mode 100644 (file)
index 0000000..3252500
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<info>
+       <id>user_openid</id>
+       <name>OpenID user backend</name>
+       <description>Allow login through OpenID</description>
+       <version>0.1</version>
+       <licence>AGPL</licence>
+       <author>Robin Appelman</author>
+       <require>2</require>
+</info>
\ No newline at end of file
diff --git a/apps/user_openid/class.openid.v3.php b/apps/user_openid/class.openid.v3.php
new file mode 100644 (file)
index 0000000..8afb9e5
--- /dev/null
@@ -0,0 +1,328 @@
+<?php
+/*
+       FREE TO USE
+        Under License: GPLv3
+       Simple OpenID PHP Class
+       
+       Some modifications by Eddie Roosenmaallen, eddie@roosenmaallen.com
+       
+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+This Class was written to make easy for you to integrate OpenID on your website. 
+This is just a client, which checks for user's identity. This Class Requires CURL Module.
+It should be easy to use some other HTTP Request Method, but remember, often OpenID servers
+are using SSL.
+We need to be able to perform SSL Verification on the background to check for valid signature.
+
+HOW TO USE THIS CLASS:
+  STEP 1)
+       $openid = new SimpleOpenID;
+       :: SET IDENTITY ::
+               $openid->SetIdentity($_POST['openid_url']);
+       :: SET RETURN URL ::
+               $openid->SetApprovedURL('http://www.yoursite.com/return.php'); // Script which handles a response from OpenID Server
+       :: SET TRUST ROOT ::
+               $openid->SetTrustRoot('http://www.yoursite.com/');
+       :: FETCH SERVER URL FROM IDENTITY PAGE ::  [Note: It is recomended to cache this (Session, Cookie, Database)]
+               $openid->GetOpenIDServer(); // Returns false if server is not found
+       :: REDIRECT USER TO OPEN ID SERVER FOR APPROVAL ::
+       
+       :: (OPTIONAL) SET OPENID SERVER ::
+               $openid->SetOpenIDServer($server_url); // If you have cached previously this, you don't have to call GetOpenIDServer and set value this directly
+               
+       STEP 2)
+       Once user gets returned we must validate signature
+       :: VALIDATE REQUEST ::
+               true|false = $openid->ValidateWithServer();
+               
+       ERRORS:
+               array = $openid->GetError();    // Get latest Error code
+       
+       FIELDS:
+               OpenID allowes you to retreive a profile. To set what fields you'd like to get use (accepts either string or array):
+               $openid->SetRequiredFields(array('email','fullname','dob','gender','postcode','country','language','timezone'));
+                or
+               $openid->SetOptionalFields('postcode');
+               
+IMPORTANT TIPS:
+OPENID as is now, is not trust system. It is a great single-sign on method. If you want to 
+store information about OpenID in your database for later use, make sure you handle url identities
+properly.
+  For example:
+       https://steve.myopenid.com/
+       https://steve.myopenid.com
+       http://steve.myopenid.com/
+       http://steve.myopenid.com
+       ... are representing one single user. Some OpenIDs can be in format openidserver.com/users/user/ - keep this in mind when storing identities
+
+       To help you store an OpenID in your DB, you can use function:
+               $openid_db_safe = $openid->OpenID_Standarize($upenid);
+       This may not be comatible with current specs, but it works in current enviroment. Use this function to get openid
+       in one format like steve.myopenid.com (without trailing slashes and http/https).
+       Use output to insert Identity to database. Don't use this for validation - it may fail.
+
+*/
+
+class SimpleOpenID{
+       var $openid_url_identity;
+       var $URLs = array();
+       var $error = array();
+       var $fields = array(
+               'required'       => array(),
+               'optional'       => array(),
+       );
+       
+       function SimpleOpenID(){
+               if (!function_exists('curl_exec')) {
+                       die('Error: Class SimpleOpenID requires curl extension to work');
+               }
+       }
+       function SetOpenIDServer($a){
+               $this->URLs['openid_server'] = $a;
+       }
+       function SetTrustRoot($a){
+               $this->URLs['trust_root'] = $a;
+       }
+       function SetCancelURL($a){
+               $this->URLs['cancel'] = $a;
+       }
+       function SetApprovedURL($a){
+               $this->URLs['approved'] = $a;
+       }
+       function SetRequiredFields($a){
+               if (is_array($a)){
+                       $this->fields['required'] = $a;
+               }else{
+                       $this->fields['required'][] = $a;
+               }
+       }
+       function SetOptionalFields($a){
+               if (is_array($a)){
+                       $this->fields['optional'] = $a;
+               }else{
+                       $this->fields['optional'][] = $a;
+               }
+       }
+       function SetIdentity($a){       // Set Identity URL
+                       if ((stripos($a, 'http://') === false)
+                          && (stripos($a, 'https://') === false)){
+                               $a = 'http://'.$a;
+                       }
+/*
+                       $u = parse_url(trim($a));
+                       if (!isset($u['path'])){
+                               $u['path'] = '/';
+                       }else if(substr($u['path'],-1,1) == '/'){
+                               $u['path'] = substr($u['path'], 0, strlen($u['path'])-1);
+                       }
+                       if (isset($u['query'])){ // If there is a query string, then use identity as is
+                               $identity = $a;
+                       }else{
+                               $identity = $u['scheme'] . '://' . $u['host'] . $u['path'];
+                       }
+//*/
+                       $this->openid_url_identity = $a;
+       }
+       function GetIdentity(){         // Get Identity
+               return $this->openid_url_identity;
+       }
+       function GetError(){
+               $e = $this->error;
+               return array('code'=>$e[0],'description'=>$e[1]);
+       }
+
+       function ErrorStore($code, $desc = null){
+               $errs['OPENID_NOSERVERSFOUND'] = 'Cannot find OpenID Server TAG on Identity page.';
+               if ($desc == null){
+                       $desc = $errs[$code];
+               }
+               $this->error = array($code,$desc);
+       }
+
+       function IsError(){
+               if (count($this->error) > 0){
+                       return true;
+               }else{
+                       return false;
+               }
+       }
+       
+       function splitResponse($response) {
+               $r = array();
+               $response = explode("\n", $response);
+               foreach($response as $line) {
+                       $line = trim($line);
+                       if ($line != "") {
+                               list($key, $value) = explode(":", $line, 2);
+                               $r[trim($key)] = trim($value);
+                       }
+               }
+               return $r;
+       }
+       
+       function OpenID_Standarize($openid_identity = null){
+               if ($openid_identity === null)
+                       $openid_identity = $this->openid_url_identity;
+
+               $u = parse_url(strtolower(trim($openid_identity)));
+               
+               if (!isset($u['path']) || ($u['path'] == '/')) {
+                       $u['path'] = '';
+               }
+               if(substr($u['path'],-1,1) == '/'){
+                       $u['path'] = substr($u['path'], 0, strlen($u['path'])-1);
+               }
+               if (isset($u['query'])){ // If there is a query string, then use identity as is
+                       return $u['host'] . $u['path'] . '?' . $u['query'];
+               }else{
+                       return $u['host'] . $u['path'];
+               }
+       }
+       
+       function array2url($arr){ // converts associated array to URL Query String
+               if (!is_array($arr)){
+                       return false;
+               }
+               $query = '';
+               foreach($arr as $key => $value){
+                       $query .= $key . "=" . $value . "&";
+               }
+               return $query;
+       }
+       function FSOCK_Request($url, $method="GET", $params = ""){
+               $fp = fsockopen("ssl://www.myopenid.com", 443, $errno, $errstr, 3); // Connection timeout is 3 seconds
+               if (!$fp) {
+                       $this->ErrorStore('OPENID_SOCKETERROR', $errstr);
+                       return false;
+               } else {
+                       $request = $method . " /server HTTP/1.0\r\n";
+                       $request .= "User-Agent: Simple OpenID PHP Class (http://www.phpclasses.org/simple_openid)\r\n";
+                       $request .= "Connection: close\r\n\r\n";
+                       fwrite($fp, $request);
+                       stream_set_timeout($fp, 4); // Connection response timeout is 4 seconds
+                       $res = fread($fp, 2000);
+                       $info = stream_get_meta_data($fp);
+                       fclose($fp);
+               
+                       if ($info['timed_out']) {
+                      $this->ErrorStore('OPENID_SOCKETTIMEOUT');
+                       } else {
+                       return $res;
+                       }
+               }
+       }
+       function CURL_Request($url, $method="GET", $params = "") { // Remember, SSL MUST BE SUPPORTED
+                       if (is_array($params)) $params = $this->array2url($params);
+                       $curl = curl_init($url . ($method == "GET" && $params != "" ? "?" . $params : ""));
+                       curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
+                       curl_setopt($curl, CURLOPT_HEADER, false);
+                       curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
+                       curl_setopt($curl, CURLOPT_HTTPGET, ($method == "GET"));
+                       curl_setopt($curl, CURLOPT_POST, ($method == "POST"));
+                       if ($method == "POST") curl_setopt($curl, CURLOPT_POSTFIELDS, $params);
+                       curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+                       $response = curl_exec($curl);
+                       
+                       if (curl_errno($curl) == 0){
+                               $response;
+                       }else{
+                               $this->ErrorStore('OPENID_CURL', curl_error($curl));
+                       }
+                       return $response;
+       }
+       
+        function HTML2OpenIDServer($content) {
+               $get = array();
+               
+               // Get details of their OpenID server and (optional) delegate
+               preg_match_all('/<link[^>]*rel=[\'"](openid2.provider )?openid.server[\'"][^>]*href=[\'"]([^\'"]+)[\'"][^>]*\/?>/i', $content, $matches1);
+               preg_match_all('/<link[^>]*href=\'"([^\'"]+)[\'"][^>]*rel=[\'"](openid2.provider )?openid.server[\'"][^>]*\/?>/i', $content, $matches2);
+               $servers = array_merge($matches1[2], $matches2[1]);
+               
+               preg_match_all('/<link[^>]*rel=[\'"]openid.delegate[\'"][^>]*href=[\'"]([^\'"]+)[\'"][^>]*\/?>/i', $content, $matches1);
+               
+               preg_match_all('/<link[^>]*href=[\'"]([^\'"]+)[\'"][^>]*rel=[\'"]openid.delegate[\'"][^>]*\/?>/i', $content, $matches2);
+               
+               $delegates = array_merge($matches1[1], $matches2[1]);
+               
+               $ret = array($servers, $delegates);
+               return $ret;
+       }
+       
+       function GetOpenIDServer(){
+               $response = $this->CURL_Request($this->openid_url_identity);
+               list($servers, $delegates) = $this->HTML2OpenIDServer($response);
+               if (count($servers) == 0){
+                       $this->ErrorStore('OPENID_NOSERVERSFOUND');
+                       return false;
+               }
+               if (isset($delegates[0])
+                 && ($delegates[0] != "")){
+                       $this->SetIdentity($delegates[0]);
+               }
+               $this->SetOpenIDServer($servers[0]);
+               return $servers[0];
+       }
+       
+       function GetRedirectURL(){
+               $params = array();
+               $params['openid.return_to'] = urlencode($this->URLs['approved']);
+               $params['openid.mode'] = 'checkid_setup';
+               $params['openid.identity'] = urlencode($this->openid_url_identity);
+               $params['openid.trust_root'] = urlencode($this->URLs['trust_root']);
+               
+               if (isset($this->fields['required'])
+                 && (count($this->fields['required']) > 0)) {
+                       $params['openid.sreg.required'] = implode(',',$this->fields['required']);
+               }
+               if (isset($this->fields['optional'])
+                 && (count($this->fields['optional']) > 0)) {
+                       $params['openid.sreg.optional'] = implode(',',$this->fields['optional']);
+               }
+               return $this->URLs['openid_server'] . "?". $this->array2url($params);
+       }
+       
+       function Redirect(){
+               $redirect_to = $this->GetRedirectURL();
+               if (headers_sent()){ // Use JavaScript to redirect if content has been previously sent (not recommended, but safe)
+                       echo '<script language="JavaScript" type="text/javascript">window.location=\'';
+                       echo $redirect_to;
+                       echo '\';</script>';
+               }else{  // Default Header Redirect
+                       header('Location: ' . $redirect_to);
+               }
+       }
+       
+       function ValidateWithServer(){
+               $params = array(
+                       'openid.assoc_handle' => urlencode($_GET['openid_assoc_handle']),
+                       'openid.signed' => urlencode($_GET['openid_signed']),
+                       'openid.sig' => urlencode($_GET['openid_sig'])
+               );
+               // Send only required parameters to confirm validity
+               $arr_signed = explode(",",str_replace('sreg.','sreg_',$_GET['openid_signed']));
+               for ($i=0; $i<count($arr_signed); $i++){
+                       $s = str_replace('sreg_','sreg.', $arr_signed[$i]);
+                       $c = $_GET['openid_' . $arr_signed[$i]];
+                       // if ($c != ""){
+                               $params['openid.' . $s] = urlencode($c);
+                       // }
+               }
+               $params['openid.mode'] = "check_authentication";
+
+               $openid_server = $this->GetOpenIDServer();
+               if ($openid_server == false){
+                       return false;
+               }
+               $response = $this->CURL_Request($openid_server,'POST',$params);
+               $data = $this->splitResponse($response);
+
+               if ($data['is_valid'] == "true") {
+                       return true;
+               }else{
+                       return false;
+               }
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/apps/user_openid/phpmyid.php b/apps/user_openid/phpmyid.php
new file mode 100644 (file)
index 0000000..719bbd9
--- /dev/null
@@ -0,0 +1,1723 @@
+<?php
+// PLEASE DO NOT EDIT THIS FILE UNLESS YOU KNOW WHAT YOU ARE DOING!
+
+/**
+ * phpMyID - A standalone, single user, OpenID Identity Provider
+ *
+ * @package phpMyID
+ * @author CJ Niemira <siege (at) siege (dot) org>
+ * @copyright 2006-2008
+ * @license http://www.gnu.org/licenses/gpl.html GNU Public License
+ * @url http://siege.org/projects/phpMyID
+ * @version 0.9
+ */
+
+
+/**
+ * Set a constant to indicate that phpMyID is running
+ */
+define('PHPMYID_STARTED', true);
+
+/**
+ * List the known types and modes
+ * @name $known
+ * @global array $GLOBALS['known']
+ */
+$GLOBALS['known'] = array(
+       'assoc_types'   => array('HMAC-SHA1'),
+
+       'openid_modes'  => array('accept',
+                                'associate',
+                                'authorize',
+                                'cancel',
+                                'checkid_immediate',
+                                'checkid_setup',
+                                'check_authentication',
+                                'error',
+                                'id_res',
+                                'login',
+                                'logout',
+                                'test'),
+
+       'session_types' => array('',
+                                'DH-SHA1'),
+
+       'bigmath_types' => array('DH-SHA1'),
+);
+
+/**
+ * Defined by OpenID spec
+ * @name $g
+ * @global integer $GLOBALS['g']
+ */
+$GLOBALS['g'] = 2;
+
+/**
+ * Defined by OpenID spec
+ * @name $p
+ * @global integer $GLOBALS['p']
+ */
+$GLOBALS['p'] = '155172898181473697471232257763715539915724801966915404479707' .
+'7953140576293785419175806512274236981889937278161526466314385615958256881888' .
+'8995127215884267541995034125870655654980358010487053768147672651325574704076' .
+'5857479291291572334510643245094715007229621094194349783925984760375594985848' .
+'253359305585439638443';
+
+
+// Runmode functions
+
+/**
+ * Allow the user to accept trust on a URL
+ * @global array $profile
+ */
+function accept_mode () {
+       global $profile;
+
+       // this is a user session
+       user_session();
+
+       // the user needs refresh urls in their session to access this mode
+       if (! isset($_SESSION['post_accept_url']) || ! isset($_SESSION['cancel_accept_url']) || ! isset($_SESSION['unaccepted_url']))
+               error_500('You may not access this mode directly.');
+
+       // has the user accepted the trust_root?
+       $accepted = @strlen($_REQUEST['accepted'])
+                       ? $_REQUEST['accepted']
+                       : null;
+
+       // if so, refresh back to post_accept_url
+       if ($accepted === 'yes') {
+               $_SESSION['accepted_url'] = $_SESSION['unaccepted_url'];
+               wrap_redirect($_SESSION['post_accept_url']);
+
+       // if they rejected it, return to the client
+       } elseif ($accepted === 'no') {
+               wrap_redirect($_SESSION['cancel_accept_url']);
+       }
+
+       // if neither, offer the trust request
+       $q = strpos($profile['req_url'], '?') ? '&' : '?';
+       $yes = $profile['req_url'] . $q . 'accepted=yes';
+       $no  = $profile['req_url'] . $q . 'accepted=no';
+
+       wrap_html('The client site you are attempting to log into has requested that you trust the following URL:<br/><b>' . $_SESSION['unaccepted_url'] . '</b><br/><br/>Do you wish to continue?<br/><a href="' . $yes . '">Yes</a> | <a href="' . $no . '">No</a>');
+}
+
+/** * Perform an association with a consumer
+ * @global array $known
+ * @global array $profile
+ * @global integer $g
+ * @global integer $p
+ */
+function associate_mode () {
+       global $g, $known, $p, $profile;
+
+       // Validate the request
+       if (! isset($_REQUEST['openid_mode']) || $_REQUEST['openid_mode'] != 'associate')
+               error_400();
+
+       // Get the request options, using defaults as necessary
+       $assoc_type = (@strlen($_REQUEST['openid_assoc_type'])
+                   && in_array($_REQUEST['openid_assoc_type'], $known['assoc_types']))
+                       ? $_REQUEST['openid_assoc_type']
+                       : 'HMAC-SHA1';
+
+       $session_type = (@strlen($_REQUEST['openid_session_type'])
+                     && in_array($_REQUEST['openid_session_type'], $known['session_types']))
+                       ? $_REQUEST['openid_session_type']
+                       : '';
+
+       $dh_modulus = (@strlen($_REQUEST['openid_dh_modulus']))
+               ? long(base64_decode($_REQUEST['openid_dh_modulus']))
+               : ($session_type == 'DH-SHA1'
+                       ? $p
+                       : null);
+
+       $dh_gen = (@strlen($_REQUEST['openid_dh_gen']))
+               ? long(base64_decode($_REQUEST['openid_dh_gen']))
+               : ($session_type == 'DH-SHA1'
+                       ? $g
+                       : null);
+
+       $dh_consumer_public = (@strlen($_REQUEST['openid_dh_consumer_public']))
+               ? $_REQUEST['openid_dh_consumer_public']
+               : ($session_type == 'DH-SHA1'
+                       ? error_post('dh_consumer_public was not specified')
+                       : null);
+
+       $lifetime = time() + $profile['lifetime'];
+
+       // Create standard keys
+       $keys = array(
+               'assoc_type' => $assoc_type,
+               'expires_in' => $profile['lifetime']
+       );
+
+       // If I can't handle bigmath, default to plaintext sessions
+       if (in_array($session_type, $known['bigmath_types']) && $profile['use_bigmath'] === false)
+               $session_type = null;
+
+       // Add response keys based on the session type
+       switch ($session_type) {
+               case 'DH-SHA1':
+                       // Create the associate id and shared secret now
+                       list ($assoc_handle, $shared_secret) = new_assoc($lifetime);
+
+                       // Compute the Diffie-Hellman stuff
+                       $private_key = random($dh_modulus);
+                       $public_key = bmpowmod($dh_gen, $private_key, $dh_modulus);
+                       $remote_key = long(base64_decode($dh_consumer_public));
+                       $ss = bmpowmod($remote_key, $private_key, $dh_modulus);
+
+                       $keys['assoc_handle'] = $assoc_handle;
+                       $keys['session_type'] = $session_type;
+                       $keys['dh_server_public'] = base64_encode(bin($public_key));
+                       $keys['enc_mac_key'] = base64_encode(x_or(sha1_20(bin($ss)), $shared_secret));
+
+                       break;
+
+               default:
+                       // Create the associate id and shared secret now
+                       list ($assoc_handle, $shared_secret) = new_assoc($lifetime);
+
+                       $keys['assoc_handle'] = $assoc_handle;
+                       $keys['mac_key'] = base64_encode($shared_secret);
+       }
+
+       // Return the keys
+       wrap_kv($keys);
+}
+
+
+/**
+ * Perform a user authorization
+ * @global array $profile
+ */
+function authorize_mode () {
+       global $profile;
+       global $USERNAME;
+
+       // this is a user session
+
+       // the user needs refresh urls in their session to access this mode
+       if (! isset($_SESSION['post_auth_url']) || ! isset($_SESSION['cancel_auth_url']))
+               error_500('You may not access this mode directly.');
+               
+       if (isset($_SERVER['PHP_AUTH_USER']) && $profile['authorized'] === false && $_SERVER['PHP_AUTH_USER']==$USERNAME) {
+               if (OC_USER::checkPassword($USERNAME, $_SERVER['PHP_AUTH_PW'])) {// successful login!
+
+                       // return to the refresh url if they get in
+                       $_SESSION['openid_auth']=true;
+                       $_SESSION['openid_user']=$USERNAME;
+                       wrap_redirect($_SESSION['post_auth_url']);
+
+               // failed login
+               } else {
+                       $_SESSION['failures']++;
+                       debug('Login failed');
+                       debug('Fail count: ' . $_SESSION['failures']);
+               }
+
+       }
+
+       // if we get this far the user is not authorized, so send the headers
+       $uid = uniqid(mt_rand(1,9));
+       $_SESSION['uniqid'] = $uid;
+
+//     debug('Prompting user to log in. Stale? ' . $stale);
+       header('HTTP/1.0 401 Unauthorized');
+//     header(sprintf('WWW-Authenticate: Digest qop="auth-int, auth", realm="%s", domain="%s", nonce="%s", opaque="%s", stale="%s", algorithm="MD5"', $profile['auth_realm'], $profile['auth_domain'], $uid, md5($profile['auth_realm']), $stale ? 'true' : 'false'));
+       header('WWW-Authenticate: Basic realm="ownCloud"');
+       $q = strpos($_SESSION['cancel_auth_url'], '?') ? '&' : '?';
+       wrap_refresh($_SESSION['cancel_auth_url'] . $q . 'openid.mode=cancel');
+//     die('401 Unauthorized');
+}
+
+
+/**
+ *  Handle a consumer's request for cancellation.
+ */
+function cancel_mode () {
+       wrap_html('Request cancelled.');
+}
+
+
+/**
+ * Handle a consumer's request to see if the user is authenticated
+ */
+function check_authentication_mode () {
+       // Validate the request
+       if (! isset($_REQUEST['openid_mode']) || $_REQUEST['openid_mode'] != 'check_authentication')
+               error_400();
+
+       $assoc_handle = @strlen($_REQUEST['openid_assoc_handle'])
+               ? $_REQUEST['openid_assoc_handle']
+               : error_post('Missing assoc_handle');
+
+       $sig = @strlen($_REQUEST['openid_sig'])
+               ? $_REQUEST['openid_sig']
+               : error_post('Missing sig');
+
+       $signed = @strlen($_REQUEST['openid_signed'])
+               ? $_REQUEST['openid_signed']
+               : error_post('Missing signed');
+
+       // Prepare the return keys
+       $keys = array(
+               'openid.mode' => 'id_res'
+       );
+
+       // Invalidate the assoc handle if we need to
+       if (@strlen($_REQUEST['openid_invalidate_handle'])) {
+               destroy_assoc_handle($_REQUEST['openid_invalidate_handle']);
+
+               $keys['invalidate_handle'] = $_REQUEST['openid_invalidate_handle'];
+       }
+
+       // Validate the sig by recreating the kv pair and signing
+       $_REQUEST['openid_mode'] = 'id_res';
+       $tokens = '';
+       foreach (explode(',', $signed) as $param) {
+               $post = preg_replace('/\./', '_', $param);
+               $tokens .= sprintf("%s:%s\n", $param, $_REQUEST['openid_' . $post]);
+       }
+
+       // Add the sreg stuff, if we've got it
+       if (isset($sreg_required)) {
+               foreach (explode(',', $sreg_required) as $key) {
+                       if (! isset($sreg[$key]))
+                               continue;
+                       $skey = 'sreg.' . $key;
+
+                       $tokens .= sprintf("%s:%s\n", $skey, $sreg[$key]);
+                       $keys[$skey] = $sreg[$key];
+                       $fields[] = $skey;
+               }
+       }
+
+       // Look up the consumer's shared_secret and timeout
+       list ($shared_secret, $expires) = secret($assoc_handle);
+
+       // if I can't verify the assoc_handle, or if it's expired
+       if ($shared_secret == false || (is_numeric($expires) && $expires < time())) {
+               $keys['is_valid'] = 'false';
+
+       } else {
+               $ok = base64_encode(hmac($shared_secret, $tokens));
+               $keys['is_valid'] = ($sig == $ok) ? 'true' : 'false';
+       }
+
+       // Return the keys
+       wrap_kv($keys);
+}
+
+
+/**
+ * Handle a consumer's request to see if the end user is logged in
+ * @global array $known
+ * @global array $profile
+ * @global array $sreg
+ */
+function checkid ( $wait ) {
+       global $known, $profile, $sreg;
+       global $USERNAME;
+
+       // This is a user session
+       user_session();
+
+       // Get the options, use defaults as necessary
+       $return_to = @strlen($_REQUEST['openid_return_to'])
+               ? $_REQUEST['openid_return_to']
+               : error_400('Missing return1_to');
+
+       $identity = @strlen($_REQUEST['openid_identity'])
+                       ? $_REQUEST['openid_identity']
+                       : error_get($return_to, 'Missing identity');
+
+       $assoc_handle = @strlen($_REQUEST['openid_assoc_handle'])
+                       ? $_REQUEST['openid_assoc.handle']
+                       : null;
+
+       $trust_root = @strlen($_REQUEST['openid_trust_root'])
+                       ? $_REQUEST['openid_trust_root']
+                       : $return_to;
+
+       $sreg_required = @strlen($_REQUEST['openid_sreg_required'])
+                       ? $_REQUEST['openid_sreg.required']
+                       : '';
+
+       $sreg_optional = @strlen($_REQUEST['openid_sreg_optional'])
+                       ? $_REQUEST['openid_sreg.optional']
+                       : '';
+
+       // determine the cancel url
+       $q = strpos($return_to, '?') ? '&' : '?';
+       $cancel_url = $return_to . $q . 'openid.mode=cancel';
+
+       // required and optional make no difference to us
+       $sreg_required .= ',' . $sreg_optional;
+       // do the trust_root analysis
+       if ($trust_root != $return_to) {
+               // the urls are not the same, be sure return decends from trust
+               if (! url_descends($return_to, $trust_root))
+                       error_500('Invalid trust_root: "' . $trust_root . '"');
+
+       }
+
+       // transfer the user to the url accept mode if they're paranoid
+       if ($wait == 1 && isset($profile['paranoid']) && $profile['paranoid'] === true && (! session_is_registered('accepted_url') || $_SESSION['accepted_url'] != $trust_root)) {
+               $_SESSION['cancel_accept_url'] = $cancel_url;
+               $_SESSION['post_accept_url'] = $profile['req_url'];
+               $_SESSION['unaccepted_url'] = $trust_root;
+
+               debug('Transferring to acceptance mode.');
+               debug('Cancel URL: ' . $_SESSION['cancel_accept_url']);
+               debug('Post URL: ' . $_SESSION['post_accept_url']);
+
+               $q = strpos($profile['idp_url'], '?') ? '&' : '?';
+               wrap_redirect($profile['idp_url'] . $q . 'openid.mode=accept');
+       }
+       
+       // make sure i am this identifier
+       if ($identity != $profile['idp_url']) {
+               debug("Invalid identity: $identity");
+               debug("IdP URL: " . $profile['idp_url']);
+               error_get($return_to, "Invalid identity: '$identity'");
+       }
+
+       // begin setting up return keys
+       $keys = array(
+               'mode' => 'id_res'
+       );
+
+       // if the user is not logged in, transfer to the authorization mode
+       if ($_SESSION['openid_auth'] === false || $USERNAME != $_SESSION['openid_user']) {
+               // users can only be logged in to one url at a time
+               $_SESSION['auth_username'] = null;
+               $_SESSION['auth_url'] = null;
+
+               if ($wait) {
+                       unset($_SESSION['uniqid']);
+
+                       $_SESSION['cancel_auth_url'] = $cancel_url;
+                       $_SESSION['post_auth_url'] = $profile['req_url'];
+
+                       debug('Transferring to authorization mode.');
+                       debug('Cancel URL: ' . $_SESSION['cancel_auth_url']);
+                       debug('Post URL: ' . $_SESSION['post_auth_url']);
+
+                       $q = strpos($profile['idp_url'], '?') ? '&' : '?';
+                       wrap_redirect($profile['idp_url'] . $q . 'openid.mode=authorize');
+               } else {
+                       $keys['user_setup_url'] = $profile['idp_url'];
+               }
+
+       // the user is logged in
+       } else {
+               // remove the refresh URLs if set
+               unset($_SESSION['cancel_auth_url']);
+               unset($_SESSION['post_auth_url']);
+
+               // check the assoc handle
+               list($shared_secret, $expires) = secret($assoc_handle);
+
+               // if I can't verify the assoc_handle, or if it's expired
+               if ($shared_secret == false || (is_numeric($expires) && $expires < time())) {
+                       debug("Session expired or missing key: $expires < " . time());
+                       if ($assoc_handle != null) {
+                               $keys['invalidate_handle'] = $assoc_handle;
+                               destroy_assoc_handle($assoc_handle);
+                       }
+
+                       $lifetime = time() + $profile['lifetime'];
+                       list ($assoc_handle, $shared_secret) = new_assoc($lifetime);
+               }
+
+               $keys['identity'] = $profile['idp_url'];
+               $keys['assoc_handle'] = $assoc_handle;
+               $keys['return_to'] = $return_to;
+
+               $fields = array_keys($keys);
+               $tokens = '';
+               foreach ($fields as $key)
+                       $tokens .= sprintf("%s:%s\n", $key, $keys[$key]);
+
+               // add sreg keys
+               foreach (explode(',', $sreg_required) as $key) {
+                       if (! isset($sreg[$key]))
+                               continue;
+                       $skey = 'sreg.' . $key;
+
+                       $tokens .= sprintf("%s:%s\n", $skey, $sreg[$key]);
+                       $keys[$skey] = $sreg[$key];
+                       $fields[] = $skey;
+               }
+
+               $keys['signed'] = implode(',', $fields);
+               $keys['sig'] = base64_encode(hmac($shared_secret, $tokens));
+       }
+
+       wrap_keyed_redirect($return_to, $keys);
+}
+
+
+/**
+ * Handle a consumer's request to see if the user is already logged in
+ */
+function checkid_immediate_mode () {
+       if (! isset($_REQUEST['openid_mode']) || $_REQUEST['openid_mode'] != 'checkid_immediate')
+               error_500();
+
+       checkid(false);
+}
+
+
+/**
+ * Handle a consumer's request to see if the user is logged in, but be willing
+ * to wait for them to perform a login if they're not
+ */
+function checkid_setup_mode () {
+       if (! isset($_REQUEST['openid_mode']) || $_REQUEST['openid_mode'] != 'checkid_setup')
+               error_500();
+
+       checkid(true);
+}
+
+
+/**
+ * Handle errors
+ */
+function error_mode () {
+       isset($_REQUEST['openid_error']) 
+               ? wrap_html($_REQUEST['openid_error'])
+               : error_500();
+}
+
+
+/**
+ * Show a user if they are logged in or not
+ * @global array $profile
+ */
+function id_res_mode () {
+       global $profile;
+
+       user_session();
+
+       if ($profile['authorized'])
+               wrap_html('You are logged in as ' . $_SESSION['auth_username']);
+
+       wrap_html('You are not logged in');
+}
+
+
+/**
+ * Allow a user to perform a static login
+ * @global array $profile
+ */
+function login_mode () {
+       global $profile;
+
+       user_session();
+
+       if ($profile['authorized'])
+               id_res_mode();
+
+       $keys = array(
+               'mode' => 'checkid_setup',
+               'identity' => $profile['idp_url'],
+               'return_to' => $profile['idp_url']
+       );
+
+       wrap_keyed_redirect($profile['idp_url'], $keys);
+}
+
+
+/**
+ * Allow a user to perform a static logout
+ * @global array $profile
+ */
+function logout_mode () {
+       global $profile;
+
+       user_session();
+
+       if (! $profile['authorized'])
+               wrap_html('You were not logged in');
+
+       $_SESSION = array();
+       session_destroy();
+       debug('User session destroyed.');
+
+       header('HTTP/1.0 401 Unauthorized');
+       wrap_redirect($profile['idp_url']);
+}
+
+
+/**
+ * The default information screen
+ * @global array $profile
+ */
+function no_mode () {
+       global $profile;
+
+       wrap_html('This is an OpenID server endpoint. For more information, see http://openid.net/<br/>Server: <b>' . $profile['idp_url'] . '</b><br/>Realm: <b>' . $profile['php_realm'] . '</b><br/><a href="' . $profile['idp_url'] . '?openid.mode=login">Login</a>' . ($profile['allow_test'] === true ? ' | <a href="' . $profile['idp_url'] . '?openid.mode=test">Test</a>' : null));
+}
+
+
+/**
+ * Testing for setup
+ * @global array $profile
+ */
+function test_mode () {
+       global $profile, $p, $g;
+
+       if ($profile['allow_test'] != true)
+               error_403();
+
+       @ini_set('max_execution_time', 180);
+
+       $test_expire = time() + 120;
+       $test_ss_enc = 'W7hvmld2yEYdDb0fHfSkKhQX+PM=';
+       $test_ss = base64_decode($test_ss_enc);
+       $test_token = "alpha:bravo\ncharlie:delta\necho:foxtrot";
+       $test_server_private = '11263846781670293092494395517924811173145217135753406847875706165886322533899689335716152496005807017390233667003995430954419468996805220211293016296351031812246187748601293733816011832462964410766956326501185504714561648498549481477143603650090931135412673422192550825523386522507656442905243832471167330268';
+       $test_client_public = base64_decode('AL63zqI5a5p8HdXZF5hFu8p+P9GOb816HcHuvNOhqrgkKdA3fO4XEzmldlb37nv3+xqMBgWj6gxT7vfuFerEZLBvuWyVvR7IOGZmx0BAByoq3fxYd3Fpe2Coxngs015vK37otmH8e83YyyGo5Qua/NAf13yz1PVuJ5Ctk7E+YdVc');
+
+       $res = array();
+
+       // bcmath
+       $res['bcmath'] = extension_loaded('bcmath')
+               ? 'pass' : 'warn - not loaded';
+
+       // gmp
+       if ($profile['allow_gmp']) {
+               $res['gmp'] = extension_loaded('gmp')
+               ? 'pass' : 'warn - not loaded';
+       } else {
+               $res['gmp'] = 'pass - n/a';
+       }
+
+       // sys_get_temp_dir
+       $res['logfile'] = is_writable($profile['logfile'])
+               ? 'pass' : "warn - log is not writable";
+
+       // session & new_assoc
+       user_session();
+       list($test_assoc, $test_new_ss) = new_assoc($test_expire);
+       $res['session'] = ($test_assoc != session_id())
+               ? 'pass' : 'fail';
+
+       // secret
+       @session_unregister('shared_secret');
+       list($check, $check2) = secret($test_assoc);
+       $res['secret'] = ($check == $test_new_ss)
+               ? 'pass' : 'fail';
+
+       // expire
+       $res['expire'] = ($check2 <= $test_expire)
+               ? 'pass' : 'fail';
+
+       // base64
+       $res['base64'] = (base64_encode($test_ss) == $test_ss_enc)
+               ? 'pass' : 'fail';
+
+       // hmac
+       $test_sig = base64_decode('/VXgHvZAOdoz/OTa5+XJXzSGhjs=');
+       $check = hmac($test_ss, $test_token);
+       $res['hmac'] = ($check == $test_sig)
+               ? 'pass' : sprintf("fail - '%s'", base64_encode($check));
+
+       if ($profile['use_bigmath']) {
+               // bigmath powmod
+               $test_server_public = '102773334773637418574009974502372885384288396853657336911033649141556441102566075470916498748591002884433213640712303846640842555822818660704173387461364443541327856226098159843042567251113889701110175072389560896826887426539315893475252988846151505416694218615764823146765717947374855806613410142231092856731';
+               $check = bmpowmod($g, $test_server_private, $p);
+               $res['bmpowmod-1'] = ($check == $test_server_public)
+                       ? 'pass' : sprintf("fail - '%s'", $check);
+
+               // long
+               $test_client_long = '133926731803116519408547886573524294471756220428015419404483437186057383311250738749035616354107518232016420809434801736658109316293127101479053449990587221774635063166689561125137927607200322073086097478667514042144489248048756916881344442393090205172004842481037581607299263456852036730858519133859409417564';
+               $res['long'] = (long($test_client_public) == $test_client_long)
+                       ? 'pass' : 'fail';
+
+               // bigmath powmod 2
+               $test_client_share = '19333275433742428703546496981182797556056709274486796259858099992516081822015362253491867310832140733686713353304595602619444380387600756677924791671971324290032515367930532292542300647858206600215875069588627551090223949962823532134061941805446571307168890255137575975911397744471376862555181588554632928402';
+               $check = bmpowmod($test_client_long, $test_server_private, $p);
+               $res['bmpowmod-2'] = ($check == $test_client_share)
+                       ? 'pass' : sprintf("fail - '%s'", $check);
+
+               // bin
+               $test_client_mac_s1 = base64_decode('G4gQQkYM6QmAzhKbVKSBahFesPL0nL3F2MREVwEtnVRRYI0ifl9zmPklwTcvURt3QTiGBd+9Dn3ESLk5qka6IO5xnILcIoBT8nnGVPiOZvTygfuzKp4tQ2mXuIATJoa7oXRGmBWtlSdFapH5Zt6NJj4B83XF/jzZiRwdYuK4HJI=');
+               $check = bin($test_client_share);
+               $res['bin'] = ($check == $test_client_mac_s1)
+                       ? 'pass' : sprintf("fail - '%s'", base64_encode($check));
+
+       } else {
+               $res['bigmath'] = 'fail - big math functions are not available.';
+       }
+
+       // sha1_20
+       $test_client_mac_s1 = base64_decode('G4gQQkYM6QmAzhKbVKSBahFesPL0nL3F2MREVwEtnVRRYI0ifl9zmPklwTcvURt3QTiGBd+9Dn3ESLk5qka6IO5xnILcIoBT8nnGVPiOZvTygfuzKp4tQ2mXuIATJoa7oXRGmBWtlSdFapH5Zt6NJj4B83XF/jzZiRwdYuK4HJI=');
+       $test_client_mac_s2 = base64_decode('0Mb2t9d/HvAZyuhbARJPYdx3+v4=');
+       $check = sha1_20($test_client_mac_s1);
+       $res['sha1_20'] = ($check == $test_client_mac_s2)
+               ? 'pass' : sprintf("fail - '%s'", base64_encode($check));
+
+       // x_or
+       $test_client_mac_s3 = base64_decode('i36ZLYAJ1rYEx1VEHObrS8hgAg0=');
+       $check = x_or($test_client_mac_s2, $test_ss);
+       $res['x_or'] = ($check == $test_client_mac_s3)
+               ? 'pass' : sprintf("fail - '%s'", base64_encode($check));
+
+       $out = "<table border=1 cellpadding=4>\n";
+       foreach ($res as $test => $stat) {
+               $code = substr($stat, 0, 4);
+               $color = ($code == 'pass') ? '#9f9'
+                       : (($code == 'warn') ? '#ff9' : '#f99');
+               $out .= sprintf("<tr><th>%s</th><td style='background:%s'>%s</td></tr>\n", $test, $color, $stat);
+       }
+       $out .= "</table>";
+
+       wrap_html( $out );
+}
+
+
+// Support functions
+
+/**
+ * Prefix the keys of an array with  'openid.'
+ * @param array $array
+ * @return array
+ */
+function append_openid ($array) {
+       $keys = array_keys($array);
+       $vals = array_values($array);
+
+       $r = array();
+       for ($i=0; $i<sizeof($keys); $i++)
+               $r['openid.' . $keys[$i]] = $vals[$i];
+       return $r;
+}
+
+/**
+ * Create a big math addition function
+ * @param string $l
+ * @param string $r
+ * @return string
+ * @url http://www.icosaedro.it/bigint Inspired by
+ */
+function bmadd($l, $r) {
+       if (function_exists('bcadd'))
+               return bcadd($l, $r);
+
+       global $profile;
+       if ($profile['use_gmp'])
+               return gmp_strval(gmp_add($l, $r));
+
+       $l = strval($l); $r = strval($r);
+       $ll = strlen($l); $rl = strlen($r);
+       if ($ll < $rl) {
+               $l = str_repeat("0", $rl-$ll) . $l;
+               $o = $rl;
+
+       } elseif ( $ll > $rl ) {
+               $r = str_repeat("0", $ll-$rl) . $r;
+               $o = $ll;
+
+       } else {
+               $o = $ll;
+       }
+
+       $v = '';
+       $carry = 0;
+
+       for ($i = $o-1; $i >= 0; $i--) {
+               $d = (int)$l[$i] + (int)$r[$i] + $carry;
+               if ($d <= 9) {
+                       $carry = 0;
+
+               } else {
+                       $carry = 1;
+                       $d -= 10;
+               }
+               $v = (string) $d . $v;
+       }
+
+       if ($carry > 0)
+               $v = "1" . $v;
+
+       return $v;
+}
+
+/**
+ * Create a big math comparison function
+ * @param string $l
+ * @param string $r
+ * @return string
+ */
+function bmcomp($l, $r) {
+       if (function_exists('bccomp'))
+               return bccomp($l, $r);
+
+       global $profile;
+       if ($profile['use_gmp'])
+               return gmp_strval(gmp_cmp($l, $r));
+
+       $l = strval($l); $r = strval($r);
+       $ll = strlen($l); $lr = strlen($r);
+       if ($ll != $lr)
+               return ($ll > $lr) ? 1 : -1;
+
+       return strcmp($l, $r);
+}
+
+/**
+ * Create a big math division function
+ * @param string $l
+ * @param string $r
+ * @param int $z
+ * @return string
+ * @url http://www.icosaedro.it/bigint Inspired by
+ */
+function bmdiv($l, $r, $z = 0) {
+       if (function_exists('bcdiv'))
+               return ($z == 0) ? bcdiv($l, $r) : bcmod($l, $r);
+
+       global $profile;
+       if ($profile['use_gmp'])
+               return gmp_strval(($z == 0) ? gmp_div_q($l, $r) : gmp_mod($l, $r));
+
+       $l = strval($l); $r = strval($r);
+       $v = '0';
+
+       while (true) {
+               if( bmcomp($l, $r) < 0 )
+                       break;
+
+               $delta = strlen($l) - strlen($r);
+               if ($delta >= 1) {
+                       $zeroes = str_repeat("0", $delta);
+                       $r2 = $r . $zeroes;
+
+                       if (strcmp($l, $r2) >= 0) {
+                               $v = bmadd($v, "1" . $zeroes);
+                               $l = bmsub($l, $r2);
+
+                       } else {
+                               $zeroes = str_repeat("0", $delta - 1);
+                               $v = bmadd($v, "1" . $zeroes);
+                               $l = bmsub($l, $r . $zeroes);
+                       }
+
+               } else {
+                       $l = bmsub($l, $r);
+                       $v = bmadd($v, "1");
+               }
+       }
+
+       return ($z == 0) ? $v : $l;
+}
+
+/**
+ * Create a big math multiplication function
+ * @param string $l
+ * @param string $r
+ * @return string
+ * @url http://www.icosaedro.it/bigint Inspired by
+ */
+function bmmul($l, $r) {
+       if (function_exists('bcmul'))
+               return bcmul($l, $r);
+
+       global $profile;
+       if ($profile['use_gmp'])
+               return gmp_strval(gmp_mul($l, $r));
+
+       $l = strval($l); $r = strval($r);
+
+       $v = '0';
+       $z = '';
+
+       for( $i = strlen($r)-1; $i >= 0; $i-- ){
+               $bd = (int) $r[$i];
+               $carry = 0;
+               $p = "";
+               for( $j = strlen($l)-1; $j >= 0; $j-- ){
+                       $ad = (int) $l[$j];
+                       $pd = $ad * $bd + $carry;
+                       if( $pd <= 9 ){
+                               $carry = 0;
+                       } else {
+                               $carry = (int) ($pd / 10);
+                               $pd = $pd % 10;
+                       }
+                       $p = (string) $pd . $p;
+               }
+               if( $carry > 0 )
+                       $p = (string) $carry . $p;
+               $p = $p . $z;
+               $z .= "0";
+               $v = bmadd($v, $p);
+       }
+
+       return $v;
+}
+
+/**
+ * Create a big math modulus function
+ * @param string $value
+ * @param string $mod 
+ * @return string
+ */
+function bmmod( $value, $mod ) {
+       if (function_exists('bcmod'))
+               return bcmod($value, $mod);
+
+       global $profile;
+       if ($profile['use_gmp'])
+               return gmp_strval(gmp_mod($value, $mod));
+
+       $r = bmdiv($value, $mod, 1);
+       return $r;
+}
+
+/**
+ * Create a big math power function
+ * @param string $value
+ * @param string $exponent
+ * @return string
+ */
+function bmpow ($value, $exponent) {
+       if (function_exists('bcpow'))
+               return bcpow($value, $exponent);
+
+       global $profile;
+       if ($profile['use_gmp'])
+               return gmp_strval(gmp_pow($value, $exponent));
+
+       $r = '1';
+       while ($exponent) {
+               $r = bmmul($r, $value, 100);
+               $exponent--;
+       }
+       return (string)rtrim($r, '0.');
+}
+
+/**
+ * Create a big math 'powmod' function
+ * @param string $value
+ * @param string $exponent
+ * @param string $mod 
+ * @return string
+ * @url http://php.net/manual/en/function.bcpowmod.php#72704 Borrowed from
+ */
+function bmpowmod ($value, $exponent, $mod) {
+       if (function_exists('bcpowmod'))
+               return bcpowmod($value, $exponent, $mod);
+
+       global $profile;
+       if ($profile['use_gmp'])
+               return gmp_strval(gmp_powm($value, $exponent, $mod));
+
+       $r = '';
+       while ($exponent != '0') {
+               $t = bmmod($exponent, '4096');
+               $r = substr("000000000000" . decbin(intval($t)), -12) . $r;
+               $exponent = bmdiv($exponent, '4096');
+       }
+
+       $r = preg_replace("!^0+!","",$r);
+
+       if ($r == '')
+               $r = '0';
+       $value = bmmod($value, $mod);
+       $erb = strrev($r);
+       $q = '1';
+       $a[0] = $value;
+
+       for ($i = 1; $i < strlen($erb); $i++) {
+               $a[$i] = bmmod( bmmul($a[$i-1], $a[$i-1]), $mod );
+       }
+
+       for ($i = 0; $i < strlen($erb); $i++) {
+               if ($erb[$i] == "1") {
+                       $q = bmmod( bmmul($q, $a[$i]), $mod );
+               }
+       }
+
+       return($q);
+}
+
+/**
+ * Create a big math subtraction function
+ * @param string $l
+ * @param string $r
+ * @return string
+ * @url http://www.icosaedro.it/bigint Inspired by
+ */
+function bmsub($l, $r) {
+       if (function_exists('bcsub'))
+               return bcsub($l, $r);
+
+       global $profile;
+       if ($profile['use_gmp'])
+               return gmp_strval(gmp_sub($l, $r));
+
+
+       $l = strval($l); $r = strval($r);
+       $ll = strlen($l); $rl = strlen($r);
+
+       if ($ll < $rl) {
+               $l = str_repeat("0", $rl-$ll) . $l;
+               $o = $rl;
+       } elseif ( $ll > $rl ) {
+               $r = str_repeat("0", $ll-$rl) . (string)$r;
+               $o = $ll;
+       } else {
+               $o = $ll;
+       }
+
+       if (strcmp($l, $r) >= 0) {
+               $sign = '';
+       } else {
+               $x = $l; $l = $r; $r = $x;
+               $sign = '-';
+       }
+
+       $v = '';
+       $carry = 0;
+
+       for ($i = $o-1; $i >= 0; $i--) {
+               $d = ($l[$i] - $r[$i]) - $carry;
+               if ($d < 0) {
+                       $carry = 1;
+                       $d += 10;
+               } else {
+                       $carry = 0;
+               }
+               $v = (string) $d . $v;
+       }
+
+       return $sign . ltrim($v, '0');
+}
+
+
+/**
+ * Get a binary value
+ * @param integer $n
+ * @return string
+ * @url http://openidenabled.com Borrowed from PHP-OpenID
+ */
+function bin ($n) {
+       $bytes = array();
+       while (bmcomp($n, 0) > 0) {
+               array_unshift($bytes, bmmod($n, 256));
+               $n = bmdiv($n, bmpow(2,8));
+       }
+
+       if ($bytes && ($bytes[0] > 127))
+               array_unshift($bytes, 0);
+
+       $b = '';
+       foreach ($bytes as $byte)
+               $b .= pack('C', $byte);
+
+       return $b;
+}
+
+
+/**
+ * Debug logging
+ * @param mixed $x
+ * @param string $m 
+ */
+function debug ($x, $m = null) {
+       global $profile;
+
+       if (! isset($profile['debug']) || $profile['debug'] === false)
+               return true;
+
+       if (! is_writable(dirname($profile['logfile'])) &! is_writable($profile['logfile']))
+               error_500('Cannot write to debug log: ' . $profile['logfile']);
+
+       if (is_array($x)) {
+               ob_start();
+               print_r($x);
+               $x = $m . ($m != null ? "\n" : '') . ob_get_clean();
+
+       } else {
+               $x .= "\n";
+       }
+
+       error_log($x . "\n", 3, $profile['logfile']);
+}
+
+
+/**
+ * Destroy a consumer's assoc handle
+ * @param string $id
+ */
+function destroy_assoc_handle ( $id ) {
+       debug("Destroying session: $id");
+
+       $sid = session_id();
+       session_write_close();
+
+       session_id($id);
+       session_start();
+       session_destroy();
+
+       session_id($sid);
+       session_start();
+}
+
+
+/**
+ * Return an error message to the user
+ * @param string $message
+ */
+function error_400 ( $message = 'Bad Request' ) {
+       header("HTTP/1.1 400 Bad Request");
+       wrap_html($message);
+}
+
+
+/**
+ * Return an error message to the user
+ * @param string $message
+ */
+function error_403 ( $message = 'Forbidden' ) {
+       header("HTTP/1.1 403 Forbidden");
+       wrap_html($message);
+}
+
+
+/**
+ * Return an error message to the user
+ * @param string $message
+ */
+function error_500 ( $message = 'Internal Server Error' ) {
+       header("HTTP/1.1 500 Internal Server Error");
+       wrap_html($message);
+}
+
+
+/**
+ * Return an error message to the consumer
+ * @param string $message
+ */
+function error_get ( $url, $message = 'Bad Request') {
+       wrap_keyed_redirect($url, array('mode' => 'error', 'error' => $message));
+}
+
+
+/**
+ * Return an error message to the consumer
+ * @param string $message
+ */
+function error_post ( $message = 'Bad Request' ) {
+       header("HTTP/1.1 400 Bad Request");
+       echo ('error:' . $message);
+       exit(0);
+}
+
+
+/**
+ * Do an HMAC
+ * @param string $key
+ * @param string $data
+ * @param string $hash
+ * @return string
+ * @url http://php.net/manual/en/function.sha1.php#39492 Borrowed from
+ */
+function hmac($key, $data, $hash = 'sha1_20') {
+       $blocksize=64;
+
+       if (strlen($key) > $blocksize)
+               $key = $hash($key);
+
+       $key = str_pad($key, $blocksize,chr(0x00));
+       $ipad = str_repeat(chr(0x36),$blocksize);
+       $opad = str_repeat(chr(0x5c),$blocksize);
+
+       $h1 = $hash(($key ^ $ipad) . $data);
+       $hmac = $hash(($key ^ $opad) . $h1);
+       return $hmac;
+}
+
+
+if (! function_exists('http_build_query')) {
+/**
+ * Create function if missing
+ * @param array $array
+ * @return string
+ */
+function http_build_query ($array) {
+       $r = array();
+       foreach ($array as $key => $val)
+               $r[] = sprintf('%s=%s', urlencode($key), urlencode($val));
+       return implode('&', $r);
+}}
+
+
+/**
+ * Turn a binary back into a long
+ * @param string $b
+ * @return integer
+ * @url http://openidenabled.com Borrowed from PHP-OpenID
+ */
+function long($b) {
+       $bytes = array_merge(unpack('C*', $b));
+       $n = 0;
+       foreach ($bytes as $byte) {
+               $n = bmmul($n, bmpow(2,8));
+               $n = bmadd($n, $byte);
+       }
+       return $n;
+}
+
+
+/**
+ * Create a new consumer association
+ * @param integer $expiration
+ * @return array
+ */
+function new_assoc ( $expiration ) {
+       if (isset($_SESSION) && is_array($_SESSION)) {
+               $sid = session_id();
+               $dat = session_encode();
+               session_write_close();
+       }
+
+       session_start();
+       session_regenerate_id('false');
+
+       $id = session_id();
+       $shared_secret = new_secret();
+       debug('Started new assoc session: ' . $id);
+
+       $_SESSION = array();
+       $_SESSION['expiration'] = $expiration;
+       $_SESSION['shared_secret'] = base64_encode($shared_secret);
+
+       session_write_close();
+
+       if (isset($sid)) {
+               session_id($sid);
+               session_start();
+               $_SESSION = array();
+               session_decode($dat);
+       }
+
+       return array($id, $shared_secret);
+}
+
+
+/**
+ * Create a new shared secret
+ * @return string
+ */
+function new_secret () {
+       $r = '';
+       for($i=0; $i<20; $i++)
+               $r .= chr(mt_rand(0, 255));
+
+       debug("Generated new key: hash = '" . md5($r) . "', length = '" . strlen($r) . "'");
+       return $r;
+}
+
+
+/**
+ * Random number generation
+ * @param integer max
+ * @return integer
+ */
+function random ( $max ) {
+       if (strlen($max) < 4)
+               return mt_rand(1, $max - 1);
+
+       $r = '';
+       for($i=1; $i<strlen($max) - 1; $i++)
+               $r .= mt_rand(0,9);
+       $r .= mt_rand(1,9);
+
+       return $r;
+}
+
+/**
+ * Get the shared secret and expiration time for the specified assoc_handle
+ * @param string $handle assoc_handle to look up
+ * @return array (shared_secret, expiration_time)
+ */
+function secret ( $handle ) {
+       if (! preg_match('/^\w+$/', $handle))
+               return array(false, 0);
+
+       if (isset($_SESSION) && is_array($_SESSION)) {
+               $sid = session_id();
+               $dat = session_encode();
+               session_write_close();
+       }
+
+       session_id($handle);
+       session_start();
+       debug('Started session to acquire key: ' . session_id());
+
+       $secret = session_is_registered('shared_secret')
+               ? base64_decode($_SESSION['shared_secret'])
+               : false;
+
+       $expiration = session_is_registered('expiration')
+               ? $_SESSION['expiration']
+               : null;
+
+       session_write_close();
+
+       if (isset($sid)) {
+               session_id($sid);
+               session_start();
+               $_SESSION = array();
+               session_decode($dat);
+       }
+
+       debug("Found key: hash = '" . md5($secret) . "', length = '" . strlen($secret) . "', expiration = '$expiration'");
+       return array($secret, $expiration);
+}
+
+
+/**
+ * Do an internal self check
+ * @global array $profile
+ * @global array $sreg
+ */
+function self_check () {
+       global $profile, $sreg;
+
+//     if (! isset($profile) || ! is_array($profile))
+//             error_500('No configuration found, you shouldn\'t access this file directly.');
+
+       if (version_compare(phpversion(), '4.2.0', 'lt'))
+               error_500('The required minimum version of PHP is 4.2.0, you are running ' . phpversion());
+
+       $extension_r = array('session', 'pcre');
+       foreach ($extension_r as $x) {
+               if (! extension_loaded($x))
+                       @dl($x);
+               if (! extension_loaded($x))
+                       error_500("Required extension '$x' is missing.");
+       }
+
+//     $extension_b = array('suhosin');
+//     foreach ($extension_b as $x) {
+//             if (extension_loaded($x) &! $profile["allow_$x"])
+//                     error_500("phpMyID is not compatible with '$x'");
+//     }
+// 
+//     $keys = array('auth_username', 'auth_password');
+//     foreach ($keys as $key) {
+//             if (! array_key_exists($key, $profile))
+//                     error_500("'$key' is missing from your profile.");
+//     }
+
+       if (! isset($sreg) || ! is_array($sreg))
+               $sreg = array();
+}
+
+
+/**
+ * Do SHA1 20 byte encryption
+ * @param string $v
+ * @return string
+ * @url http://openidenabled.com Borrowed from PHP-OpenID
+ */
+function sha1_20 ($v) {
+       if (version_compare(phpversion(), '5.0.0', 'ge'))
+               return sha1($v, true);
+
+       $hex = sha1($v);
+       $r = '';
+       for ($i = 0; $i < 40; $i += 2) {
+               $hexcode = substr($hex, $i, 2);
+               $charcode = base_convert($hexcode, 16, 10);
+               $r .= chr($charcode);
+       }
+       return $r;
+}
+
+
+/**
+ * Look for the point of differentiation in two strings
+ * @param string $a
+ * @param string $b
+ * @return int
+ */
+function str_diff_at ($a, $b) {
+       if ($a == $b)
+               return -1;
+       $n = min(strlen($a), strlen($b));
+       for ($i = 0; $i < $n; $i++)
+               if ($a[$i] != $b[$i])
+                       return $i;
+       return $n;
+}
+
+
+if (! function_exists('sys_get_temp_dir') && ini_get('open_basedir') == false) {
+/**
+ * Create function if missing
+ * @return string
+ */
+function sys_get_temp_dir () {
+       $keys = array('TMP', 'TMPDIR', 'TEMP');
+       foreach ($keys as $key) {
+               if (isset($_ENV[$key]) && is_dir($_ENV[$key]) && is_writable($_ENV[$key]))
+                       return realpath($_ENV[$key]);
+       }
+
+       $tmp = tempnam(false, null);
+       if (file_exists($tmp)) {
+               $dir = realpath(dirname($tmp));
+               unlink($tmp);
+               return realpath($dir);
+       }
+
+       return realpath(dirname(__FILE__));
+}} elseif (! function_exists('sys_get_temp_dir')) {
+function sys_get_temp_dir () {
+       return realpath(dirname(__FILE__));
+}}
+
+
+/**
+ * Determine if a child URL actually decends from the parent, and that the
+ * parent is a good URL.
+ * THIS IS EXPERIMENTAL
+ * @param string $parent
+ * @param string $child
+ * @return bool
+ */
+function url_descends ( $child, $parent ) {
+       if ($child == $parent)
+               return true;
+
+       $keys = array();
+       $parts = array();
+
+       $req = array('scheme', 'host');
+       $bad = array('fragment', 'pass', 'user');
+
+       foreach (array('parent', 'child') as $name) {
+               $parts[$name] = @parse_url($$name);
+               if ($parts[$name] === false)
+                       return false;
+
+               $keys[$name] = array_keys($parts[$name]);
+
+               if (array_intersect($keys[$name], $req) != $req)
+                       return false;
+
+               if (array_intersect($keys[$name], $bad) != array())
+                       return false;
+
+               if (! preg_match('/^https?$/i', strtolower($parts[$name]['scheme'])))
+                       return false;
+
+               if (! array_key_exists('port', $parts[$name]))
+                       $parts[$name]['port'] = (strtolower($parts[$name]['scheme']) == 'https') ? 443 : 80;
+
+               if (! array_key_exists('path', $parts[$name]))
+                       $parts[$name]['path'] = '/';
+       }
+
+       // port and scheme must match
+       if ($parts['parent']['scheme'] != $parts['child']['scheme'] ||
+           $parts['parent']['port'] != $parts['child']['port'])
+               return false;
+
+       // compare the hosts by reversing the strings
+       $cr_host = strtolower(strrev($parts['child']['host']));
+       $pr_host = strtolower(strrev($parts['parent']['host']));
+
+       $break = str_diff_at($cr_host, $pr_host);
+       if ($break >= 0 && ($pr_host[$break] != '*' || substr_count(substr($pr_host, 0, $break), '.') < 2))
+               return false;
+
+       // now compare the paths
+       $break = str_diff_at($parts['child']['path'], $parts['parent']['path']);
+       if ($break >= 0
+          && ($break < strlen($parts['parent']['path']) && $parts['parent']['path'][$break] != '*')
+          || ($break > strlen($parts['child']['path'])))
+               return false;
+
+       return true;
+}
+
+
+/**
+ * Create a user session
+ * @global array $profile
+ * @global array $proto
+ */
+function user_session () {
+       global $proto, $profile;
+
+       session_name('phpMyID_Server');
+       @session_start();
+
+       $profile['authorized'] = (isset($_SESSION['auth_username'])
+                           && $_SESSION['auth_username'] == $profile['auth_username'])
+                       ? true
+                       : false;
+
+       debug('Started user session: ' . session_id() . ' Auth? ' . $profile['authorized']);
+}
+
+
+/**
+ * Return HTML
+ * @global string $charset
+ * @param string $message
+ */
+function wrap_html ( $message ) {
+       global $charset, $profile;
+       header('Content-Type: text/html; charset=' . $charset);
+       $html= '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<head>
+<title>phpMyID</title>
+<link rel="openid.server" href="' . $profile['req_url'] . '" />
+<link rel="openid.delegate" href="' . $profile['idp_url'] . '" />
+' . implode("\n", $profile['opt_headers']) . '
+<meta name="charset" content="' . $charset . '" />
+<meta name="robots" content="noindex,nofollow" />
+</head>
+<body>
+<p>' . $message . '</p>
+</body>
+</html>
+';
+       error_log($html);
+       echo $html;
+       exit(0);
+}
+
+
+/**
+ * Return a key-value pair in plain text
+ * @global string $charset
+ * @param array $keys
+ */
+function wrap_kv ( $keys ) {
+       global $charset;
+
+       debug($keys, 'Wrapped key/vals');
+       header('Content-Type: text/plain; charset=' . $charset);
+       foreach ($keys as $key => $value)
+               printf("%s:%s\n", $key, $value);
+
+       exit(0);
+}
+
+
+/**
+ * Redirect, with OpenID keys
+ * @param string $url
+ * @param array @keys
+ */
+function wrap_keyed_redirect ($url, $keys) {
+       $keys = append_openid($keys);
+       debug($keys, 'Location keys');
+
+       $q = strpos($url, '?') ? '&' : '?';
+       wrap_redirect($url . $q . http_build_query($keys));
+}
+
+
+/**
+ * Redirect the browser
+ * @global string $charset
+ * @param string $url
+ */
+function wrap_redirect ($url) {
+       header('HTTP/1.1 302 Found');
+       header('Location: ' . $url);
+       debug('Location: ' . $url);
+       exit(0);
+}
+
+/**
+ * Return an HTML refresh
+ * @global string $charset
+ * @param string $url
+ */
+function wrap_refresh ($url) {
+       global $charset;
+
+       header('Content-Type: text/html; charset=' . $charset);
+       echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<head>
+<title>phpMyID</title>
+<meta http-equiv="refresh" content="0;url=' . $url . '">
+</head>
+<body>
+<p>Redirecting to <a href="' . $url . '">' . $url . '</a></p>
+</body>
+</html>
+';
+
+       debug('Refresh: ' . $url);
+       exit(0);
+}
+
+
+/**
+ * Implement binary x_or
+ * @param string $a
+ * @param string $b
+ * @return string
+ */
+function x_or ($a, $b) {
+       $r = "";
+
+       for ($i = 0; $i < strlen($b); $i++)
+               $r .= $a[$i] ^ $b[$i];
+       debug("Xor size: " . strlen($r));
+       return $r;
+}
+
+
+
+/*
+ * App Initialization
+ */
+// Determine the charset to use
+$GLOBALS['charset'] = 'iso-8859-1';
+
+// Set the internal encoding
+if (function_exists('mb_internal_encoding'))
+       mb_internal_encoding($charset);
+
+// Avoid problems with non-default arg_separator.output settings
+// Credit for this goes to user 'prelog' on the forums
+ini_set('arg_separator.output', '&');
+
+// Do a check to be sure everything is set up correctly
+self_check();
+
+
+/**
+ * Determine the HTTP request port
+ * @name $port
+ * @global integer $GLOBALS['port']
+ */
+$GLOBALS['port'] = ((isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == 'on' && $_SERVER['SERVER_PORT'] == 443)
+         || $_SERVER['SERVER_PORT'] == 80)
+               ? ''
+               : ':' . $_SERVER['SERVER_PORT'];
+
+
+error_log($_SERVER['HTTP_HOST']);
+/**
+ * Determine the HTTP request protocol
+ * @name $proto
+ * @global string $GLOBALS['proto']
+ */
+$GLOBALS['proto'] = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == 'on') ? 'https' : 'http';
+
+// Set the authorization state - DO NOT OVERRIDE
+$profile['authorized'] = false;
+
+// Set a default IDP URL
+if (! array_key_exists('idp_url', $profile))
+       $profile['idp_url'] = sprintf("%s://%s%s%s",
+                             $proto,
+                             $_SERVER['SERVER_NAME'],
+                             $port,
+                             $_SERVER['PHP_SELF']);
+
+// Determine the requested URL - DO NOT OVERRIDE
+$profile['req_url'] = sprintf("%s://%s%s",
+                     $proto,
+                     $_SERVER['HTTP_HOST'],
+//                   $port,//host  already includes the path
+                     $_SERVER["REQUEST_URI"]);
+
+error_log($profile['req_url']);
+
+// Set the default allowance for testing
+if (! array_key_exists('allow_test', $profile))
+       $profile['allow_test'] = false;
+
+// Set the default allowance for gmp
+if (! array_key_exists('allow_gmp', $profile))
+       $profile['allow_gmp'] = false;
+
+// Set the default force bigmath - BAD IDEA to override this
+if (! array_key_exists('force_bigmath', $profile))
+       $profile['force_bigmath'] = false;
+
+// Determine if GMP is usable
+$profile['use_gmp'] = (extension_loaded('gmp') && $profile['allow_gmp']) ? true : false;
+
+// Determine if I can perform big math functions
+$profile['use_bigmath'] = (extension_loaded('bcmath') || $profile['use_gmp'] || $profile['force_bigmath']) ? true : false;
+
+// Set a default authentication domain
+if (! array_key_exists('auth_domain', $profile))
+       $profile['auth_domain'] = $profile['req_url'] . ' ' . $profile['idp_url'];
+
+// Set a default authentication realm
+if (! array_key_exists('auth_realm', $profile))
+       $profile['auth_realm'] = 'phpMyID';
+
+// Determine the realm for digest authentication - DO NOT OVERRIDE
+$profile['php_realm'] = $profile['auth_realm'] . (ini_get('safe_mode') ? '-' . getmyuid() : '');
+
+// Set a default lifetime - the lesser of GC and cache time
+if (! array_key_exists('lifetime', $profile)) {
+       $sce = session_cache_expire() * 60;
+       $gcm = ini_get('session.gc_maxlifetime');
+       $profile['lifetime'] = $sce < $gcm ? $sce : $gcm;
+}
+
+// Set a default log file
+if (! array_key_exists('logfile', $profile))
+       $profile['logfile'] = sys_get_temp_dir() . DIRECTORY_SEPARATOR . $profile['auth_realm'] . '.debug.log';
+
+
+/*
+ * Optional Initialization
+ */
+// Setup optional headers
+$profile['opt_headers'] = array();
+
+// Determine if I should add microid stuff
+if (array_key_exists('microid', $profile)) {
+       $hash = sha1($profile['idp_url']);
+       $values = is_array($profile['microid']) ? $profile['microid'] : array($profile['microid']);
+
+       foreach ($values as $microid) {
+               preg_match('/^([a-z]+)/i', $microid, $mtx);
+               $profile['opt_headers'][] = sprintf('<meta name="microid" content="%s+%s:sha1:%s" />', $mtx[1], $proto, sha1(sha1($microid) . $hash));
+       }
+}
+
+// Determine if I should add pavatar stuff
+if (array_key_exists('pavatar', $profile))
+       $profile['opt_headers'][] = sprintf('<link rel="pavatar" href="%s" />', $profile['pavatar']);
+
+
+/*
+ * Do it
+ */
+// Decide which runmode, based on user request or default
+$run_mode = (isset($_REQUEST['openid_mode'])
+         && in_array($_REQUEST['openid_mode'], $known['openid_modes']))
+       ? $_REQUEST['openid_mode']
+       : 'no';
+
+// Run in the determined runmode
+debug("Run mode: $run_mode at: " . time());
+debug($_REQUEST, 'Request params');
+call_user_func($run_mode . '_mode');
+?>
diff --git a/apps/user_openid/settings.php b/apps/user_openid/settings.php
new file mode 100644 (file)
index 0000000..76316de
--- /dev/null
@@ -0,0 +1,24 @@
+<?php
+
+require_once('../../lib/base.php');
+require( 'template.php' );
+if( !OC_USER::isLoggedIn()){
+    header( "Location: ".OC_HELPER::linkTo( "index.php" ));
+    exit();
+}
+
+if(isset($_POST['input_identity'])){
+       OC_PREFERENCES::setValue(OC_USER::getUser(),'user_openid','identity',$_POST['input_identity']);
+}
+
+OC_APP::setActiveNavigationEntry( "user_openid_settings" );
+
+$identity=OC_PREFERENCES::getValue(OC_USER::getUser(),'user_openid','identity','');
+
+$tmpl = new OC_TEMPLATE( "user_openid", "settings", "admin");
+$tmpl->assign('identity',$identity);
+$tmpl->assign('user',OC_USER::getUser());
+
+$tmpl->printPage();
+
+?>
diff --git a/apps/user_openid/templates/settings.php b/apps/user_openid/templates/settings.php
new file mode 100644 (file)
index 0000000..7a1b530
--- /dev/null
@@ -0,0 +1,7 @@
+<form id="identity" action='#' method='post'>
+       <fieldset>
+               <legend><?php echo $l->t( 'OpenID identity' );?></legend>
+               <label for='input_identity'>OpenID identity for <b><?php echo $_['user'];?></b></label><br/>
+               <input name='input_identity' id='input_identity' value="<?php echo $_['identity'];?>"/><input type='submit' value='Save'/>
+       </fieldset>
+</form>
diff --git a/apps/user_openid/user.php b/apps/user_openid/user.php
new file mode 100644 (file)
index 0000000..9ca1fd4
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+
+/**
+* ownCloud
+*
+* @author Robin Appelman
+* @copyright 2011 Robin Appelman icewind1991@gmail.com
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the License, or any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+$USERNAME=substr($_SERVER["REQUEST_URI"],strpos($_SERVER["REQUEST_URI"],'.php/')+5);
+if(strpos($USERNAME,'?')){
+       $USERNAME=substr($USERNAME,0,strpos($USERNAME,'?'));
+}
+
+require_once '../../lib/base.php';
+
+require_once 'phpmyid.php';
+
+
+?>
\ No newline at end of file
diff --git a/apps/user_openid/user_openid.php b/apps/user_openid/user_openid.php
new file mode 100644 (file)
index 0000000..d4bcefe
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+
+/**
+ * ownCloud
+ *
+ * @author Robin Appelman
+ * @copyright 2011 Robin Appelman icewind1991gmailc.om
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+require_once('User/backend.php');
+require_once('class.openid.v3.php');
+
+/**
+ * Class for user management in a SQL Database (e.g. MySQL, SQLite)
+ */
+class OC_USER_OPENID extends OC_USER_BACKEND {
+       /**
+        * @brief Check if the password is correct
+        * @param $uid The username
+        * @param $password The password
+        * @returns true/false
+        *
+        * Check if the password is correct without logging in the user
+        */
+       public function checkPassword( $uid, $password ){
+               global $WEBROOT;
+               // Get identity from user and redirect browser to OpenID Server
+               $openid = new SimpleOpenID;
+               $openid->SetIdentity($uid);
+               $openid->SetTrustRoot('http://' . $_SERVER["HTTP_HOST"]);
+               if ($openid->GetOpenIDServer()){
+                       $openid->SetApprovedURL('http://' . $_SERVER["HTTP_HOST"] . $WEBROOT);      // Send Response from OpenID server to this script
+                       $openid->Redirect();     // This will redirect user to OpenID Server
+                       exit;
+               }else{
+                       $error = $openid->GetError();
+                       echo "ERROR CODE: " . $error['code'] . "<br>";
+                       echo "ERROR DESCRIPTION: " . $error['description'] . "<br>";
+               }
+               exit;
+       }
+       
+       /**
+        * find the user that can be authenticated with an openid identity
+        */
+       public static function findUserForIdentity($identity){
+               $query=OC_DB::prepare('SELECT userid FROM *PREFIX*preferences WHERE appid=? AND configkey=? AND configvalue=?');
+               $result=$query->execute(array('user_openid','identity',$identity))->fetchAll();
+               if(count($result)>0){
+                       return $result[0]['userid'];
+               }else{
+                       return false;
+               }
+       }
+}
+
+
+
+?>
\ No newline at end of file