<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Tender Surrender &#187; Orkut</title>
	<atom:link href="http://devlog.agektmr.com/en/archives/tag/orkut/feed" rel="self" type="application/rss+xml" />
	<link>http://devlog.agektmr.com</link>
	<description>SocialWeb Evolves</description>
	<lastBuildDate>Mon, 05 Jul 2010 05:13:06 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>EN</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<atom:link rel="hub" href="http://pubsubhubbub.appspot.com"/><atom:link rel="hub" href="http://superfeedr.com/hubbub"/>		<item>
		<title>Orkutアプリのソースコードを覗くブックマークレット</title>
		<link>http://devlog.agektmr.com/en/archives/194</link>
		<comments>http://devlog.agektmr.com/en/archives/194#comments</comments>
		<pubDate>Mon, 20 Oct 2008 03:57:02 +0000</pubDate>
		<dc:creator>Eiji</dc:creator>
				<category><![CDATA[Service]]></category>
		<category><![CDATA[Gadget]]></category>
		<category><![CDATA[Orkut]]></category>

		<guid isPermaLink="false">http://devlog.agektmr.com/en/?p=194</guid>
		<description><![CDATA[
topsyWidgetPreload({ "url": "http%3A%2F%2Fdevlog.agektmr.com%2Fen%2Farchives%2F194", "style": "big", "title": [...]]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_light-green" style="float: left;margin-right: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fdevlog.agektmr.com%252Fen%252Farchives%252F194%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22Orkut%E3%82%A2%E3%83%97%E3%83%AA%E3%81%AE%E3%82%BD%E3%83%BC%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%89%E3%82%92%E8%A6%97%E3%81%8F%E3%83%96%E3%83%83%E3%82%AF%E3%83%9E%E3%83%BC%E3%82%AF%E3%83%AC%E3%83%83%E3%83%88%22%20%7D);"><script type="text/javascript">topsyWidgetPreload({ "url": "http%3A%2F%2Fdevlog.agektmr.com%2Fen%2Farchives%2F194", "style": "big", "title": "Orkutアプリのソースコードを覗くブックマークレット" });</script></div>
<p>OpenSocial-Japanのメーリングリストで出した小ネタを貼っておきます。</p>
<p>OpenSocialアプリ(ガジェット)はiframe内に表示されているのですが、iframeタグのsrc属性に含まれるURLのquery部分に、実はソースコードとなるXMLのURLが書いてあります。 このブックマークレットを使えば、ワンクリックでソースコードを開くことができます。</p>
<p><a href="javascript:var%20inner_doc%20=%20document.getElementsByTagName('iframe')[0].contentDocument;var%20iframes%20=%20inner_doc.getElementsByTagName('iframe');var%20src%20=%20iframes[0].src.replace(/^.*??url=(.*?)&amp;.*$/i,%20&quot;$1&quot;);window.open(decodeURIComponent(src));undefined;" target="_blank">Open Orkut Gadget XML</a></p>
<p>↑上記をブックマークレットとして保存し、Orkutアプリを表示した状態でクリックすると、ソースコードのページが新規ウィンドウで開きます。 (複数表示されている場合は、一番上のアプリのソースコードが開きます)</p>
<p>※Firefoxでしか動作確認してないので、動かなかったら教えてください。</p>

]]></content:encoded>
			<wfw:commentRss>http://devlog.agektmr.com/en/archives/194/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>OAuthの署名方式を掘り下げる</title>
		<link>http://devlog.agektmr.com/en/archives/174</link>
		<comments>http://devlog.agektmr.com/en/archives/174#comments</comments>
		<pubDate>Fri, 03 Oct 2008 19:11:18 +0000</pubDate>
		<dc:creator>Eiji</dc:creator>
				<category><![CDATA[OAuth]]></category>
		<category><![CDATA[HMAC-SHA1]]></category>
		<category><![CDATA[iGoogle]]></category>
		<category><![CDATA[MySpace]]></category>
		<category><![CDATA[Orkut]]></category>
		<category><![CDATA[RSA-SHA1]]></category>

		<guid isPermaLink="false">http://devlog.agektmr.com/en/?p=174</guid>
		<description><![CDATA[
topsyWidgetPreload({ "url": "http%3A%2F%2Fdevlog.agektmr.com%2Fen%2Farchives%2F174", "style": "big", "title": [...]]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_light-green" style="float: left;margin-right: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fdevlog.agektmr.com%252Fen%252Farchives%252F174%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22OAuth%E3%81%AE%E7%BD%B2%E5%90%8D%E6%96%B9%E5%BC%8F%E3%82%92%E6%8E%98%E3%82%8A%E4%B8%8B%E3%81%92%E3%82%8B%22%20%7D);"><script type="text/javascript">topsyWidgetPreload({ "url": "http%3A%2F%2Fdevlog.agektmr.com%2Fen%2Farchives%2F174", "style": "big", "title": "OAuthの署名方式を掘り下げる" });</script></div>
<p>当ブログでこれまで何度かOpenSocialに絡んだOAuthについて取り上げてきましたが、MySpaceを参考にしていたため、署名方式としてHMAC-SHA1のみを対象にしてきました。しかしShindigを掘り下げる上でRSA-SHA1を避けて通ることはできず、むしろこちらについても十分な知識を得ていないとなかなか先に進めないことが分かりましたので、この機会にまとめてみます。(OpenSocialをある程度前提にしていますが、署名の話はOpenSocialに限らないものです。)</p>
<h2>署名とは何か</h2>
<p>ITの世界で署名とは、問い合わせ元がその人であることを証明するための手段、と言えます。OAuthだと、コンシューマがサービスプロバイダに対して、名乗っている通りの者であることを証明することを意味します。これは、「自分」もしくは「相手と自分」にしか分からないものをリクエストに付け加えて送ることで実現されます。</p>
<p><a href="http://oauth.net/core/1.0" target="_blank">OAuthの仕様</a>では、署名方式について厳密に規定していませんが、HMAC-SHA1、RSA-SHA1、PLAINTEXTの3つの署名方式を説明しています。</p>
<blockquote><p>OAuth does not mandate a particular signature method, as each implementation can have its own unique requirements. The protocol defines three signature methods: <tt>HMAC-SHA1</tt>, <tt>RSA-SHA1</tt>, and <tt>PLAINTEXT</tt>, but Service Providers are free to implement and document their own methods. Recommending any particular method is beyond the scope of this specification.</p></blockquote>
<h2>HMAC-SHA1</h2>
<p>HMAC-SHA1を使ったOAuthでは、予めコンシューマとサービスプロバイダが、同じコンシューマキー(oauth_consumer_key)とコンシューマシークレット(oauth_consumer_secret)を持ちます。コンシューマシークレットはもちろん、秘密というくらいですから、2者以外に知られてはいけません。2者がコンシューマシークレットを共有することから、Shared Secretと呼んだりもします。</p>
<p>MySpaceでは、コンシューマキーをアプリケーションのURL、コンシューマシークレットをMD5らしきランダムな(?)ハッシュ文字列としていますが、コンシューマキーはディベロッパの任意で変更可能です。詳しくは<a href="http://devlog.agektmr.com/archives/tag/oauth">この辺り</a>をご覧下さい。</p>
<h2>RSA-SHA1</h2>
<p>逆に、RSA-SHA1の方式では、コンシューマが公開鍵と秘密鍵を持ちますが、サービスプロバイダは秘密鍵を知ることはありません。コンシューマは秘密鍵で暗号化した署名を加えたリクエストを投げます。この暗号化された署名は、公開鍵でしか解くことができませんし、秘密鍵でしか作ることができないため、コンシューマが身分を証明できる、という訳です。</p>
<p>署名を作る際、HMAC-SHA1方式の場合、コンシューマシークレット(oauth_consumer_secret)とトークンシークレット(oauth_token_secret)を&#8221;&amp;&#8221;で繋いだものをkeyとして利用しますが、RSA-SHA1方式の場合、秘密鍵をkeyとして使って暗号化します。そのため、コンシューマシークレットとトークンシークレットは不要です。</p>
<p>逆にサービスプロバイダは、公開鍵を使って署名が正当なものであることを確認します。</p>
<pre class="brush: php;">
$publickeyid = openssl_get_publickey($cert);
$ok = openssl_verify($raw, $signature, $publickeyid);
openssl_free_key($publickeyid);
</pre>
<p>$certは公開鍵、$rawは署名の基本文字列(Signature Base String)、$signatureは署名文字列(oauth_signature)を表しています。$rawと$signatureはコンシューマからのリクエストで生成することができますが、$certについてはちょっと考察が必要です。</p>
<h2>RSA-SHA1の公開鍵の扱い</h2>
<p>OAuthの拡張として<a href="http://dirk.balfanz.googlepages.com/oauth_key_rotation.html" target="_blank">OAuth Key Rotation Extension</a>が提案されています。これはコンシューマがサービスプロバイダにリクエストする際、公開鍵のIDをリクエストと一緒に渡すことで、サービスプロバイダに鍵をダウンロード/認識させるための仕様です。公開鍵のIDはxoauth_signature_publickeyパラメータで渡されます</p>
<p>※<a href="http://dirk.balfanz.googlepages.com/oauth_key_rotation.html" target="_blank">OAuth Key Rotation Extension</a>のドラフト、<a href="http://www.opensocial.org/Technical-Resources/opensocial-spec-v08/gadgets-reference08#gadgets.io.makeRequest" target="_blank">OpenSocial/Gadgetの仕様書</a>など、いくつかのドキュメントにxoauth_public_keyと記述されていますが、Shindigの実装でxoauth_signature_publickeyが使用されており、こちらが正式なものとなるようです。</p>
<p>ここで公開鍵のIDと言いましたが、もちろん、これだけでは公開鍵を取得することができないので、これを使ってゴニョゴニョする必要があります。</p>
<p>が、、、。</p>
<p><a href="http://www.opensocial.org/Technical-Resources/opensocial-spec-v08/gadgets-reference08#gadgets.io.makeRequest" target="_blank">OpenSocial/Gadgetの仕様書</a>には</p>
<blockquote><p>The container should make its public key available for download at a well-known location. The location <code>https://<em>container-hostname</em>/opensocial/certificates/<em>xoauth_public_keyvalue</em></code> is recommended.</p></blockquote>
<p>と書いてあるのですが、Shindigの実装ではhttp://container-hostname/public.cerになっていたりと、仕様が一貫していません。</p>
<p>現実はどうしているかというと、xoauth_signature_publickeyを無視して、コンテナのドキュメントに書いてある公開鍵をコピペして<strong>ソースコードにハードコーディング</strong>しています。hi5、Orkutについては動作確認ができました。iGoogleについては<a href="https://sites.google.com/site/oauthgoog/oauth-proxy" target="_blank">ここ</a>に公開鍵が書いてありますが、動作しませんでした。</p>
<p>OAuthが広まって様々なコンシューマが登場するまでは、まだまだこの中途半端な状態が続くのではないでしょうか。</p>
<h2>コンシューマは誰か</h2>
<p>ここで勘のいい方は気付かれたと思いますが、RSA-SHA1方式の場合、署名元が<strong>OpenSocialのコンテナサイトそのもの</strong>になっています。MySpaceのように、<strong>ガジェットではありません</strong>。ということは、もちろんコンシューマキー(oauth_consumer_key)もOrkutなら&#8221;orkut.com&#8221;、hi5なら&#8221;hi5.com&#8221;といった具合に、コンテナサイトを表すものが使用されます。</p>
<p>またこの方式の場合、どのガジェットがリクエストを投げているのかを表すため、<strong>xoauth_app_urlというパラメータ</strong>が追加されます。これを提案しているのが<a href="http://dirk.balfanz.googlepages.com/oauth_gadget_extension.html" target="_blank">OAuth Gadget Extension</a>です。</p>
<p>MySpaceのようにHMAC-SHA1を使っている場合は、ガジェットごとにコンシューマキーを設定し、ガジェットのリクエストをコンテナがProxyするという形を取っていました。これはShindigを使っているiGoogle、Orkut、hi5と、独自にOpenSocialを実装しているMySpaceとの方針の違いから来るものです。</p>
<p>HMAC-SHA1方式でコンテナをコンシューマとして扱おうとすると、シークレットは2者間のみで共有されなければならないため、コンシューマは、サービスプロバイダごとにキーとシークレットを発行しなければなりません。しかし、RSA-SHA1方式であれば、コンテナがコンシューマでも、公開鍵と秘密鍵の組み合わせは一つだけあれば使い回せるため、OpenSocialにおけるmakeRequest (Outbound OAuth)のように、コンテナが外部サービスからデータを取得するアーキテクチャの場合、RSA-SHA1方式にした方がコンシューマにとってサービスプロバイダの追加も容易になりますし、サービスプロバイダにとってコンシューマの署名を確認する作業も楽になるのが利点です。</p>
<p>ShindigがRSA-SHA1方式を中心に実装されているのはそんな理由がありそうです。ちなみに、Shindigの開発はGoogleが中心になって行われており、HMAC-SHA1方式についても現在実装中らしいですが、iGoogleでのコンシューマキーとコンシューマシークレットの発行は、メールで依頼することになっているため、今のところ本気で考えてはいなさそうです。</p>
<blockquote><p>In the case of the iGoogle sandbox, you can send mail to oauthproxyreg@google.com with the following information to register your shared secret:<br />
* URL of your gadget<br />
* The shared secret assigned to you by the service provider<br />
* The consumer key assigned to you by the service provider<br />
* Whether to use symmetric or asymmetric signing with the service provider (or say that you don&#8217;t know)<br />
Until your shared secret has been registered, your gadget will not work.  If you change the URL of your gadget, you will need to re-register the secret for that gadget.</p></blockquote>
<h2>まとめ</h2>
<p>現時点ではOpenSocialのOutbound OAuthではMySpaceがHMAC-SHA1方式でガジェットをコンシューマに、Shindig系コンテナはRSA-SHA1方式でコンテナをコンシューマにしていますので、外部サーバーとやり取りを多なうOpenSocialガジェットを作る場合、どちらからのリクエストも受け付けられるよう構築しておく必要がありそうです。</p>
<h2><strong>参考サイト</strong></h2>
<ul>
<li><a href="http://d.hatena.ne.jp/lyokato/20080818/1219081040" target="_blank">Outbound OAuthを実現するOAuth Proxy &#8211; Codin&#8217; In The Free World</a></li>
<li><a href="https://sites.google.com/site/oauthgoog/oauth-proxy" target="_blank">OAuth Proxy(Google OAuth &amp; Federated Login Research)</a></li>
</ul>

]]></content:encoded>
			<wfw:commentRss>http://devlog.agektmr.com/en/archives/174/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>OpenSocialアプリケーションを作る(2)</title>
		<link>http://devlog.agektmr.com/en/archives/41</link>
		<comments>http://devlog.agektmr.com/en/archives/41#comments</comments>
		<pubDate>Wed, 16 Apr 2008 17:37:50 +0000</pubDate>
		<dc:creator>Eiji</dc:creator>
				<category><![CDATA[OpenSocial]]></category>
		<category><![CDATA[Widget]]></category>
		<category><![CDATA[Gadget]]></category>
		<category><![CDATA[Orkut]]></category>

		<guid isPermaLink="false">http://devlog.agektmr.com/en/?p=41</guid>
		<description><![CDATA[
topsyWidgetPreload({ "url": "http%3A%2F%2Fdevlog.agektmr.com%2Fen%2Farchives%2F41", "style": "big", "title":  [...]]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_light-green" style="float: left;margin-right: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fdevlog.agektmr.com%252Fen%252Farchives%252F41%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22OpenSocial%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E4%BD%9C%E3%82%8B%282%29%22%20%7D);"><script type="text/javascript">topsyWidgetPreload({ "url": "http%3A%2F%2Fdevlog.agektmr.com%2Fen%2Farchives%2F41", "style": "big", "title": "OpenSocialアプリケーションを作る(2)" });</script></div>
<p><a rel="bookmark" href="http://devlog.agektmr.com/archives/22">OpenSocialアプリケーションを作る(1)</a>では、ガジェットの仕組みと、Orkutでアカウントを取得するところまで書きました。今回は、<a href="http://devlab.agektmr.com/OpenSocial/Orkut/FriendIntroducer.xml" target="_blank">前回紹介したアプリケーション</a>のコードを解説します。</p>
<p>このアプリケーション(FriendIntroducer)は、自分が見た場合は友達の紹介文を書くことができ、他人が見た場合はその人に向けて書かれた紹介文を読むことができる、というmixiなどにもよくある簡単なアプリケーションです。JavaScriptやjQuery的にはもっと賢い実装方法があると思いますが、今回はOpenSocialのコードにフォーカスしますので、アホなコードは大目に見てください。</p>
<h2>ガジェットXML</h2>
<pre class="brush: xml;">&lt; ?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;
&lt;module&gt;
&lt;moduleprefs title=&quot;Friend Introducer&quot; title_url=&quot;&quot; description=&quot;Introduce your friend!&quot; height=&quot;100&quot;&gt;
  &lt;require feature=&quot;opensocial-0.7&quot; /&gt;
  &lt;require feature=&quot;views&quot; /&gt;
  &lt;require feature=&quot;dynamic-height&quot; /&gt;
 &lt;/moduleprefs&gt;
&lt;content type=&quot;html&quot; view=&quot;canvas&quot;&gt;
  &lt; ![CDATA[
  &lt;link href=&quot;http://devlab.agektmr.com/OpenSocial/css/FriendIntroducer.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot;&gt;
  &lt;script type=&quot;text/javascript&quot; src=&quot;http://devlab.agektmr.com/OpenSocial/js/jquery.js&quot;&gt;&lt;/script&gt;
  &lt;script type=&quot;text/javascript&quot; src=&quot;http://devlab.agektmr.com/OpenSocial/js/FriendIntroducer.js&quot;&gt;&lt; /script&gt;
  &lt;/script&gt;&lt;script type=&quot;text/javascript&quot;&gt;
    gadgets.util.registerOnLoadHandler(FriendIntroducer.init);
  &lt;/script&gt;
  &lt;div id=&quot;title&quot;&gt;&lt;/div&gt;
  &lt;div id=&quot;friends&quot;&gt;&lt;/div&gt;
  &lt;div id=&quot;message&quot;&gt;&lt;/div&gt;
  ]]&gt;
 &lt;/content&gt;
&lt;/module&gt;</pre>
<p>ここでは</p>
<ul>
<li>ガジェットの設定</li>
<li>外部のCSSやJavaScriptを読み込み</li>
<li>初期化スクリプトの呼び出し</li>
<li>表示用DIV指定</li>
</ul>
<p>を行っています。</p>
<pre class="brush: xml;">&lt;content type=&quot;html&quot; view=&quot;profile&quot;&gt;</pre>
<p>Contentはhtmlタイプ、profileビューと指定しました。typeにはhtmlとurlが選択可能ですが、htmlとして内容をContentタグで囲まれた部分に記述しています。viewはOpenSocialの仕様上profile、canvasが想定されていますが、コンテナによってhomeやpreviewが存在するようです。ここでは例としてcanvasを使用しています。</p>
<p>また、viewを指定しない場合はdefaultビューとして扱われます。コンテナは表示場面(コンテキスト)によってビューを切り替えますが、Content内でviewを取り出してJavaScriptで処理を分ける方法もあります。</p>
<h2>Contentの内容</h2>
<p>Contentの内容は、基本的に通常のウェブページと同じように扱うことができ、HTMLで書くことができますが、</p>
<pre class="brush: xml;">  &lt;script type=&quot;text/javascript&quot;&gt;
    gadgets.util.registerOnLoadHandler(FriendIntroducer.init);
  &lt;/script&gt;</pre>
<p>このようにgadgets.util.registerOnLoadHandlerを使って初期化処理を入れることができます。</p>
<p>このアプリケーションでは、表示テンプレートとして空のdivタグを3つ用意しています。</p>
<h2>JavaScriptのコード</h2>
<p>JavaScriptのソースコードは<a href="http://devlab.agektmr.com/OpenSocial/js/FriendIntroducer.js" target="_blank">ここ</a>にありますが、抜粋して紹介します。</p>
<pre class="brush: jscript;">    $('#friends').html('Requesting friends...');
    var req = opensocial.newDataRequest();
    req.add(req.newFetchPersonRequest('VIEWER'), 'viewer');
    req.add(req.newFetchPeopleRequest('VIEWER_FRIENDS'), 'friends');
    req.add(req.newFetchPersonAppDataRequest('VIEWER', 'Introduction'), 'intro');
    req.send(FriendIntroducer.onLoadViewerFriends);</pre>
<p>最も基本的な処理となる、閲覧者、閲覧者の友達、保存したデータを取り出す処理です。</p>
<p>opensocial.newDataRequest()でデータリクエストオブジェクトを作り、addで3種類のリクエストを追加、最後にsendでコールバック関数を指定した上、データリクエストを送信しています。3種類のリクエストにはそれぞれ後で区別するためviewer, friends, introという名前(キー)を付けています。</p>
<pre class="brush: jscript;">   var viewer    = response.get('viewer').getData();
   var friends   = response.get('friends').getData();
   var intro     = response.get('intro').getData();</pre>
<p>コールバック関数では、引数(response)を使って、response.get(キー名).getData()でリクエストしていたデータを取り出すことができます。</p>
<pre class="brush: jscript;">    var viewer_id = viewer.getId();
    var json = null;
    if (intro[viewer_id]) {
      if (intro[viewer_id].Introduction) {
        var json_str = gadgets.util.unescapeString(intro[viewer_id].Introduction);
        var json = eval(json_str)[0];
      }
    }</pre>
<p>introは、このアプリケーションを使ってコンテナのデータ保存領域に予め保存しておいた内容、つまり「以前保存した友達の紹介文」です。</p>
<pre class="brush: jscript;">    $('#title').html('&lt;p&gt;Friends of '+viewer.getDisplayName()+':&lt;/p&gt;');
    var html = '';
    if (friends.size() == 0) {
      $('#message').html(&quot;&lt;p&gt;You don't have any friends yet!&lt;/p&gt;&quot;);
    }</pre>
<p>友達が誰もいない場合を考慮して、メッセージを表示しています。</p>
<pre class="brush: jscript;">    friends.each(function(person) {
      var t = FriendIntroducer.template.friend_list_canvas;
      t = t.replace('##thumbnail_url##', person.getField(opensocial.Person.Field.THUMBNAIL_URL));
      t = t.replace('##profile_url##',   person.getField(opensocial.Person.Field.PROFILE_URL));
      t = t.replace('##display_name##',  person.getDisplayName());
      t = t.replace('##input_id##',      'input_'+person.getId());
      if (json) {
        t = t.replace('##intro_text##',  json[person.getId()] ? json[person.getId()] : '');
      } else {
        t = t.replace('##intro_text##', '');
      }
      html += t;
    });
    $('#friends').html('&lt;ul&gt;'+html+'&lt;/ul&gt;');</pre>
<p>OpenSocialでは配列をなめる、いわゆるiterationも仕様に含まれていて、eachを使うことができます。ここでは、友達のリストをループして、友達の名前やサムネイル画像、保存されていた紹介文をHTMLテンプレートに埋め込んでいきます。</p>
<p style="text-align: center;"><a href="http://devlog.agektmr.com/wp-content/uploads/2008/03/orkut5.jpg"><img title="Orkut5" src="http://devlog.agektmr.com/wp-content/uploads/2008/03/orkut5.jpg" alt="" width="300" height="264" /></a></p>
<p>ここまでで、友達の紹介文を書き込むことができるcanvasページの表示することができました。次に、友達の紹介文をユーザーが書き込んだものと想定し、投稿して保存するところまでを解説します。</p>
<h2>データの保存</h2>
<p>OpenSocialはコンテナにデータ保存領域を持っており、アプリケーションがデータを保存することができます。これはパーシステントデータ(Persistant data)や、アプリケーションデータ(AppData)と呼ばれています。アプリケーションデータはバージョン0.7では<strong>エスケープした文字列のみ</strong>サポートしています(次のバージョンではJSONそのものの保存も可能になるようです)。</p>
<pre class="brush: jscript;">    var list = $('#friends ul li');
    var intro = &quot;{result:[{&quot;;
    for (var i=0; i &lt; list.length; i++) {
      var textarea = list[i].lastChild.lastChild;
      var uid = textarea.id.substring(6);
      var intro_text = textarea.value.replace(&quot;'&quot;, &quot;\'&quot;);;
      intro += &quot;'&quot;+uid+&quot;':'&quot;+intro_text+&quot;'&quot;;
      intro += (list.length-1)==i ? &quot;&quot; : &quot;,&quot;;
    };
    intro += '}]};';
    var req = opensocial.newDataRequest();
    intro = gadgets.util.escapeString(intro);</pre>
<p>この処理は、ユーザーが友達の紹介文を書き終わって「投稿ボタン」を押すことでトリガーされるものです。DOMを辿って各友達のユーザーIDと紹介文の内容を取得する、普通のJavaScriptです。取得した内容はJSONの文字列になるよう連結し、エスケープすることで、アプリケーションデータとして保存が可能になります。</p>
<pre class="brush: jscript;">    req.add(req.newUpdatePersonAppDataRequest('VIEWER', 'Introduction', intro));
    req.send(function() {
      $('#message').html('&lt;p&gt;Your introduction has been submitted.');
    });</pre>
<p>最後に、JSON形式になった文字列をデータリクエストオブジェクトに追加して送信して、完了です。</p>
<h2>まとめ</h2>
<p>解説というよりはソースコード並べただけみたいな記事になってしまいましたが、OpenSocialアプリケーションのほとんどがJavaScriptでできてしまうということは、分かったかと思います。次回は外部サーバーとの連携を行うmakeRequestに触れたいと思います。</content></p>

]]></content:encoded>
			<wfw:commentRss>http://devlog.agektmr.com/en/archives/41/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>OpenSocialアプリケーションを作る(1)</title>
		<link>http://devlog.agektmr.com/en/archives/22</link>
		<comments>http://devlog.agektmr.com/en/archives/22#comments</comments>
		<pubDate>Sun, 30 Mar 2008 07:01:26 +0000</pubDate>
		<dc:creator>Eiji</dc:creator>
				<category><![CDATA[OpenSocial]]></category>
		<category><![CDATA[Widget]]></category>
		<category><![CDATA[Gadget]]></category>
		<category><![CDATA[Orkut]]></category>

		<guid isPermaLink="false">http://devlog.agektmr.com/en/archives/22</guid>
		<description><![CDATA[
topsyWidgetPreload({ "url": "http%3A%2F%2Fdevlog.agektmr.com%2Fen%2Farchives%2F22", "style": "big", "title":  [...]]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_light-green" style="float: left;margin-right: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fdevlog.agektmr.com%252Fen%252Farchives%252F22%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22OpenSocial%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E4%BD%9C%E3%82%8B%281%29%22%20%7D);"><script type="text/javascript">topsyWidgetPreload({ "url": "http%3A%2F%2Fdevlog.agektmr.com%2Fen%2Farchives%2F22", "style": "big", "title": "OpenSocialアプリケーションを作る(1)" });</script></div>
<p>OrkutとMySpaceで自作アプリを動かしてみたので、そのレポートです。</p>
<p>まだ仕様が固まっていないのでグレーな部分も多いのですが、OpenSocialはGoogleGadgetと相性が良いらしく、OrkutもMySpaceも、hi5もGoogleGadget前提となっています。というわけで、今回はGoogleGadgetの基本的な作り方とOrkutへのアプリケーション追加方法の解説です。</p>
<h2>ガジェットとは何か</h2>
<p>GoogleGadgetは<a href="http://www.google.com/ig?hl=ja" target="_blank">iGoogle</a>で動くJavaScriptとHTMLで記述された簡単なアプリケーションです。JavaScriptとHTMLはXML上に埋め込み、設定内容もXMLに記述します。</p>
<pre class="brush: jscript;">&lt; ?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;
&lt;module&gt;
 &lt;moduleprefs title=&quot;Blah Blah Gadget&quot;
  description=&quot;Gadget Example&quot;
  author_email=&quot;***@***.com&quot;
 &gt;
 &lt;/moduleprefs&gt;
 &lt;content type=&quot;html&quot;&gt;
.....
 &lt;/content&gt;
&lt;/module&gt;</pre>
<p>XMLはこんな感じ。Contentの中にJavaScriptとHTMLを記述することで、その内容がiGoogle上やMySpace等のOpenSocialアプリケーションとして表示されます。</p>
<p>ガジェットはJavaScriptを許可していることから、XSSなどの脆弱性を回避するため、iframeを使って別ドメインで動作するようになっています(iGoogleの場合、gmodules.com)。Contentの属性であるtypeを&#8221;html&#8221;から&#8221;url&#8221;に変更し、hrefでURL指定すると、iframe内に自分の管理するサーバーを表示することも可能です。</p>
<p>GoogleGadget自体の仕様は掘り下げるとキリがないのでこの辺りで。詳細は<a href="http://code.google.com/intl/ja/apis/gadgets/docs/reference.html" target="_blank">リファレンス</a>をご覧ください。</p>
<h2>OrkutのSandboxアカウントを取得する</h2>
<p>OrkutはGoogle直結ということもあり、OpenSocialの仕様が最も早く反映されるようです。そのOrkutのOpenSocial実験環境は<a href="http://sandbox.orkut.com/" target="_blank">Sandbox</a>と呼ばれ、通常のOrkutアカウントを拡張したSandboxアカウントを取得することで、利用可能となります。</p>
<p>アカウントを取得するには<a href="http://code.google.com/support/opensocialsignup/">コチラ</a>から申請を行ってください。申請が受理されるまでには数日を要するようです。</p>
<h2>OrkutにOpenSocialアプリを追加する</h2>
<p>無事アカウントの取得ができたら、実際にアプリケーションを試すことができるようになります。ちなみに、どこかのサーバーにGoogleGadgetのXMLファイルを置いておく必要がありますので、Geocitiesでも何でもいいはずですので、ファイルをアップできるところを用意しておきましょう。</p>
<p><a href="http://devlog.agektmr.com/wp-content/uploads/2008/03/orkut1.jpg" title="Orkut1"><img src="http://devlog.agektmr.com/wp-content/uploads/2008/03/orkut1.jpg" alt="Orkut1" /></a><a href="http://devlog.agektmr.com/wp-content/uploads/2008/03/orkut1.jpg" title="Orkut1"> </a></p>
<p>Sandboxにログインするとこんな感じ。一見通常のログイン画面と変わりませが、一点だけ：</p>
<p><a href="http://devlog.agektmr.com/wp-content/uploads/2008/03/orkut2.jpg" title="Orkut2"><img src="http://devlog.agektmr.com/wp-content/uploads/2008/03/orkut2.jpg" alt="Orkut2" /></a></p>
<p>画面左にアプリケーションを追加するリンクがあります。クリックすると・・・</p>
<p><a href="http://devlog.agektmr.com/wp-content/uploads/2008/03/orkut3.jpg" title="Orkut3"><img src="http://devlog.agektmr.com/wp-content/uploads/2008/03/orkut3.jpg" alt="Orkut3" /></a></p>
<p>URLでXMLファイルを指定してアプリケーションを追加することが出来ます。(ちなみにアプリケーションディレクトリはいつもほとんどアプリがありません)</p>
<p>ここでは、僕の作ったアプリケーションで試してみましょう。URLに下記を入力します：</p>
<pre>http://devlab.agektmr.com/OpenSocial/FriendIntroducer.xml</pre>
<p>「アプリケーションを追加」ボタンを押すと、次の画面に遷移します。</p>
<h2><a href="http://devlog.agektmr.com/wp-content/uploads/2008/03/orkut4.jpg" title="Orkut4"><img src="http://devlog.agektmr.com/wp-content/uploads/2008/03/orkut4.jpg" alt="Orkut4" /></a></h2>
<p>ここでも「アプリケーションを追加」ボタンを押すことで、アプリケーションの追加が完了します。</p>
<p><a href="http://devlog.agektmr.com/wp-content/uploads/2008/03/orkut5.jpg" title="Orkut5"><img src="http://devlog.agektmr.com/wp-content/uploads/2008/03/orkut5.jpg" alt="Orkut5" /></a></p>
<p>こんな感じの画面が表示されたら成功。Orkut上に友達がいない方は、<a href="http://sandbox.orkut.com:80/Profile.aspx?uid=2129608995524995619" target="_blank">僕のアカウント</a>に友達申請してくれてもOKです。</p>
<p>ひとまず、第一回はここまで。</p>
<p><a href="http://devlog.agektmr.com/wp-content/uploads/2008/03/orkut4.jpg" title="Orkut4"> </a></p>

]]></content:encoded>
			<wfw:commentRss>http://devlog.agektmr.com/en/archives/22/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>OpenSocialの疑問がひとつ解決した</title>
		<link>http://devlog.agektmr.com/en/archives/10</link>
		<comments>http://devlog.agektmr.com/en/archives/10#comments</comments>
		<pubDate>Sat, 15 Mar 2008 14:02:43 +0000</pubDate>
		<dc:creator>Eiji</dc:creator>
				<category><![CDATA[OpenSocial]]></category>
		<category><![CDATA[Widget]]></category>
		<category><![CDATA[Gadget]]></category>
		<category><![CDATA[Orkut]]></category>

		<guid isPermaLink="false">http://devlog.agektmr.com/en/archives/10</guid>
		<description><![CDATA[
topsyWidgetPreload({ "url": "http%3A%2F%2Fdevlog.agektmr.com%2Fen%2Farchives%2F10", "style": "big", "title":  [...]]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_light-green" style="float: left;margin-right: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fdevlog.agektmr.com%252Fen%252Farchives%252F10%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22OpenSocial%E3%81%AE%E7%96%91%E5%95%8F%E3%81%8C%E3%81%B2%E3%81%A8%E3%81%A4%E8%A7%A3%E6%B1%BA%E3%81%97%E3%81%9F%22%20%7D);"><script type="text/javascript">topsyWidgetPreload({ "url": "http%3A%2F%2Fdevlog.agektmr.com%2Fen%2Farchives%2F10", "style": "big", "title": "OpenSocialの疑問がひとつ解決した" });</script></div>
<p><strong>前提：Google Gadgetでurlタイプを指定した場合、iframe内にはリモートサーバーの内容がそのまま表示されるため、Ajaxで友達情報等を取得しようとすると、ドメイン超えが必要となり、プロキシ経由でサーバー間通信となりRESTful APIがないと役に立たない</strong></p>
<p>どうやらOrkutでは、Content Type=&#8217;url&#8217;を許可していない模様。</p>
<p><a href="http://groups.google.com/group/opensocial-orkut/browse_thread/thread/f6de89397dc56576/70f57151180b87cb?lnk=gst&amp;q=content+type+url#70f57151180b87cb" target="_blank">MYSQL database connection using PHP for my gadget ? &#8211; Orkut Developer Forum | Google グループ</a></p>
<p>Content Type=&#8217;url&#8217;を指定すると404が返るらしい。 404が返ること自体はバグとのことですが、Content Type=&#8217;url&#8217;が動くようになったところで、ドメインを超えてOpenSocialを利用するにはプロキシを介したRESTful APIによるアクセスが必須であることは確認できました。これがRESTful APIが正式に登場するまでの暫定措置なのかどうかは未確認ですが、前提は誤っていなかったようです。</p>

]]></content:encoded>
			<wfw:commentRss>http://devlog.agektmr.com/en/archives/10/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
