LDR Full Feed Opera ver0.2

Opera9.50 build9841(2008/03/18)で、UserJSのセキュリティポリシーが変更されたらしく、このScriptは動作しなくなっています。document.postMessageがwindow.postMessageに変わっただけというオチだった模様

LDR Full Feed 0.0.8 - 枕を欹てて聴くと同じくセキュリティFIXです。

http://ss-o.net/userjs/ldrfullfeed.js

タグを取得する方法をホワイトリスト相当の実装にしたので、XSSの危険性は格段に下がったはず。が、最低限の属性(imgのsrcとaのhrefだけ)しか許可していないので、こちらは近日中に再度手を入れると思う。ご了承を。


一応、エスケープの中身について解説。
nodeがElementだったらchildNodesに潜り、textNodeだったらテキストを返すってのを再帰的にやってます。で、ElementはtagNameをみて、imgやaなどの属性だけを拾ってあげています。この部分を磨けばちゃんと色々表示できるはず。

var safeNode2String = function(node){
  if (node.nodeType != Node.ELEMENT_NODE && node.nodeType != Node.TEXT_NODE) return;
  var func = arguments.callee;
  var nodes = node.childNodes;
  var contents =[];
  for (var i=0,l=nodes.length;i<l;i++){
    var content = func(nodes[i]);
    if(content) contents.push(content);
  }
  if (node.nodeType == Node.ELEMENT_NODE){
    var tag = node.tagName;
    var attr = (function(){
      var res=[''];
      switch(tag){
        case 'IMG':
          if (node.src.match(/^http:/) ) res.push('src="' + node.src + '"' );
          break;
        case 'A':
          if (node.href.match(/^http:/) ) res.push( 'href="' + node.href + '"' );
          break;
        default:
          break;
      }
      return res.join(' ');
    })();
    return '<' + tag + attr + '>' + contents.join('') + '</'+tag+'>';
  } else if (node.nodeType == Node.TEXT_NODE) {
    return node.nodeValue;
  }
};

OperaでLDR Full Feed

id:Constellation さん作の、LDR Full Feed for GreasemonkeyOperaに移植してみた。

注意事項

LDRに外部のテキストを読み込むため、Cross Site Scriptingの危険性があります。初歩的な対策(scriptタグの除去とタグの属性の除去)は行っていますが、安全であると保障されているわけではありません。脆弱性が発見された場合は可能な限り対応しますが、対応が遅れる場合もあります。また、更新は手動で行っていただく必要がある点もご了承ください。

  • ショートカット
    • g で現在のエントリーを取得、取得済みの場合は元に戻す(戻すのはOpera版オリジナル)
    • y で次の取得可能なエントリーを先読みしてキャッシュ(Opera版オリジナル)
    • G(Shift+g) でSITEINFOを再取得
  • 本家との違い
    • 先読み機能(上記、ショートカットのy)
    • SITEINFOのキャッシュなし
      • OperaではキャッシュをCookieに入れるしかない、(SITEINFOの取得回数==LDRへのアクセス数)となるだけなので、必要ないと判断。
    • documentFiltersの実装が異なる(多くの人にとって、意識することはありません)
      • 本家では、取得したテキストをHTMLに変換し、そのHTMLに対してdocumentFiltersをかけてからXPATHによる切り出しを行っている(その後、切り出した要素をページに追加したあとにfiltersがかかる)
      • Opera版では、iframe相当のobjectのなかでXPATHによる切り出しを行い文字列にしてLDRに送る、LDR側では受け取った文字列をHTML要素に戻して、その要素にdocumentFiltersをかけてからページに追加している。(その後、filtersがかかるのは同じ)

Opera9.26で動作。
Safari版はちょっと難しいかも。(iframeのScriptの処理がOperaと大きく違うっぽい)

更新

  • 2009/02/23 02:35
    Opera10で動かなかった問題を修正(OperaのpostMessageの実装(Opera10でLDR Full Feedを動くように) - 0xFF)
  • 2008/02/27 16:34
    Opera9.50bで動かなかった問題を修正
  • 2008/02/27 23:58
    任意のページから任意のページを読めてしまう大問題を修正
    • ちょっといい訳しますと、元々postMessageでデータをやり取りしていて、そのときはlivedoorドメインをチェックしていました。 ただ、 postMessageを省略してwindow.nameを使うズルを思いついてしまい*1、試したらあっさりうまくいったので、domainチェックがなくなっているのをすっかり忘れて公開してしまいました。。すみません。

OperaでGM_xmlhttpRequest相当のことをするために、http://developer.mozilla.org/en/docs/DOM:window.postMessageOpera版の実装(document.postMessage)を使っている。気合入れればほとんどのクロスドメインなGreasemonkey ScriptをpostMessageでOpera用に書き直すことはできるんだけど、postMessageはコードの量は多くなるし、単純に難易度が高い感じ。

*1:これにより、onloadを待つ必要がなくなったため、劇的な高速化ができています