OSDN Git Service

v1.1.1
authorhsur <hsur@1ca29b6e-896d-4ea0-84a5-967f57386b96>
Tue, 10 Jun 2008 14:35:12 +0000 (14:35 +0000)
committerhsur <hsur@1ca29b6e-896d-4ea0-84a5-967f57386b96>
Tue, 10 Jun 2008 14:35:12 +0000 (14:35 +0000)
git-svn-id: https://svn.sourceforge.jp/svnroot/nucleus-jp/plugin@630 1ca29b6e-896d-4ea0-84a5-967f57386b96

16 files changed:
trunk/NP_OpenId/NP_OpenId.php
trunk/NP_OpenId/openid/help.html
trunk/NP_OpenId/openid/language/english.php [new file with mode: 0644]
trunk/NP_OpenId/openid/language/japanese-euc.php [new file with mode: 0644]
trunk/NP_OpenId/openid/language/japanese-utf8.php [new file with mode: 0644]
trunk/NP_OpenId/openid/template/np_openid/updatefailed_english.html [deleted file]
trunk/NP_OpenId/openid/template/np_openid/updatesucceeded_english.html [deleted file]
trunk/NP_OpenId/openid/template/np_openid/updatesucceeded_japanese-euc.html [deleted file]
trunk/NP_OpenId/openid/template/np_openid/updatesucceeded_japanese-utf8.html [deleted file]
trunk/NP_OpenId/openid/template/np_openid/yui_english.html
trunk/NP_OpenId/sharedlibs/Jsphon.php [new file with mode: 0644]
trunk/NP_OpenId/sharedlibs/Jsphon/Decoder.php [new file with mode: 0644]
trunk/NP_OpenId/sharedlibs/Jsphon/Decoder/Tokenizer.php [new file with mode: 0644]
trunk/NP_OpenId/sharedlibs/Jsphon/Encoder.php [new file with mode: 0644]
trunk/NP_OpenId/sharedlibs/Jsphon/Error.php [new file with mode: 0644]
trunk/NP_OpenId/sharedlibs/Jsphon/Exception.php [new file with mode: 0644]

index f64f875..778f839 100644 (file)
@@ -2,9 +2,9 @@
 // vim: tabstop=2:shiftwidth=2
 
 /**
-  * NP_OpenId ($Revision: 1.2 $)
+  * NP_OpenId ($Revision: 1.3 $)
   * by hsur ( http://blog.cles.jp/np_cles )
-  * $Id: NP_OpenId.php,v 1.2 2008-06-07 19:33:43 hsur Exp $
+  * $Id: NP_OpenId.php,v 1.3 2008-06-10 14:35:12 hsur Exp $
   *
 */
 
@@ -50,6 +50,7 @@ require_once 'Auth/OpenID/Consumer.php';
 require_once 'cles/SQLStoreForNucleus.php';
 require_once 'Auth/OpenID/SReg.php';
 require_once 'Auth/OpenID/PAPE.php';
+require_once 'Jsphon.php';
 
 class NP_OpenId extends NucleusPlugin {
 
@@ -63,7 +64,7 @@ class NP_OpenId extends NucleusPlugin {
                return 'http://blog.cles.jp/np_cles/category/31/subcatid/21';
        }
        function getVersion() {
-               return '1.1.0';
+               return '1.1.1';
        }
        function getMinNucleusVersion() {
                return 330;
@@ -84,7 +85,7 @@ class NP_OpenId extends NucleusPlugin {
                );
        }
        function getDescription() {
-               return '[$Revision: 1.2 $]<br />Adds OpenID authentication to anonymous comment, to prevent robots from spamming.';
+               return '[$Revision: 1.3 $]<br />Adds OpenID authentication to anonymous comment, to prevent robots from spamming.';
        }
        function supportsFeature($what) {
                switch ($what) {
@@ -107,6 +108,12 @@ class NP_OpenId extends NucleusPlugin {
                @mkdir($store_path);
                $this->store = new Auth_OpenID_FileStore($store_path);
 */
+               // include language file for this plugin 
+               $language = ereg_replace( '[\\|/]', '', getLanguageName()); 
+               if (file_exists($this->getDirectory().'language/'.$language.'.php')) 
+                       @ include_once($this->getDirectory().'language/'.$language.'.php');
+               else
+                       @ include_once($this->getDirectory().'language/english.php');
 
                $this->store = new cles_SQLStoreForNucleus();
                $this->consumer = new Auth_OpenID_Consumer($this->store);
@@ -198,7 +205,6 @@ class NP_OpenId extends NucleusPlugin {
                                break;
                        
                        case 'updateProfile':
-                               $te = $this->_getTemplateEngine();
                                $aVars = array();
                                if( $this->isLoggedin() ){
                                        $profile = array();
@@ -206,11 +212,17 @@ class NP_OpenId extends NucleusPlugin {
                                        $aVars['email'] = requestVar('email');
                                        
                                        $this->_doUpdateProfile($aVars);
-                                       echo $te->fetchAndFill('updatesucceeded', $aVars, strtolower(__CLASS__));
+                                       
+                                       $aVars['message'] = NP_OPENID_updateSucceeded;
+                                       $aVars['result'] = 'succeeded';
                                } else {
-                                       $aVars['message'] = 'You aren\'t logged in.';
-                                       echo $te->fetchAndFill('updatefailed', $aVars, strtolower(__CLASS__));
+                                       $aVars['message'] = NP_OPENID_notloggedin;
+                                       $aVars['result'] = 'failure';
                                }
+                               
+                               // return JSON
+                               if(_CHARSET != 'UTF-8') mb_convert_variables('UTF-8', _CHARSET, $aVars);
+                               echo Jsphon::encode($aVars);
                                exit;
                                //break;
                        default:
@@ -281,9 +293,6 @@ class NP_OpenId extends NucleusPlugin {
 
                $this->loggedinUser['nick'] = $profile['nick'];
                $this->loggedinUser['email'] = $profile['email'];
-
-               setcookie($CONF['CookiePrefix'] . 'comment_user', $this->loggedinUser['nick'], 0, $CONF['CookiePath'], $CONF['CookieDomain'], $CONF['CookieSecure']);
-               setcookie($CONF['CookiePrefix'] . 'comment_email', $this->loggedinUser['email'], 0, $CONF['CookiePath'], $CONF['CookieDomain'], $CONF['CookieSecure']);
        }
        
        function _doLoginLocal($name){
@@ -344,7 +353,7 @@ class NP_OpenId extends NucleusPlugin {
        
        function isLoggedin(){
                global $CONF;
-               if( $this->loggedinUser ) return true;
+               if( $this->loggedinUser['identity'] ) return true;
                
                $cookie = cookieVar($CONF['CookiePrefix'] . NP_OPENID_AUTH_COOKIE);
                if( ! $cookie ) return false;
@@ -410,8 +419,6 @@ class NP_OpenId extends NucleusPlugin {
                        $this->loggedinUser = array_merge($this->loggedinUser, unserialize($this->loggedinUser['sreg']));
                        
                        setcookie($CONF['CookiePrefix'] . NP_OPENID_AUTH_COOKIE , $cookie, 0, $CONF['CookiePath'], $CONF['CookieDomain'], $CONF['CookieSecure']);
-                       setcookie($CONF['CookiePrefix'] . 'comment_user', $this->loggedinUser['nick'], 0, $CONF['CookiePath'], $CONF['CookieDomain'], $CONF['CookieSecure']);
-                       setcookie($CONF['CookiePrefix'] . 'comment_email', $this->loggedinUser['email'], 0, $CONF['CookiePath'], $CONF['CookieDomain'], $CONF['CookieSecure']);
                        return true;
                }
                
@@ -422,8 +429,6 @@ class NP_OpenId extends NucleusPlugin {
                global $CONF;
                $this->loggedinUser = null;
                setcookie($CONF['CookiePrefix'] . NP_OPENID_AUTH_COOKIE, '', 0, $CONF['CookiePath'], $CONF['CookieDomain'], $CONF['CookieSecure']);
-               setcookie($CONF['CookiePrefix'] . 'comment_user', '', 0, $CONF['CookiePath'], $CONF['CookieDomain'], $CONF['CookieSecure']);
-               setcookie($CONF['CookiePrefix'] . 'comment_email', '', 0, $CONF['CookiePath'], $CONF['CookieDomain'], $CONF['CookieSecure']);
                return true;
        }
        
@@ -608,4 +613,4 @@ class NP_OpenId extends NucleusPlugin {
                return $this->templateEngine;
        }
        
-}
+}
\ No newline at end of file
index 72bb8a5..79394f8 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $Id: help.html,v 1.2 2008-06-07 19:33:43 hsur Exp $ -->
+<!-- $Id: help.html,v 1.3 2008-06-10 14:35:11 hsur Exp $ -->
 <h3>バージョン履歴</h3>
 
 <ul>
@@ -11,4 +11,6 @@
        <li> [Changed] テンプレートをプラグインオプションから、ファイルベースに変更</li>
        <li> [Changed] Profileの変更にYUIを使うようにした</li>
        <li> [Fixed] テーブルの作成に失敗する問題に対応</li>
+       <li> [Fixed] XSSが発生する問題を解決(v1.1.1, 2008/06/10)</li>
+       <li> [Fixed] 不必要なCookieを使わないようにした(v1.1.1, 2008/06/10)</li>
 </ul>
diff --git a/trunk/NP_OpenId/openid/language/english.php b/trunk/NP_OpenId/openid/language/english.php
new file mode 100644 (file)
index 0000000..5d0c989
--- /dev/null
@@ -0,0 +1,4 @@
+<?php 
+
+define('NP_OPENID_updateSucceeded', 'Thanks, your profile have been updated.');                
+define('NP_OPENID_notloggedin', 'You are not logged in.');             
diff --git a/trunk/NP_OpenId/openid/language/japanese-euc.php b/trunk/NP_OpenId/openid/language/japanese-euc.php
new file mode 100644 (file)
index 0000000..0ce9f06
--- /dev/null
@@ -0,0 +1,4 @@
+<?php 
+
+define('NP_OPENID_updateSucceeded', '¥×¥í¥Õ¥£¡¼¥ë¤Î¹¹¿·¤¬´°Î»¤·¤Þ¤·¤¿¡£');             
+define('NP_OPENID_notloggedin', '¥í¥°¥¤¥ó¤·¤Æ¤¤¤Þ¤»¤ó¡£');             
diff --git a/trunk/NP_OpenId/openid/language/japanese-utf8.php b/trunk/NP_OpenId/openid/language/japanese-utf8.php
new file mode 100644 (file)
index 0000000..07fe98a
--- /dev/null
@@ -0,0 +1,4 @@
+<?php 
+
+define('NP_OPENID_updateSucceeded', 'プロフィールの更新が完了しました。');            
+define('NP_OPENID_notloggedin', 'ログインしていません。');          
diff --git a/trunk/NP_OpenId/openid/template/np_openid/updatefailed_english.html b/trunk/NP_OpenId/openid/template/np_openid/updatefailed_english.html
deleted file mode 100644 (file)
index c27b311..0000000
+++ /dev/null
@@ -1 +0,0 @@
-{{message|}}
\ No newline at end of file
diff --git a/trunk/NP_OpenId/openid/template/np_openid/updatesucceeded_english.html b/trunk/NP_OpenId/openid/template/np_openid/updatesucceeded_english.html
deleted file mode 100644 (file)
index fba9c5a..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-document.getElementById('nucleus_cf_name').value = '{{nick}} [OpenID]';
-document.getElementById('nucleus_cf_email').value = '{{email}}';
-document.getElementById('resp').innerHTML = 'Thanks, your profile have been updated.';
diff --git a/trunk/NP_OpenId/openid/template/np_openid/updatesucceeded_japanese-euc.html b/trunk/NP_OpenId/openid/template/np_openid/updatesucceeded_japanese-euc.html
deleted file mode 100644 (file)
index 285912b..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-document.getElementById('nucleus_cf_name').value = '{{nick}} [OpenID]';
-document.getElementById('nucleus_cf_email').value = '{{email}}';
-document.getElementById('resp').innerHTML = '¥×¥í¥Õ¥£¡¼¥ë¤Î¹¹¿·¤¬´°Î»¤·¤Þ¤·¤¿¡£';
diff --git a/trunk/NP_OpenId/openid/template/np_openid/updatesucceeded_japanese-utf8.html b/trunk/NP_OpenId/openid/template/np_openid/updatesucceeded_japanese-utf8.html
deleted file mode 100644 (file)
index ffbb4e5..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-document.getElementById('nucleus_cf_name').value = '{{nick}} [OpenID]';
-document.getElementById('nucleus_cf_email').value = '{{email}}';
-document.getElementById('resp').innerHTML = 'プロフィールの更新が完了しました。';
index f01ca24..11fd939 100644 (file)
@@ -23,13 +23,17 @@ function init() {
                this.cancel();
        };
        var handleSuccess = function(o) {
-               var response = o.responseText;
-               //debug
-               //document.getElementById("resp").innerHTML = response;
-               eval(response);
+               var param = eval( "(" + o.responseText + ")" );
+               if( param['result'] == 'succeeded'){
+                       document.getElementById('nucleus_cf_name').value = param['nick'] + ' [OpenID]';
+                       document.getElementById('nucleus_cf_email').value = param['email'];
+                       document.getElementById("resp").innerHTML = param['message'];
+               } else {
+                       document.getElementById("resp").innerHTML = param['message'];
+               }
        };
        var handleFailure = function(o) {
-               document.getElementById("resp").innerHTML = "Submission failed: " + o.status;
+               document.getElementById("resp").innerHTML = "Error: " + o.status;
        };
 
        // Instantiate the Dialog
diff --git a/trunk/NP_OpenId/sharedlibs/Jsphon.php b/trunk/NP_OpenId/sharedlibs/Jsphon.php
new file mode 100644 (file)
index 0000000..5ac2856
--- /dev/null
@@ -0,0 +1,79 @@
+<?php
+//
+// +--------------------------------------------------------------------+
+// | PHP version 4 and 5                                                |
+// +--------------------------------------------------------------------+
+// | Copyright (c) 2006 Hawk                                            |
+// +--------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License,    |
+// | that is available at http://www.php.net/license/3_0.txt.           |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to        |
+// | license@php.net so we can mail you a copy immediately.             |
+// +--------------------------------------------------------------------+
+// | Authors: Hawk <scholar@hawklab.jp>                                 |
+// +--------------------------------------------------------------------+
+//
+//
+
+define('JSPHON_ERROR_DECODE_SYNTAX', 1);
+
+require_once(dirname(__FILE__) .'/Jsphon/Error.php');
+require_once(dirname(__FILE__) .'/Jsphon/Decoder.php');
+require_once(dirname(__FILE__) .'/Jsphon/Encoder.php');
+
+Jsphon_Error::singleton();
+
+/**
+ * Jsphon - JSON in PHP
+ * 
+ * example:
+ * <code>
+ * //encode
+ * $value = array('foo', 'bar', array('hoge' => array(1,2)));
+ * $json = Jsphon::encode($value);
+ * echo $json;
+ * 
+ * //decode
+ * $var =  Jsphon::decode($json);
+ * echo $var[2]['hoge'];
+ * 
+ * </code>
+ * 
+ * @author Hawk
+ */
+class Jsphon
+{
+    /**
+     * Encodes an arbitrary variables into JSON format.
+     * See Jsphon_Encoder::encode() for details.
+     * 
+     * @param  String    $value
+     * @param  boolean   $escapeNonASCII
+     * @param  boolean   $escapeOverUCS2
+     * @return String
+     */
+    function encode($value, $escapeNonASCII=true, $escapeOverUCS2=false)
+    {
+        $encoder = new Jsphon_Encoder($escapeNonASCII, $escapeOverUCS2);
+        return $encoder->encode($value);
+    }
+    
+
+    /**
+     * Decodes JSON-formatted string into appropriate PHP variable.
+     * See Jsphon_Decoder::decode() for details.
+     * 
+     * @param  String    $json
+     * @param  String    $decodeOverUCS2
+     * @return mixed
+     */
+    function decode($json, $decodeOverUCS2=false)
+    {
+        $decoder = new Jsphon_Decoder($decodeOverUCS2);
+        return $decoder->decode($json);
+    }
+
+}
+
+?>
diff --git a/trunk/NP_OpenId/sharedlibs/Jsphon/Decoder.php b/trunk/NP_OpenId/sharedlibs/Jsphon/Decoder.php
new file mode 100644 (file)
index 0000000..9e60dc3
--- /dev/null
@@ -0,0 +1,377 @@
+<?php
+//
+// +--------------------------------------------------------------------+
+// | PHP version 4 and 5                                                |
+// +--------------------------------------------------------------------+
+// | Copyright (c) 2006 Hawk                                            |
+// +--------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License,    |
+// | that is available at http://www.php.net/license/3_0.txt.           |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to        |
+// | license@php.net so we can mail you a copy immediately.             |
+// +--------------------------------------------------------------------+
+// | Authors: Hawk <scholar@hawklab.jp>                                 |
+// +--------------------------------------------------------------------+
+//
+//
+
+require_once(dirname(__FILE__) .'/Decoder/Tokenizer.php');
+
+/**
+ * Converts JSON-formatted string to appropriate PHP variable
+ * 
+ * example:
+ * <code>
+ * //create a new instance of Jsphon_Decoder
+ * $json =& new Jsphon_Decoder();
+ * 
+ * //convert JSON-formatted string to PHP variable
+ * $value = '["foo","bar",{"hoge":[1,2]}]';
+ * $var = $json->decode($value);
+ * 
+ * print_r($var);
+ * //array('foo', 'bar', array('hoge' => array(1,2)))
+ * </code>
+ * 
+ * @author Hawk
+ */
+class Jsphon_Decoder
+{
+    var $_mbstring;
+
+    var $_decodeOverUCS2;
+
+    var $_internalError;
+
+    var $_transTable = array(
+        '\b' => "\x08",
+        '\t' => "\x09",
+        '\n' => "\x0A",
+        '\f' => "\x0C",
+        '\r' => "\x0D",
+        '\"' => "\x22",
+        '\/' => "\x2F",
+         '\\\\' => "\x5C"
+        );
+
+    var $_allUESreg = '/\\\u([a-fA-F0-9]{4})/';
+
+    var $_utf16surUESreg = '/\\\u(D[89AB][A-F0-9]{2})\\\u(D[C-F][A-F0-9]{2})/i';
+
+    /**
+     * construct a new Jsphon_Decoder instance.
+     * 
+     * @param  bool   $decodeOverUCS2   If true, decodeString() converts the whole
+     *                                  Unicode escape sequences (\uXXXX) including surrogate pairs
+     *                                  to corresponding characters in UTF-8.
+     */
+    function Jsphon_Decoder($decodeOverUCS2=false)
+    {
+        $this->_decodeOverUCS2 = $decodeOverUCS2;
+        $this->_mbstring = extension_loaded('mbstring');
+    }
+
+    /**
+     * decodes a JSON string into appropriate variable
+     * 
+     * @param  String    $json
+     * @return mixed
+     */
+    function decode($json)
+    {
+        $tknz = new Jsphon_Decoder_Tokenizer($json,
+                                             array(&$this, 'handleInternalError'));
+        $this->_internalError = false;
+
+        $result = null;
+        if($tknz->nextToken()) {
+            $result = $this->_decodeJSValue($tknz);
+        }
+        
+        $this->_internalError = false;
+        return $result;
+    }
+
+    /**
+     * 
+     * @param  Object $tknz
+     * @return mixed
+     */
+    function _decodeJSValue(&$tknz)
+    {
+        switch($tknz->getToken()) {
+          case JSPHON_TOKEN_DATUM:
+            if(is_string($r = $tknz->getTokenValue())) {
+                $r = $this->decodeString($r);
+            }
+            return $r;
+            
+          case JSPHON_TOKEN_LBRACKET:
+            return $this->_decodeArray($tknz);
+
+          case JSPHON_TOKEN_LBRACE:
+            return $this->_decodeObject($tknz);
+
+          default:
+            $this->_error("syntax error: Expecting '{', '[' or DAUM.");
+            return null;
+        }
+    }
+
+    /**
+     * Decodes a JSON array format:
+     * [element, element2,...,elementN]
+     * 
+     * @param  Object $tknz
+     * @return array
+     */
+    function _decodeArray(&$tknz)
+    {
+        $ret = array();
+        if(!($token = $tknz->nextToken())) {
+            return null;
+            
+        } elseif($token == JSPHON_TOKEN_RBRACKET) {
+            return $ret;
+        }
+
+        //if false, break
+        while(  ($value = $this->_decodeJSValue($tknz) or true)
+            and !$this->_internalError
+            and ($ret[] = $value or true)
+            and $token = $tknz->nextToken()
+            and $token == JSPHON_TOKEN_COMMA
+            and $token = $tknz->nextToken()
+            );
+
+        if($this->_internalError) {
+            return null;
+            
+        } elseif($token == JSPHON_TOKEN_RBRACKET) {
+            return $ret;
+        } else {
+            $this->_error("Missing ',' or ']' in array encoding.");
+            return null;
+        }
+    }
+
+    /**
+     * Decodes an object of the form:
+     *  { "attribute: value, "attribute2" : value,...}
+     * 
+     * _decodeObject() always converts a JSON-object to an associative array,
+     * because you can't access empty property in PHP5.
+     * <code>
+     * // { "":"foo" }
+     * $obj->{""} = "foo"; //Fatal error: Cannot access empty property
+     * </code>
+     * 
+     * @param  Object $tknz
+     * @return array
+     */
+    function _decodeObject(&$tknz)
+    {
+        $ret = array();
+        if(!($token = $tknz->nextToken())) {
+            return null;
+            
+        } elseif($token == JSPHON_TOKEN_RBRACE) {
+            return $ret;
+        }
+
+        //if false, break
+        while(  ($key = $this->_decodeJSValue($tknz) or true)
+            and !$this->_internalError
+            and $this->_checkObjectKey($key)
+            and $token = $tknz->nextToken()
+            and $this->_checkKeyValueSep($token)
+            and $token = $tknz->nextToken()
+            and ($value = $this->_decodeJSValue($tknz) or true)
+            and !$this->_internalError
+            and ($ret[$key] = $value or true)
+            and $token = $tknz->nextToken()
+            and $token == JSPHON_TOKEN_COMMA
+            and $token = $tknz->nextToken()
+            );
+
+        if($this->_internalError) {
+            return null;
+            
+        } elseif($token == JSPHON_TOKEN_RBRACE) {
+            return $ret;
+        } else {
+            $this->_error("Missing ',' or '}' in object encoding.");
+            return null;
+        }
+    }
+
+    function _checkObjectKey($key)
+    {
+        if(!is_string($key)) {
+            $this->_error("Object's key must be a string, but is ". gettype($key));
+            return false;
+        }
+        return true;
+    }
+
+    function _checkKeyValueSep($token)
+    {
+        if($token != JSPHON_TOKEN_COLON) {
+            $this->_error("Missing ':' in object encoding.");
+            return false;
+        }
+        return true;
+    }
+    
+
+    /**
+     * 
+     * 
+     * @param  String    $encoded
+     * @return String
+     */
+    function decodeString($encoded)
+    {
+        $ret = strtr($encoded, $this->_transTable);
+        
+        if($this->_decodeOverUCS2) {
+            return $this->_decodeUESOverUCS2($ret);
+        } else {
+            //_decodeUESWithoutMbstring() fastar than _decodeUES()...
+            return $this->_decodeUESWithoutMbstring($ret);
+        }
+        
+        /*
+        if(!$this->_mbstring) {
+            return $this->_decodeUESWithoutMbstring($ret);
+        } elseif($this->_decodeOverUCS2) {
+            return $this->_decodeUESOverUCS2($ret);
+        } else {
+            return $this->_decodeUES($ret);
+        }
+        */
+    }
+
+    function _decodeUES($str)
+    {
+        $transTable = array();
+
+        if(!preg_match_all($this->_allUESreg, $str, $matches)) {
+            return $str;
+        }
+
+        $codepoints = $matches[1];
+        foreach($matches[0] as $i => $escSeq) {
+            if(isset($transTable[$escSeq])) {
+                continue;
+            }
+            $codepoint = hexdec($codepoints[$i]);
+            $transTable[$escSeq] = (0xD800 <= $codepoint && $codepoint <= 0xDFFF) ? ""
+            : mb_convert_encoding(pack('n', $codepoint), 'UTF-8', 'UCS-2');
+        }
+        return strtr($str, $transTable);
+    }
+    
+    function _decodeUESOverUCS2($str)
+    {
+        $transTable = array();
+
+        if(!preg_match_all($this->_allUESreg, $str, $u16)) {
+            return $str;
+        }
+        
+        if(preg_match_all($this->_utf16surUESreg, $str, $u16sur)) {
+            $sur1st = $u16sur[1];
+            $sur2nd = $u16sur[2];
+            
+            foreach($u16sur[0] as $i => $escSeq) {
+                if(isset($transTable[$escSeq])) {
+                    continue;
+                }
+                $transTable[$escSeq] = mb_convert_encoding(
+                    pack('n2', hexdec($sur1st[$i]), hexdec($sur2nd[$i])), 'UTF-8', 'UTF-16BE');
+            }
+        }
+
+        $codepoints = $u16[1];
+        foreach($u16[0] as $i => $escSeq) {
+            if(isset($transTable[$escSeq])) {
+                continue;
+            }
+            $codepoint = hexdec($codepoints[$i]);
+            $transTable[$escSeq] = (0xD800 <= $codepoint && $codepoint <= 0xDFFF) ? ""
+            : mb_convert_encoding(pack('n', $codepoint), 'UTF-8', 'UCS-2');
+        }
+        return strtr($str, $transTable);
+    }
+
+    function _decodeUESWithoutMbstring($str)
+    {
+        $transTable = array();
+
+        if(!preg_match_all($this->_allUESreg, $str, $matches)) {
+            return $str;
+        }
+
+        $codepoints = $matches[1];
+        foreach($matches[0] as $i => $escSeq) {
+            if(isset($transTable[$escSeq])) {
+                continue;
+            }
+            
+            $utf8char = "";
+
+            $cp = hexdec($codepoints[$i]);
+            switch(true) {
+              case ($cp < 0x80):
+                $utf8char = chr($cp);
+                break;
+                
+              case (0xD800 <= $cp && $cp <= 0xDFFF):
+                break;
+
+              case ($cp < 0x800):
+                $utf8char = chr($cp >> 6 & 0x1F | 0xC0) . chr($cp & 0x3F | 0x80);
+                break;
+                
+              case ($cp < 0x10000):
+                $utf8char = chr($cp >> 12 & 0xF | 0xE0) .
+                chr($cp >> 6 & 0x3F | 0x80) . chr($cp & 0x3F | 0x80);
+                break;
+
+              default:
+            }
+            $transTable[$escSeq] = $utf8char;
+        }
+        return strtr($str, $transTable);
+    }
+    
+
+    /**
+     * a simple wrapper for PEAR_ErrorStack::push.
+     * 
+     * @param  String    $message
+     * @param  array     $param
+     * @param  string    $level
+     * @param  int       $code
+     * @return String
+     */
+    function _error($message,
+                    $param= array(),
+                    $level='error',
+                    $code=JSPHON_ERROR_DECODE_SYNTAX)
+    {
+        $e = Jsphon_Error::push(
+            $code, $level, $param, $message, false, debug_backtrace());
+        $this->_internalError = true;
+        return $e;
+    }
+    
+    function handleInternalError($err)
+    {
+        $this->_internalError = true;
+    }
+}
+
+?>
diff --git a/trunk/NP_OpenId/sharedlibs/Jsphon/Decoder/Tokenizer.php b/trunk/NP_OpenId/sharedlibs/Jsphon/Decoder/Tokenizer.php
new file mode 100644 (file)
index 0000000..f422692
--- /dev/null
@@ -0,0 +1,143 @@
+<?php
+//
+// +--------------------------------------------------------------------+
+// | PHP version 4 and 5                                                |
+// +--------------------------------------------------------------------+
+// | Copyright (c) 2006 Hawk                                            |
+// +--------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License,    |
+// | that is available at http://www.php.net/license/3_0.txt.           |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to        |
+// | license@php.net so we can mail you a copy immediately.             |
+// +--------------------------------------------------------------------+
+// | Authors: Hawk <scholar@hawklab.jp>                                 |
+// +--------------------------------------------------------------------+
+//
+//
+
+define('JSPHON_TOKEN_EOF',      1);
+define('JSPHON_TOKEN_DATUM',    2);
+define('JSPHON_TOKEN_LBRACE',   3);
+define('JSPHON_TOKEN_LBRACKET', 4);
+define('JSPHON_TOKEN_RBRACE',   5);
+define('JSPHON_TOKEN_RBRACKET', 6);
+define('JSPHON_TOKEN_COMMA',    7);
+define('JSPHON_TOKEN_COLON',    8);
+
+/**
+ * Jsphon_Decoder_Tokenizer
+ * 
+ * @author Hawk
+ */
+class Jsphon_Decoder_Tokenizer
+{
+    var $_source;
+
+    var $_token;
+
+    var $_tokenValue;
+
+    var $_tokenTable = array(
+        '{' => JSPHON_TOKEN_LBRACE,
+        '}' => JSPHON_TOKEN_RBRACE,
+        '[' => JSPHON_TOKEN_LBRACKET,
+        ']' => JSPHON_TOKEN_RBRACKET,
+        ',' => JSPHON_TOKEN_COMMA,
+        ':' => JSPHON_TOKEN_COLON
+        );
+
+    var $_tokenValueTable = array(
+        'true'  => true,
+        'false' => false,
+        'null'  => null
+        );
+
+    var $_errorCallback;
+
+    /**
+     * constructs a new Jsphon_Decoder_Tokenizer instance.
+     * 
+     * @param  String    $source
+     */
+    function Jsphon_Decoder_Tokenizer($source, $internalErrorCallback=null)
+    {
+        $this->_source = $source;
+        $this->_errorCallback = $internalErrorCallback;
+    }
+
+    /**
+     * Retrieves the next token from the source stream.
+     * 
+     * @return int or false
+     */
+    function nextToken()
+    {
+        $src = ltrim($this->_source);
+
+        $this->_tokenValue = null;
+        $this->_token = JSPHON_TOKEN_EOF;
+
+        switch(true)
+        {
+          case $src === '':
+            break;
+            
+          case ($c = $src{0}) !== "" and isset($this->_tokenTable[$c]):
+            $this->_token = $this->_tokenTable[$c];
+            $src = substr($src, 1);
+            break;
+
+          case $c == '"' and preg_match('/^"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"/', $src, $m):
+            $this->_token = JSPHON_TOKEN_DATUM;
+            $this->_tokenValue = $m[1];
+            $src = substr($src, strlen($m[0]));
+            break;
+
+          case preg_match('/^(true|false|null)\b/', $src, $m):
+            $this->_token = JSPHON_TOKEN_DATUM;
+            $this->_tokenValue = $this->_tokenValueTable[$m[1]];
+            $src = substr($src, ($m[1]{0} == 'f' ? 5 : 4));
+            break;
+
+          case preg_match('/^-?(?:[1-9]\d+|\d)(?:\.\d+)?(?:[eE][-+]?\d+)?/', $src, $m):
+            $this->_token = JSPHON_TOKEN_DATUM;
+            $intV   = (int)$m[0];
+            $floatV = (float)$m[0];
+            $this->_tokenValue = ($intV == $floatV) ? $intV : $floatV;
+            $src = substr($src, strlen($m[0]));
+            break;
+
+          default:
+            $err = Jsphon_Error::push(
+                JSPHON_ERROR_DECODE_SYNTAX,
+                'error',
+                array(),
+                'Illegal Token',
+                false,
+                debug_backtrace());
+
+            if(is_callable($this->_errorCallback)) {
+                call_user_func($this->_errorCallback, $err);
+            }
+            return false;
+
+        }
+
+        $this->_source = $src;
+        return $this->_token;
+    }
+
+    function getToken()
+    {
+        return $this->_token;
+    }
+
+    function getTokenValue()
+    {
+        return $this->_tokenValue;
+    }
+
+}
+
+?>
diff --git a/trunk/NP_OpenId/sharedlibs/Jsphon/Encoder.php b/trunk/NP_OpenId/sharedlibs/Jsphon/Encoder.php
new file mode 100644 (file)
index 0000000..7cf9689
--- /dev/null
@@ -0,0 +1,250 @@
+<?php
+//
+// +--------------------------------------------------------------------+
+// | PHP version 4 and 5                                                |
+// +--------------------------------------------------------------------+
+// | Copyright (c) 2006 Hawk                                            |
+// +--------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License,    |
+// | that is available at http://www.php.net/license/3_0.txt.           |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to        |
+// | license@php.net so we can mail you a copy immediately.             |
+// +--------------------------------------------------------------------+
+// | Authors: Hawk <scholar@hawklab.jp>                                 |
+// +--------------------------------------------------------------------+
+//
+//
+
+/**
+ * Converts to JSON format.
+ * 
+ * example:
+ * <code>
+ * //create a new instance of Jsphon_Encoder
+ * $json =& new Jsphon_Encoder();
+ * 
+ * //convert a complex value to JSON notation, and send it to the browser
+ * $value = array('foo', 'bar', array('hoge' => array(1,2)));
+ * $output = $json->encode($value);
+ * 
+ * print_r($output);
+ * //prints: ["foo","bar",{"hoge":[1,2]}]
+ * </code>
+ * 
+ * @author Hawk
+ */
+class Jsphon_Encoder
+{
+    var $_mbstring;
+    
+    var $_escapeNonASCII;
+    
+    var $_escapeOverUCS2;
+    
+    var $_transTable;
+    
+    var $_utf8UCS2reg;
+    
+    var $_utf8overUCS2reg;
+    
+    /**
+     * constructs a new Jsphon_Encoder instance.
+     * 
+     * @param bool $escapeNonASCII  If true, encode() converts non-ASCII characters 
+     *                              to Unicode escape sequence (\uXXXX).
+     * @param bool $escapeOverUCS2  If true, encode() converts all the non-ASCII characters 
+     *                              that is encodable in UTF-16 to Unicode escape sequence.
+     *                              This parameter affects the encoder's behavior 
+     *                              only if $escapeNonASCII is set to true and 
+     *                              the multibyte string extension is available.
+     * 
+     */
+    function Jsphon_Encoder($escapeNonASCII=true, $escapeOverUCS2=false)
+    {
+        $this->_escapeNonASCII = $escapeNonASCII;
+        $this->_escapeOverUCS2 = $escapeOverUCS2;
+        $this->_mbstring = extension_loaded('mbstring');
+
+        $this->_transTable = array(
+            "\x08" => '\b',
+            "\x09" => '\t',
+            "\x0A" => '\n',
+            "\x0C" => '\f',
+            "\x0D" => '\r',
+            "\x22" => '\"',
+            "\x2F" => '\/',
+            "\x5C" => '\\\\'
+        );
+        
+        $utf8ucs2 = '[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}';
+        $utf16sur = '[\xF0-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2}';
+        $this->_utf8UCS2reg = "/{$utf8ucs2}/";
+        $this->_utf8overUCS2reg = "/{$utf8ucs2}|{$utf16sur}/";
+    }
+    
+    /**
+     * encodes an arbitrary variables into JSON format.
+     * 
+     * If $_escapeNonASCII is set to true, 
+     * encode() removes all non-ASCII characters to make sure that 
+     * returning value dosen't contain any non-ASCII characters.
+     * 
+     * @param mixed $value
+     * @return string
+     */
+    function encode($value)
+    {
+        $json = $this->_encode($value);
+        if($this->_escapeNonASCII) {
+            $json = preg_replace('/[\x80-\xFF]/', '', $json);
+        }
+        return $json;
+    }
+    
+    function _encode($value)
+    {
+        if($value === null) {
+            return 'null';
+            
+        } elseif(is_bool($value)) {
+            return $value ? 'true' : 'false';
+            
+        } elseif(is_int($value)) {
+            return (int)$value;
+            
+        } elseif(is_float($value)) {
+            return (float)$value;
+            
+        } elseif(is_string($value)) {
+            return '"'. $this->_encodeString($value) .'"';
+
+        } elseif(is_array($value)) {
+            if(($len = count($value)) > 0 &&
+               array_keys($value) !== range(0, $len - 1)) {
+                return $this->_encodeObject($value);
+            } else {
+                return '['. join(',', array_map(array(&$this, '_encode'), $value)) .']';
+            }
+
+        } elseif(is_object($value)) {
+            return $this->_encodeObject($value);
+            
+        }
+        
+        return 'null';
+    }
+    
+    function _encodeObject($arr)
+    {
+        $result = array();
+        foreach($arr as $name => $value) {
+            $result[] = $this->_encode((string)$name) .':'. $this->_encode($value);
+        }
+        return '{'. join(',', $result) ."}";
+    }
+    
+    function _encodeString($str)
+    {
+        $str = strtr($str, $this->_transTable);
+        
+        if(!$this->_escapeNonASCII) {
+            return $str;
+        }
+        
+        if(!$this->_mbstring) {
+            return $this->_escapeNonASCIIWithoutMbstring($str);
+        }
+        
+        if($this->_escapeOverUCS2) {
+            return $this->_escapeNonASCIIOverUCS2($str);
+        } else {
+            return $this->_escapeNonASCII($str);
+        }
+    }
+    
+    function _escapeNonASCII($str) 
+    {
+        $transTable = array();
+
+        if(!preg_match_all($this->_utf8UCS2reg, $str, $matches)) {
+            return $str;
+        }
+        
+        foreach($matches[0] as $utf8char) {
+            if(isset($transTable[$utf8char])) {
+                continue;
+            }
+            $transTable[$utf8char] = $this->_formatSeq(
+                mb_convert_encoding($utf8char, 'UTF-16', 'UTF-8'));
+        }
+        return strtr($str, $transTable);
+    }
+
+    function _escapeNonASCIIOverUCS2($str) 
+    {
+        $transTable = array();
+
+        if(!preg_match_all($this->_utf8overUCS2reg, $str, $matches)) {
+            return $str;
+        }
+        
+        foreach($matches[0] as $utf8char) {
+            if(isset($transTable[$utf8char])) {
+                continue;
+            }
+            $utf16char = mb_convert_encoding($utf8char, 'UTF-16', 'UTF-8');
+            
+            if(($l = strlen($utf16char)) == 2) {
+                $transTable[$utf8char] = $this->_formatSeq($utf16char);
+            } elseif($l == 4) {
+                $transTable[$utf8char] = 
+                    $this->_formatSeq(substr($utf16char, 0, 2)) . $this->_formatSeq(substr($utf16char, 2));
+            }
+            
+        }
+        return strtr($str, $transTable);
+    }
+
+    function _escapeNonASCIIWithoutMbstring($str) 
+    {
+        $transTable = array();
+
+        if(!preg_match_all($this->_utf8UCS2reg, $str, $matches)) {
+            return $str;
+        }
+        
+        foreach($matches[0] as $utf8char) {
+            if(isset($transTable[$utf8char])) {
+                continue;
+            }
+            
+            switch(strlen($utf8char)) {
+            case 2:
+                $code = (
+                 ((ord($utf8char{0}) & 0x1F) << 6) |
+                  (ord($utf8char{1}) & 0x3F)
+                );
+                break;
+
+            case 3:
+                $code = (
+                 ((ord($utf8char{0}) & 0x0F) << 12) |
+                 ((ord($utf8char{1}) & 0x3F) << 6 ) |
+                  (ord($utf8char{2}) & 0x3F)
+                );
+                break;
+            default:
+            }
+            $transTable[$utf8char] = '\u'. substr('0000'. dechex($code), -4);
+        }
+        return strtr($str, $transTable);
+    }
+
+    function _formatSeq($u16)
+    {
+        return '\u'. substr('0000'. bin2hex($u16), -4);
+    }
+}
+
+?>
diff --git a/trunk/NP_OpenId/sharedlibs/Jsphon/Error.php b/trunk/NP_OpenId/sharedlibs/Jsphon/Error.php
new file mode 100644 (file)
index 0000000..b2a5413
--- /dev/null
@@ -0,0 +1,190 @@
+<?php
+//
+// +--------------------------------------------------------------------+
+// | PHP version 4 and 5                                                |
+// +--------------------------------------------------------------------+
+// | Copyright (c) 2006 Hawk                                            |
+// +--------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License,    |
+// | that is available at http://www.php.net/license/3_0.txt.           |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to        |
+// | license@php.net so we can mail you a copy immediately.             |
+// +--------------------------------------------------------------------+
+// | Authors: Hawk <scholar@hawklab.jp>                                 |
+// +--------------------------------------------------------------------+
+//
+//
+
+/**
+ * Jsphon_Error
+ * 
+ * @author Hawk
+ */
+class Jsphon_Error
+{
+    var $_isPHP5;
+
+    var $_existsPEAR;
+
+    var $_throwException = true;
+
+    var $_exceptionCreator;
+
+    /**
+     * Constructor
+     * 
+     * @access private
+     */
+    function Jsphon_Error()
+    {
+        $this->_isPHP5     = version_compare(phpversion(), '5', '>=');
+        $this->_existsPEAR = (@include_once "PEAR/ErrorStack.php");
+        
+        if($this->_isPHP5) {
+            if($this->_existsPEAR) {
+                require_once(dirname(__FILE__) .'/Exception.php');
+                $method = '_createJsphonException';
+            } else {
+                $method = '_createException';
+            }
+            $this->_exceptionCreator = array(__CLASS__, $method);
+        }
+    }
+
+    /**
+     * 
+     * 
+     * @since 06/09/05 13:21
+     * @return Jsphon_Error
+     */
+    function &singleton()
+    {
+        static $instance = null;
+        if($instance === null) {
+            $instance = new Jsphon_Error();
+        }
+        return $instance;
+    }
+
+    /**
+     * 
+     * @static
+     * @param  int      $code
+     * @param  string   $level
+     * @param  array    $params
+     * @param  string   $msg
+     * @param  mixed    $repackage
+     * @param  array    $backtrace
+     * @return array
+     */
+    function push($code, $level = 'error', $params = array(), $msg = false,
+                  $repackage = false, $backtrace = false)
+    {
+        if (!$backtrace) {
+            $backtrace = debug_backtrace();
+        }
+
+        $self  =& Jsphon_Error::singleton();
+
+        if(!$self->_isPHP5 || !$self->_throwException) {
+            return $self->_push(
+                $code, $level, $params, $msg, $repackage, $backtrace);
+        }
+
+        $pushOnly = true;
+        $err = $self->_push(
+                $code, $level, $params, $msg, $repackage, $backtrace, $pushOnly);
+
+        array_shift($backtrace);
+        throw (call_user_func($self->_exceptionCreator, $msg, $code, $backtrace));
+        return ;
+    }
+
+    /**
+     * 
+     * 
+     * @access private
+     * @static
+     * @param  int      $code
+     * @param  string   $level
+     * @param  array    $params
+     * @param  string   $msg
+     * @param  mixed    $repackage
+     * @param  array    $backtrace
+     * @param  bool     $pushOnly
+     * @return array or null unless PEAR_ErrorStack exists.
+     */
+    function _push($code, $level='error', $params=array(), $msg=false,
+                              $repackage=false, $backtrace=false, $pushOnly=false)
+    {
+        if(!$this->_existsPEAR) {
+            return;
+        }
+
+        $stack =& PEAR_ErrorStack::singleton('Jsphon');
+        if($pushOnly) {
+            $stack->pushCallback(array(__CLASS__, 'pushOnly'));
+        }
+        
+        $err = $stack->push($code, $level, $params, $msg, $repackage, $backtrace);
+
+        if($pushOnly) {
+            $stack->popCallback();
+        }
+        return $err;
+    }
+
+    /**
+     * 
+     * @since 06/09/05 13:34
+     * @param  String    $bool
+     * @param  String    $exceptionClass
+     * @return String
+     */
+    function setThrowException($bool)
+    {
+        $this->_throwException = $bool;
+    }
+
+    /**
+     * error handler which do nothing
+     * 
+     * @since 06/09/05 13:52
+     * @param  array    $err
+     * @return int
+     */
+    function pushOnly($err)
+    {
+        return PEAR_ERRORSTACK_PUSH;
+    }
+
+    /**
+     * 
+     * @static
+     * @param  String    $msg
+     * @param  int       $code
+     * @param  array    $trace
+     * @return Exception
+     */
+    function _createJsphonException($msg, $code, $trace)
+    {
+        return new Jsphon_Exception($msg, $code, $trace);
+    }
+
+    /**
+     * 
+     * @static
+     * @param  String    $msg
+     * @param  int       $code
+     * @param  array    $trace
+     * @return Exception
+     */
+    function _createException($msg, $code, $trace)
+    {
+        return new Exception($msg, $code);
+    }
+}
+
+
+?>
diff --git a/trunk/NP_OpenId/sharedlibs/Jsphon/Exception.php b/trunk/NP_OpenId/sharedlibs/Jsphon/Exception.php
new file mode 100644 (file)
index 0000000..3fc5f85
--- /dev/null
@@ -0,0 +1,56 @@
+<?php
+//
+// +--------------------------------------------------------------------+
+// | PHP version 4 and 5                                                |
+// +--------------------------------------------------------------------+
+// | Copyright (c) 2006 Hawk                                            |
+// +--------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License,    |
+// | that is available at http://www.php.net/license/3_0.txt.           |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to        |
+// | license@php.net so we can mail you a copy immediately.             |
+// +--------------------------------------------------------------------+
+// | Authors: Hawk <scholar@hawklab.jp>                                 |
+// +--------------------------------------------------------------------+
+//
+//
+
+require_once('PEAR/Exception.php');
+
+/**
+ * Jsphon_Exception
+ * 
+ * @author Hawk
+ */
+class Jsphon_Exception extends PEAR_Exception
+{
+    private $_outerTrace;
+    
+    /**
+     * Constructor
+     * 
+     */
+    public function __construct($msg, $code, $outerTrace)
+    {
+        $this->_outerTrace = $outerTrace;
+        parent::__construct($msg, $code);
+    }
+    
+    /**
+     * 
+     * 
+     * @override
+     * @return array
+     */
+    public function getTraceSafe()
+    {
+        if(count($this->_outerTrace) > 0) {
+            return $this->_outerTrace;
+        }
+        return parent::getTraceSafe();
+    }
+
+}
+
+?>