PHPçShindigãä¸æãåããªã
ãªã¼ãã³ã½ã¼ã·ã£ã«ã®ã¢ããªãéçºããä¸ã§ãå¿
é ã¨ãããShindigãShindigã§ã³ã³ãããæ§ç¯ããã°ãã¼ã«ã«ã§ãªã¼ãã³ã½ã¼ã·ã£ã«ã®éçºããããã¨ãåºæ¥ã¾ãã
ããã§ã¡ãã£ã¨ããã£ããã¨ãè¨é²ã¨ãã¦æ®ãã¦ããã¾ãã
ã¾ãShindigã«ã¯ãè²ã
ãªãã¼ã¸ã§ã³ãããä¸ã«Javaçã¨PHPçã®äºç¨®é¡ãåå¨ãã¾ãã
以åéçºã«ä½¿ã£ã¦ããã®ã¯Javaçã§ãPHPã§ä¸æãåãããã¨ãåºæ¥ãªãã£ããã使ã£ã¦ãã¾ãããããããHAS_APPãã£ã«ã¿ããªããä¸æãåããªãäºã«æ°ã¥ãã調ã¹ã¦ã¿ããã®ã®Javaãã»ã¨ãã©åãããããããæ©ä¼ã«PHPçãæ°ãã«ã¤ã³ã¹ãã¼ã«ãã¦ã¿ã訳ã§ãã
Shindigãã¤ã³ã¹ãã¼ã«ãã
Shindigã¯Apacheã®æã§éçºããã¦ããããã§ãä¸è¨ãããã¦ã³ãã¼ãã§ãã¾ãã
Shindig - Download
ä»åã¯ãCurrentã®ãshindig-1.1-BETA5-incubating-php.zipãã使ãã¾ãããSVNãªãã¸ããªããè½ã¨ãã¨ãJavaçãå«ã¾ãã¦ããããããã£ã¬ã¯ããªãã¹ã®è¨å®ãã¡ãã£ã¨ããã©ãã ã¨æãã¾ãã
zipãå±éããWebããã¢ã¯ã»ã¹åºæ¥ãããã«åã ã§è¨å®ãã¦ãã ããã注æç¹ã¯ã.htaccessãå«ã¾ãã¦ãããmod_rewriteãå¿ è¦ã«ãªãã¨ãããã¨ã§ãã
<VirtualHost *:80> ServerName shindig.localhost.man DocumentRoot /home/wwww/shindig # zipãå±éãããã£ã¬ã¯ã㪠<Directory /> AllowOverride All # .htaccessãèªã¿è¾¼ããããã«ãã </Directory> </VirtualHost>
URLãã©ã¡ã¼ã¿ä»ãã§ãåãããã«ãã
ä¸è¨ã®ããã«ã¤ã³ã¹ãã¼ã«ããã°ãã¨ããããã¯åãã®ã§ãããåã使ãä¸ã§ã¡ãã£ã¨ä¸ä¾¿ãªé¨åããã£ãã®ã§ä¿®æ£ãã¾ããã
ããã¯ãã³ã³ããã®URLã«ãã©ã¡ã¼ã¿ãæå®ããã¦ããå ´åã«ä¸æãåããªãã£ãäºã§ãã
æ£ãããã©ã¡ã¼ã¿ãå¦çã§ãããã400 - Bad Requestãã¨ãªã£ã¦ãã¾ãã¾ãã
http://shindig.localhost.man/gadgets/files/container/container.html?view=canvas
ãããªæãã§å¼æ°ã§ç»é¢ãåãæ¿ãã¦ãã¾ããã
# src/gadgets/servlet/FileServlet.php # 40è¡ç®ã®ä¸ã«ãã©ã¡ã¼ã¿ãç¡è¦ãããããªã³ã¼ã追å # $file = str_replace(Config::get('web_prefix') . '/gadgets/files/', '', $_SERVER["REQUEST_URI"]); $file = Config::get('javascript_path') . $file; // ããã追å $file = substr($file, 0, strlen($file) - strlen(strstr($file, '?'))); // make sure that the real path name is actually in the javascript_path, so people can't abuse this to read // your private data from disk .. otherwise this would be a huge privacy and security issue if (substr(realpath($file), 0, strlen(realpath(Config::get('javascript_path')))) != realpath(Config::get('javascript_path'))) {
ç½²åä»ããªã¯ã¨ã¹ãã«å¯¾å¿ãã
ç½²åä»ããªã¯ã¨ã¹ãã¨ã¯ä½ããããã¯ãªã¼ãã³ã½ã¼ã·ã£ã«éçºãããä¸ãå¤é¨ãµã¼ããå¼ã³åºãããå ´åã«ã¨ã¦ãéè¦ã«ãªã£ã¦ãã¾ãããmakeRequestãã¨ããJavaScripté¢æ°ã使ç¨ããå¤é¨ãµã¼ãã«éåæã«ãªã¯ã¨ã¹ããéãããã§ãããããã§éè¦ãªã®ã¯ããªã¯ã¨ã¹ããæ¹ãããããªãããã«ç½²åããã¨ãããã¨ã§ãã
Shindigã§ç½²åä»ããªã¯ã¨ã¹ãã使ãããã«ãopensslã§ç§å¯éµã¨è¨¼ææ¸ãä½æãã¾ãã
$ openssl req -newkey rsa:1024 -days 365 -nodes -x509 -keyout test.pem -out test.pem -subj '/CN=mytestke $ openssl pkcs8 -in test.pem -out private.key -topk8 -nocrypt -outform PEM
åºæ¥ã証ææ¸ã¨éµãcertsãã£ã¬ã¯ããªã«ä¿åããShindigã®è¨å®ãã¡ã¤ã«ãæ¸ãæãã¾ãã
# config/container.php 'private_key_file' => realpath(dirname(__FILE__) . '/../certs') . '/private.key', 'public_key_file' => realpath(dirname(__FILE__) . '/../certs') . '/test.pem', 'private_key_phrase' => '',
ããã§åé¡ãªãã¨æãããã®ã§ãããä¸æãç½²åä»ããªã¯ã¨ã¹ãããããªãäºãåºæ¥ã¾ããã§ããã
ãã©ã¡ã¼ã¿ä»ãURLããä¸æãmakeRequestããããªããªã
makeRequestã§å¤é¨ãµã¼ããå¼ã³åºãã¨ãã«ããã©ã¡ã¼ã¿ãä»å ããã¨ä¸æãåããªãã¨ããç¾è±¡ãçºçãã¾ããã
var url = 'http://localhost/gadget/canvas?ts=1277893054'; gadgets.io.makeRequest(url, null, this.makeParams(data));
ã¿ã¤ã ã¹ã¿ã³ãå¤ãæ«å°¾ã«ä»å ãã¦ãªã¯ã¨ã¹ããéã£ã¦ããã®ã§ãããã?ts=1277893054ããåé¡ã§ããã®ãã©ã¡ã¼ã¿ãä¸æãå¦çåºæ¥ã¦ããªãããã«å¤±æãã¦ããããã§ããã
# src/gadgets/oauth/OAuth.php # 186è¡ç®ã®build_signatureãå®éã«ç½²åããããªã£ã¦ããç®æã«ãªãã¾ãã public function build_signature(&$request, OAuthConsumer $consumer, $token) { $base_string = $request->get_signature_base_string(); // Fetch the private key cert based on the request $cert = $consumer->getProperty(OAuthSignatureMethod_RSA_SHA1::$PRIVATE_KEY); // Pull the private key ID from the certificate //FIXME this function seems to be called both for a oauth.json action where // there is no phrase required, but for signed requests too, which do require it // this is a dirty hack to make it work .. kinda if (! $privatekeyid = @openssl_pkey_get_private($cert)) { if (! $privatekeyid = @openssl_pkey_get_private($cert, Config::get('private_key_phrase') != '' ? (Config::get('private_key_phrase')) : null)) { throw new Exception("Could not load private key"); } } // Sign using the key $signature = ''; if (($ok = openssl_sign($base_string, $signature, $privatekeyid)) === false) { throw new OAuthException("Could not create signature"); } // Release the key resource @openssl_free_key($privatekeyid); return base64_encode($signature); }
openssl_pkey_get_privateé¢æ°ã«ãã£ã¦ãç§å¯éµãåå¾ãã$base_stringã«å¯¾ãã¦ç½²åãã¦ãããã¨ãåããã¾ãããã®$base_stringã®ä¸èº«ã¯ãããªã£ã¦ãã¾ããã
POST&http%3A%2F%2Flocalhost%3A3000%2Fgadget%2Fcanvas&dummy%3D1%26oauth_consumer_key%3Dcont%26oauth_nonce%3D96bd6e6d4103d3c5197f26d5dd6e3463%26oauth_signature_method%3DRSA-SHA1%26oauth_timestamp%3D1277893517%26oauth_token%3D%26opensocial_app_id%3Dappid%26opensocial_app_url%3Durl%26opensocial_owner_id%3Djohn.doe%26opensocial_viewer_id%3Djohn.doe%26ts%3D1277893516%26xoauth_public_key%3Dhttp%253A%252F%252Fshindig.localhost.man%252Fpublic.cer%26xoauth_signature_publickey%3Dhttp%253A%252F%252Fshindig.localhost.man%252Fpublic.cer
ãã®æã«ãts%3D1277893516ãã®æååãããããã©ã¡ã¼ã¿ãtsããå«ãã¦ç½²åããã¦ããäºãåããã¾ãã
ç¶ãã¦å®éã«å¤é¨ãµã¼ãã«ãªã¯ã¨ã¹ããéãé¨åã§ãã
# src/gadgets/SigningFetcher.php # 111è¡ç®ã®signRequestãéä¿¡ãªã¯ã¨ã¹ããä½æãã¾ãã # 174è¡ç®ã«ã¯ã¨ãªã¼ã¹ããªã³ã°ãå¦çããç®æããããéä¿¡å ãªã¯ã¨ã¹ãã«ãã©ã¡ã¼ã¿ã追å ãã¦æ¸¡ãã¦ãã¾ã $newQuery = ''; foreach ($req_req->get_parameters() as $key => $param) { if (! isset($forPost[$key])) { $newQuery .= urlencode($key) . '=' . urlencode($param) . '&'; } } # åé¡ã®ç®æ // and stick on the original query params too if (isset($parsedUri['query']) && ! empty($parsedUri['query'])) { $oldQuery = array(); parse_str($parsedUri['query'], $oldQuery); foreach ($oldQuery as $key => $val) { $newQuery .= urlencode($key) . '=' . urlencode($val) . '&'; } }
ä¸è¦åé¡ãªãããã«è¦ãã¾ããã$req_req->get_parametersé¢æ°ãè¿ãå¤ã«ã¯ãæ¢ã«ã¯ã¨ãªã¼ã¹ããªã³ã°ãå¦çããã¦ãããäºéã§ã¯ã¨ãªã¼ã¹ããªã³ã°ãå¦çããã¦ãããã¨ã«ãªãã¾ãã
ãã©ã¡ã¼ã¿ã®äºéåã«ãã£ã¦ãç½²åããããªã¯ã¨ã¹ãã¨ç°ãªãå¤ã«ãªã£ã¦ãã¾ããå¤é¨ãµã¼ãã§ã®ç½²å確èªæã«ã¨ã©ã¼ã¨ãªã£ã¦ãã¾ãã¾ãã
ãã©ã¡ã¼ã¿ãäºéå¦çããããªã¯ã¨ã¹ãã§ãããã©ã¡ã¼ã¿ãtsããäºã¤ãããã¨ãåããã¾ãã
http://localhost/gadget/canvas?oauth_nonce=0c8c8040978beed7b0221f655ef50303&oauth_timestamp=1277893863&oauth_consumer_key=cont&ts=1277893863&opensocial_owner_id=john.doe&opensocial_viewer_id=john.doe&opensocial_app_id=appid&opensocial_app_url=url&oauth_token=&xoauth_signature_publickey=http%3A%2F%2Fshindig.localhost.man%2Fpublic.cer&xoauth_public_key=http%3A%2F%2Fshindig.localhost.man%2Fpublic.cer&oauth_signature_method=RSA-SHA1&oauth_signature=KTo5X7QxKg8mSpDiaGjljeyKAlmdMLO%2BbPrAr0qYycqAzqTSw8t44p2lXmdRZendFwEpbKLPZy9tAoJ98X9YVkOHjXsp6D19%2BtFBCgSQDJzuvWxHC6xKiRnw2iR0M0HcKSNeMf6x45W%2FJM9rwxT%2BdUYrDZ%2BO4IKbq1etvQj6nWs%3D&ts=1277893863&
src/gadgets/SigningFetcher.phpã®181è¡ç®ã187è¡ç®ã¾ã§ãã³ã¡ã³ãã¢ã¦ããããã¨ã§åé¿ã§ãã¾ãã
html_sanitize is not defined
ããã§ããããç½²åä»ããªã¯ã¨ã¹ãã«å¯¾å¿åºæ¥ããã¨æããã¾ãããã次ã«æ°ããªåé¡ãçºçãã¾ããã
ã³ã³ããå
ã§ãTabsãFeatureãå©ç¨ããæã«ãhtml_sanitize is not definedãã¨ããJavaScriptã¨ã©ã¼ãåºããã¨ã§ãã
ã©ããããcore Featureã§html-sanitizer.jsã¨ããã®ãèªã¿è¾¼ãã³ã¼ãã足ããªãããã§ãã
# src/gadgets/GadgetFeatureRegistry.php // Make html-santitization work see SHINDIG-346 if ($content == 'res://com/google/caja/plugin/html-sanitizer.js') { $content= 'http://google-caja.googlecode.com/svn/trunk/src/com/google/caja/plugin/html-sanitizer.js'; }
ãã®ãããªè¨è¿°ããããhtml-sanitizer.jsã ãç¹å¥ãªå¦ç½®ãããã¦ããããã§ãã
ä»åã¯ãTabs Featureã«html-sanitizer.jsãèªã¿è¾¼ã¾ããã³ã¼ãã追å ãã¾ããå
·ä½çã«ã¯ãfeature.xmlã«ä»¥ä¸ã®ããã«è¿½å ãã¾ãã
# features/src/main/javascript/features/tabs/feature.xml <feature> <name>tabs</name> <gadget> <!-- for gadgets.util.sanitizeHtml --> <script src="res://com/google/caja/plugin/html-sanitizer.js"/> <script src="tabs.js"/> <script src="taming.js"/> </gadget> </feature>
ããã§ã¾ã¨ãã«ä½¿ããããã«ãªãã¾ãããPHPçShindigã¯å°é·ãå¤ãã®ã§Javaçã使ã£ãã»ããç°¡åã¨ãããã¨ã§ãããããããã¨ãããæ¹ãããããã®ãã»ã»ã»ï¼