« 2008年10月 | メイン | 2008年12月 »



2008年11月 アーカイブ

2008年11月04日

ブクマのサジェストつくってみた(重い。。。)

ブクマのサジェストつくってみた(重い。。。)をはてなブックマークに追加 ブクマのサジェストつくってみた(重い。。。)をdel.icio.usに追加  Yahoo!ブックマークに登録 ブクマのサジェストつくってみた(重い。。。)をGoogle Bookmarksに追加 ブクマのサジェストつくってみた(重い。。。)をtwitterにポスト
というわけで、作ってみました。
私はpost2sbmでdeliciousとtwitterとはてなに対していっぺんにブックマークをポストしているのですが、今見てるページはどんなタグでブックマークされているのかなー?とかいう機能をつけてみたい!というとこから作ってみました(クライアント側は作ってないです)。
タグの集計までは結構さくさくいくのですが、欲が出てその先のそのタグを付けた人は、他に同じタグでどんなページをブクマしているのか?ってのも欲しくなって、これを実装したらアホみたいに重くなりました。
PHPで実装しているのですが、ちょっといろいろダメだろこれ的なところが沢山ありそうです。XMLパーサはサーバがPHP4だからそういう作りになっちゃいました。PHP5になればsimpleXMLとかが使えるらしいのですがよくわからん。
クライアントのグリモンとかubiquityコマンドはまだ手つかずなのですが、もしかしたら全部クライアントでやった方が体感早いのかもしれません。そうなったらそうなったでそうする。

gigazineのページを渡すとこんな感じで返してくる。ブックマークレットにすると↓な感じ。
javascript:void(location.href="http://mojalog.com/mojascript/hatena.php?p="+encodeURI(location.href))
とりあえずやってみたかったのは、
・ブクマしようとしているページをはてブのRSSからひろう。
・で、タグを集計する
・タグの嵩みが多い順にソートする
・そのタグを付けたユーザのブクマRSSを拾う。
・このページをブックマークしているユーザはこんなタグで他のこんなページもブックマークしてますよ的な表示をさせてあわよくば*あとで読むタグを付けながら一緒にブクマできるようなインターフェイスを設ける
てことをやりたい。恥ずかしながらソースを載せてみる(股間を隠しry)。ここは普通こうすんだろJK的な事があったら教えてほしいです><(←><ってやると優しく教えてくれるらしいよってvipに載ってた)(うそ)
<?php
    $targetUrl = $_GET[ "p" ];
    mb_internal_encoding('UTF-8');
    mb_http_output('UTF-8');
    mb_detect_order('ASCII,JIS,UTF-8,EUC-JP,SJIS');

    class xml {

        var $parser;
        var $refTag;
        var $suggestUser;
        var $curData;
        
        var $keyList;
        var $suggestList;
        var $urlList;

        function xml(){
            $this->keyList = array();
            $this->suggestList = array();
            $this->urlList = array();

            $this->suggestUser = "";
            $this->curData = "";
            
            $this->parser = xml_parser_create( 'UTF-8' );
            xml_set_object( $this->parser, $this );
            xml_set_element_handler( $this->parser, "TagOpen", "TagClose" );
            xml_set_character_data_handler( $this->parser, "CData" );
        }
        
        function parse( $data ){
            xml_parse( $this->parser, $data );
        }

        function TagOpen( $parser, $tag, $attributes ){
            $this->refTag = $tag;
        }

        function CData( $parser, $cdata ){
            if( strcmp( $this->refTag, "TITLE" ) == 0 ){
                $this->suggestUser = trim( $cdata );
            }

            if( strcmp( $this->refTag, "DC:SUBJECT" ) == 0 || strcmp( $this->refTag, "LINK" ) == 0 ){
                $this->curData .=  $cdata;
            }
        }

        function TagClose( $parser, $tag ){

            if( strcmp( $tag, "DC:SUBJECT" ) == 0 ){
                $this->keyList[ $this->curData ] = ( isset( $this->keyList[ $this->curData ] ) )
                    ? $this->keyList[ $this->curData ] + 1
                    : 1;
                $this->suggestList[ $this->curData ] = ( isset( $this->suggestList[ $this->curData ] ) )
                    ? $this->suggestList[ $this->curData ] . ',' . $this->suggestUser
                    : $this->suggestUser;
            }

            if( strcmp( $tag, "LINK" ) == 0 ){
                $this->urlList[ $this->curData ] = $this->suggestUser;
            }

            if( strcmp( $tag, "DC:SUBJECT" ) == 0 || strcmp( $tag, "LINK" ) == 0 || strcmp( $tag, "TITLE" ) == 0 ){
                $this->curData = "";
            }
            $this->refTag = "";

        }

        function getSuggestList(){
            return $this->suggestList;
        }

        function getKeyList(){
            return $this->keyList;
        }

        function getUrlList(){
            $ary = $this->urlList;
            $this->urlList = array();
            return $ary; 
        }
    }

    $suggestList = array();
    $keyList = array();
    require_once( 'HTTP/Request.php' );
    $req =& new HTTP_Request( "http://b.hatena.ne.jp/entry/rss/" . $targetUrl );
    $req->setMethod( HTTP_REQUEST_METHOD_GET );
    if ( !PEAR::isError( $req->sendRequest() ) ) {
        $res = $req->getResponseBody();
        $xml_parser = new xml();
        $xml_parser->parse( $res );
        $suggestList = $xml_parser->getSuggestList();
        $keyList = $xml_parser->getKeyList();
        unset( $xml_parser );
    }
    $req->clearPostData();

    arsort( $keyList );

    header('Content-Type: text/xml');
    $xml =<<< EOD
<?xml version="1.0" encoding="UTF-8" ?>
<itemlist>
EOD;
    echo $xml . "\n";

    $loopCount = 0;
    while( list( $key, $val ) = each( $keyList ) ) {

        echo "<elem>\n";
        echo "<tagname>" . htmlspecialchars( $key ) . "</tagname>\n";

        $usersList = split( ",", $suggestList[ $key ] );
        $userBkm =& new HTTP_Request( "http://b.hatena.ne.jp/" . $usersList[ rand( 1, count( $usersList ) -1 ) ] . "/rss?tag=" . urlencode( $key ) );
        $userBkm->setMethod( HTTP_REQUEST_METHOD_GET );
        if ( !PEAR::isError( $userBkm->sendRequest() ) ) {
            $res = $userBkm->getResponseBody();
            $xml_parser = new xml();
            $xml_parser->parse( $res );
            $tempList = $xml_parser->getUrlList();
            $nLoopCount = 0;
            while( list( $nkey, $nval ) = each( $tempList ) ) {
                $nLoopCount++;
                if( $nLoopCount < 2 ){
                    continue;
                }
                echo "<suggest>\n";
                echo "<title>" . htmlspecialchars( $nval ) . "</title>\n";
                echo "<link>" . htmlspecialchars( $nkey ) . "</link>\n";
                echo "</suggest>\n";
            }
            unset( $xml_parser );
        }
        $userBkm->clearPostData();

        echo "</elem>\n";
        $loopCount++;
        if( $loopCount >= 3 ) break;
    }
    echo "</itemlist>";
?>

[ 最近のエントリーとその関連エントリー ]


[ スポンサードリンク ]

2008年11月25日

数学ガールコミック版買ったよ

数学ガールコミック版買ったよをはてなブックマークに追加 数学ガールコミック版買ったよをdel.icio.usに追加  Yahoo!ブックマークに登録 数学ガールコミック版買ったよをGoogle Bookmarksに追加 数学ガールコミック版買ったよをtwitterにポスト
DSCF3109.JPG 発売日に横浜のルミネを通ったときに数学ガールコミック版を買ってきました。コミックの棚を探してみたのですが、見つからなかったので店員さんに書籍検索はないか?と聞いたら、「ご自分で調べるか、私の方で承るか」を問われ少し悩んで調べてもらった。「理系男子最強の萌え—」に悩んだ。

「書籍名はえー・・・と、『数学が、在る』でよろしかったでしょうか?」
などと言いやがるのでとりあえず 愛想笑いと苦笑いが入り混じった笑いをクールにしようと思った。
「はは…、いや、数学ガールです。すみません」
こんな風に落ち着いて言いたかったのだが、緊張やら恥ずかしいやらでもう舌が回らず
「フヒヒヒヒ! すいません!」
もろ変態みたいに言ってしまった。
相当恥ずかしかったよ。
その後ロボットみたいな歩き方でどっか行った。

などというコピペはどうでもよろしいのですが、内容の方はと言いますと、丁寧に原作をそのままマンガ化されています。俺は「萌え」という感覚に疎いので期待される読み方(そんなものがあれば)をしていないのかもしれないけれど、マンガだとやっぱり読みやすいです。
ここまで書いて

読みやすい

しか出てこないので、このコピペが貼りたかっただけなんだと改めて思った。(ゲスヤロウ)

[ 最近のエントリーとその関連エントリー ]


2008年11月19日

crossdomain.xmlでさらにハマる

crossdomain.xmlでさらにハマるをはてなブックマークに追加 crossdomain.xmlでさらにハマるをdel.icio.usに追加  Yahoo!ブックマークに登録 crossdomain.xmlでさらにハマるをGoogle Bookmarksに追加 crossdomain.xmlでさらにハマるをtwitterにポスト
昨日のエントリの続きです。結局、クロスドメインはcrossdomain.xmlをおいて解決しようと思ってサーバルートに置いてみましたが、なぜかフラッシュがサービスを呼んでくれない。。もう半泣き。なにこれ。firebugで接続を見るとcrossdomain.xmlは読み込んでいるようなのでパスは間違ってなさそうです。が、コールしない。サーバ側のサービスログにも呼ばれた形跡がない。グーグルで探してみても「置けば動いた」みたいなもんばっかり。

で、すごい煮詰まってたところ、もうひとつの端末から呼んだらスコンと動いた。なんだと。IEか?先輩の端末からも試してもらってみると動くものと動かないものがある。動かない方の端末は、オレのも先輩のもいろいろインストールしたり結構使い倒してる方。あまりいじってないのが動く。で調べてみると、

flushPlayerのバージョンにより、crossdomain.xmlに記述する内容が追加されるので注意が必要

だと言う事がわかりました。
とりあえずcrossdomain.xmlを置いた当初の記述は以下の内容です。
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
    <site-control permitted-cross-domain-policies="all" />
    <allow-access-from domain="*" />
</cross-domain-policy>
上記の設定だけで動いた端末のflushPlayerのバージョンは9,0,115,0。
使い倒してる方の端末はバージョンが9,0,124,0以上で、そういう場合はさらに追記が必要だという事みたい。
   <allow-http-request-headers-from domain="*" headers="*"/>
多分、冗長な箇所があると思いますが、とりあえず動いたのでよしとします。
via : Flash Player 9およびFlash Player 10ベータのポリシーファイル変更点への対応をみると、どうやら
ドメインを超えたネットワークリクエストにおいて、カスタムのHTTPヘッダが送られるようなSWFファイルを開発したデベロッパー
にあたるらしい。flex builderでwsdlをインポートしたパッケージを使ったからかな?

[ 最近のエントリーとその関連エントリー ]


2008年11月18日

統合認証のダブルホップ問題とクロスドメインで死んだ

統合認証のダブルホップ問題とクロスドメインで死んだをはてなブックマークに追加 統合認証のダブルホップ問題とクロスドメインで死んだをdel.icio.usに追加  Yahoo!ブックマークに登録 統合認証のダブルホップ問題とクロスドメインで死んだをGoogle Bookmarksに追加 統合認証のダブルホップ問題とクロスドメインで死んだをtwitterにポスト
お仕事でwindowsにアパッチたてて、tomcatと連携してさらにwindows統合認証もほしいのでmod_auth_sspi使って認証通ってアプリ動いたー!なんてとこまでは上手くいってたんですが、問題が出てきたのがエントリタイトルの「統合認証のダブルホップ問題とクロスドメイン」です。

今回このお仕事で作った(作ってもらった)サーバはServerPiyoとして、アプリケーションは主にjavaで作られています。で、ベンダーさんとのやり取りはというと
オレ:あ、こっちのServerMogeでもそっちのデータ欲しいのでServerPiyoでサービス作ってー
ベンダ:いいよー。でもクロスドメイン的なのはどうすんのー?
オレ:こっちでプロキシサービスっぽいの組むよー
ベンダ:オケオケ。作ったよー。認証はアパッチのmod_auth_sspiでやってるから認証情報はそっちのプロキシっぽいサービスからリレーしてー
オレ:あーでも、認証の前にクロスドメイン的な問題は、json的なコールバック的な実装も欲しいなー。
ベンダ:ギャハー。的々うぜー無理無理。てか、soapで作ってるよー。RESTにしたりJSONとかコールバックとか.net的にうまいの?てかクライアントからも呼ぶの?なんなの?
オレ:どうだろ。言われてみれば.netでプロキシっぽいの作るなら、soapの方がやりやすそうだなー。オケオケ。soapオケ。認証はたしかCredentialCache.DefaultCredentials的なとこでリレーできたよなー。じゃあそれでー。
ベンダ:オケオケ
オレ:じゃあ結合ねー
ベンダ:オケオケ
オレ:401www
ベンダ:オケオケwwww
ということでいろいろググったら統合認証のダブルホップ問題で認証はリレーしないと言われた。なんなの。馬鹿なの。死ぬの?(オレが)
mod_auth_sspiの検証をしているときにNTLMはプロキシ通さないけどケルベロスならいけるとかいうエントリ見たような気がするし、今回作ろうとしたプロキシサービスもやることはまんまプロキシだし。調べてみるとダブルホップ問題はケルベロス通すらしいし、mod_spnego(ケルベロス認証のモジュール)とか調べてケルベロスでgo!しそうだったんだけどNTLMに倒れてgoした。後の祭り。どうしよう。

というわけで、
・ServerPiyoのサービスをRESTで呼べるようにServerPiyoでラップしてコールバックできるようにしてJSONで返す。
・か、crossdomain.xmlをServerPiyoサーバにおいてServerMogeはflexでデータレンダリングする。
・か、crossdomain.xmlをServerPiyoサーバにおいてServerMogeはcrossdomain.swf的なものをおいてjavascriptにリレーするか。
あと、丁寧に謝る。やばいー。あした結果出さなきゃヤバい。

[ 最近のエントリーとその関連エントリー ]


2008年11月17日

なんでこれほどまでに感動するんだろう。

なんでこれほどまでに感動するんだろう。をはてなブックマークに追加 なんでこれほどまでに感動するんだろう。をdel.icio.usに追加  Yahoo!ブックマークに登録 なんでこれほどまでに感動するんだろう。をGoogle Bookmarksに追加 なんでこれほどまでに感動するんだろう。をtwitterにポスト
なんでなんだぜ?

高画質で見た方がいい感じです。エンベッドがどうやるかわからなかった。

[ 最近のエントリーとその関連エントリー ]


2008年11月13日

もしかしてmojalogきたこれ

もしかしてmojalogきたこれをはてなブックマークに追加 もしかしてmojalogきたこれをdel.icio.usに追加  Yahoo!ブックマークに登録 もしかしてmojalogきたこれをGoogle Bookmarksに追加 もしかしてmojalogきたこれをtwitterにポスト
googlemojallog.png googleでmojallogってまつがって検索したらもしかしてmojalogっていわれた!!mojalogのmoja色天然水イヤッフゥー!マンマミーヤ!(みんな逃げてー)

[ 最近のエントリーとその関連エントリー ]


2008年11月12日

MD5のコードリーディングしてみた→わからない→誰か説明s(いまココ)

MD5のコードリーディングしてみた→わからない→誰か説明s(いまココ)をはてなブックマークに追加 MD5のコードリーディングしてみた→わからない→誰か説明s(いまココ)をdel.icio.usに追加  Yahoo!ブックマークに登録 MD5のコードリーディングしてみた→わからない→誰か説明s(いまココ)をGoogle Bookmarksに追加 MD5のコードリーディングしてみた→わからない→誰か説明s(いまココ)をtwitterにポスト
MD5のコードリーディングをしてみました。
MD5 メッセージダイジェストアルゴリズムに日本語訳されたRFCが載っていて非常に参考になりました。Cのソースも載っているんだけど、今回は高度なjavascript集から拾ってきて、読みながら書いてみながらいじくり回してみました。

firebugで1ステップずつ見ていきながら、この処理ではsin関数(ソースではあらかじめ値をsinTbl配列に書き出してあります)がでてきて、ここはパディング処理が出てきて、ここはMD5アルゴリズムとは関係ないjavascript的な言語仕様的な解決ね・・・・てのはわかるんだけど、だからどうして衝突しづらいハッシュ値が得られるのかはさっぱりわからん。プログラマの癖にわからないと駄目だろ的なところから読み始めたんだけどまぁわからん。
sin関数で得られる64個の値は(視覚的に言うと「〜」←こんな値ね)(絶対値でつかってるからマイナスに振れたやつは正の値になってるけど)なんなの?とか。
メッセージダイジェストのバッファ初期値はなんでこういう並びなの?とか

01 23 45 67
89 ab cd ef
fe dc ba 98
76 54 32 10
※ソースではこういう風に使ってる。
        var state = [ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 ];


最近、日頃何となく使ってるアルゴリズムの仕組みを知りたくて色々と勉強してるんですけど、公開鍵の仕組みの方がわかりやすくて、この調子でメッセージダイジェストもわかるかなーと思ったんですけど、「このアルゴリズムはこうすると衝突しにくいダイジェストが得られるんです」がわからないです。ちっとも。ヤフー知恵袋にでも投稿してみようか。メッセージダイジェスト(笑)とかいわれるんだろうか(言いません)
var MD5 = {
    utf16to8 : function( str ){
        var retStr = "";
        var len = str.length;
        for( var idx = 0; idx < len; idx++ ){
            var chara = str.charCodeAt( idx );
            if( ( chara >= 0x0001 ) && ( chara <= 0x007F ) ){
                retStr += str.charAt( idx );
            }
            else if ( chara > 0x07FF ){
                retStr += String.fromCharCode( 0xE0 | ( ( chara >> 12 ) & 0x0F ) );
                retStr += String.fromCharCode( 0x80 | ( ( chara >>  6 ) & 0x3F ) );
                retStr += String.fromCharCode( 0x80 | ( ( chara >>  0 ) & 0x3F ) );
            }
            else {
                retStr += String.fromCharCode( 0xC0 | ( ( chara >> 6 ) & 0x1F ) );
                retStr += String.fromCharCode( 0x80 | ( ( chara >> 0 ) & 0x3F ) );
            }
        }
        return retStr;
    },

    sinTbl : [
        0x00000000, 0xd76aa478, 0xe8c7b756, 0x242070db,
        0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613,
        0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1,
        0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e,
        0x49b40821, 0xf61e2562, 0xc040b340, 0x265e5a51,
        0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681,
        0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87,
        0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9,
        0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122,
        0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60,
        0xbebfbc70, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085,
        0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8,
        0xc4ac5665, 0xf4292244, 0x432aff97, 0xab9423a7,
        0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d,
        0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314,
        0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb,
        0xeb86d391 
    ],

    tblIdx : [
        [ 
            function( x, y, z ){ return ( x & y ) | ( ~x & z ); },
            [
                [ 0, 7, 1],[ 1,12, 2],[ 2,17, 3],[ 3,22, 4],
                [ 4, 7, 5],[ 5,12, 6],[ 6,17, 7],[ 7,22, 8],
                [ 8, 7, 9],[ 9,12,10],[10,17,11],[11,22,12],
                [12, 7,13],[13,12,14],[14,17,15],[15,22,16]
            ]
        ],[
            function( x, y, z ){ return ( x & z ) | ( y & ~z ); },
            [
                [ 1,5,17],[ 6, 9,18],[11,14,19],[ 0,20,20],
                [ 5,5,21],[10, 9,22],[15,14,23],[ 4,20,24],
                [ 9,5,25],[14, 9,26],[ 3,14,27],[ 8,20,28],
                [13,5,29],[ 2, 9,30],[ 7,14,31],[12,20,32]
            ]
        ],[
            function( x, y, z ){ return x ^ y ^ z; },
            [
                [ 5,4,33],[ 8,11,34],[11,16,35],[14,23,36],
                [ 1,4,37],[ 4,11,38],[ 7,16,39],[10,23,40],
                [13,4,41],[ 0,11,42],[ 3,16,43],[ 6,23,44],
                [ 9,4,45],[12,11,46],[15,16,47],[ 2,23,48]
            ]
        ],[
            function( x, y, z ) { return y ^ (x | ~z); },
            [
                [ 0,6,49],[ 7,10,50],[14,15,51],[ 5,21,52],
                [12,6,53],[ 3,10,54],[10,15,55],[ 1,21,56],
                [ 8,6,57],[15,10,58],[ 6,15,59],[13,21,60],
                [ 4,6,61],[11,10,62],[ 2,15,63],[ 9,21,64]
            ]
        ]
    ],

    shift : function( code ){
        return String.fromCharCode( code & 0xff ) +
            String.fromCharCode( ( code >>> 8 ) & 0xff ) +
            String.fromCharCode( ( code >>> 16) & 0xff ) +
            String.fromCharCode( ( code >>> 24) & 0xff );
    },

    rollNum : function( num ){
        while( num < 0 ) num += 4294967296;
        while( num > 4294967295 ) num -= 4294967296;
        return num;
    },

    setRound : function( codeLst, state, func, rndRbn, pos ){

        var _0 = rndRbn[ 0 ];
        var _1 = rndRbn[ 1 ];
        var _2 = rndRbn[ 2 ];
        var _3 = rndRbn[ 3 ];

        var codePos    = pos[ 0 ];
        var shiftValue = pos[ 1 ];
        var curTblIdx  = pos[ 2 ];

        var result = state[ _0 ] + func( state[ _1 ], state[ _2 ], state[ _3 ] ) + codeLst[ codePos ] + MD5.sinTbl[ curTblIdx ];
        result = MD5.rollNum( result );
        result = ( ( result << shiftValue ) | ( result >>> ( 32 - shiftValue ) ) );
        result += state[ _1 ];
        state[ _0 ] = MD5.rollNum( result );
    },

    get128BitDigest : function( data ){

        var state = [ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 ];
        var len = data.length;
        var idx = len & 0x3f;
        var padLen = ( idx < 56 ) ?( 56 - idx ) :( 120 - idx );
        if( padLen > 0 ) {
            data += "\x80";
            for( idx = 0; idx < padLen - 1; idx++ )
                data += "\x00";
        }

        data += MD5.shift( len * 8 );
        data += MD5.shift( 0 );
        len  += padLen + 8;
        var rndRbn = [ 0, 1, 2, 3 ];
        var codeLst = new Array( 16 );
        var tmpStat = new Array( 4 );

        for( var rndCnt = 0; rndCnt < len; rndCnt += 64) {

            for( idx = 0, shiftIdx = rndCnt; idx < 16; idx++, shiftIdx += 4 ) {
                codeLst[ idx ] = data.charCodeAt( shiftIdx ) |
                ( data.charCodeAt( shiftIdx + 1 ) <<  8 ) |
                ( data.charCodeAt( shiftIdx + 2 ) << 16 ) |
                ( data.charCodeAt( shiftIdx + 3 ) << 24 );
            }

            for( idx = 0; idx < 4; idx++ )
                tmpStat[ idx ] = state[ idx ];

            for( idx = 0; idx < 4; idx++ ){
                var func  = MD5.tblIdx[ idx ][ 0 ];
                var block = MD5.tblIdx[ idx ][ 1 ];

                for( shiftIdx = 0; shiftIdx < 16; shiftIdx++ ) {
                    MD5.setRound( codeLst, tmpStat, func, rndRbn, block[ shiftIdx ]);
                    var tmp = rndRbn[ 0 ];
                    rndRbn[ 0 ] = rndRbn[ 3 ];
                    rndRbn[ 3 ] = rndRbn[ 2 ];
                    rndRbn[ 2 ] = rndRbn[ 1 ];
                    rndRbn[ 1 ] = tmp;
                }
            }

            for( idx = 0; idx < 4; idx++ ){
                state[ idx ] += tmpStat[ idx ];
                state[ idx ] = MD5.rollNum( state[ idx ] );
            }
        }
        return MD5.shift( state[ 0 ] ) +
            MD5.shift( state[ 1 ] ) +
            MD5.shift( state[ 2 ] ) +
            MD5.shift( state[ 3 ] );
    },

    getDigest : function( data ) {
        var str = "";
        var bit128 = MD5.get128BitDigest( MD5.utf16to8( data ) );
        for( var idx = 0; idx < 16; idx++ ){
            var chara = bit128.charCodeAt( idx );
            str += "0123456789abcdef".charAt( ( chara >> 4 ) & 0xf );
            str += "0123456789abcdef".charAt( chara & 0xf );
        }
        return str;
    }
}
(function(){
    alert( MD5.getDigest( "test" ) );
    //098f6bcd4621d373cade4e832627b4f6
})();

[ 最近のエントリーとその関連エントリー ]


2008年11月10日

やる夫4コマのテンプレが5つできた。

やる夫4コマのテンプレが5つできた。をはてなブックマークに追加 やる夫4コマのテンプレが5つできた。をdel.icio.usに追加  Yahoo!ブックマークに登録 やる夫4コマのテンプレが5つできた。をGoogle Bookmarksに追加 やる夫4コマのテンプレが5つできた。をtwitterにポスト
template0.png template1.png template2.png template3.png template4.png

こんなかんじでテンプレートが5つ出来た。何が表示されるのかはランダムに決まります。適当に雑誌ポイ色の質感を出そうとしたら結構ばらけたwこのまま淡々とやる夫を作り続けるんだと思う。
http://mojalog.com/mojascript/img.php?u=higemoja
<a href="http://twitter.com/higemoja"> <img src="http://mojalog.com/mojascript/img.php?u=higemoja" alt="twittermagazine" /></a>
twitterのアカウントを渡すだけです。イメージタグでブログなんかに貼れます。

[ 最近のエントリーとその関連エントリー ]


2008年11月05日

twitterのつぶやきを拾って4コマ漫画にしたよ

twitterのつぶやきを拾って4コマ漫画にしたよをはてなブックマークに追加 twitterのつぶやきを拾って4コマ漫画にしたよをdel.icio.usに追加  Yahoo!ブックマークに登録 twitterのつぶやきを拾って4コマ漫画にしたよをGoogle Bookmarksに追加 twitterのつぶやきを拾って4コマ漫画にしたよをtwitterにポスト
twitterのつぶやきを拾って4コマ漫画にしたよ。

http://mojalog.com/mojascript/img.php?u=higemoja

こんな感じでtwitterのユーザをパラメータに与えると、タイムラインを4つさかのぼって4コマになるよ!あとやりたい事は、このやる夫のマンガテンプレを任意のものにするのとテンプレを増やす事です。

twitterにいきなり「光の速さでうんこがヤバい」やつを4連投したけどこのネタだから気にしないでほしいです。

[ 最近のエントリーとその関連エントリー ]


2008年11月04日

ブクマのサジェストつくってみた(重い。。。)

ブクマのサジェストつくってみた(重い。。。)をはてなブックマークに追加 ブクマのサジェストつくってみた(重い。。。)をdel.icio.usに追加  Yahoo!ブックマークに登録 ブクマのサジェストつくってみた(重い。。。)をGoogle Bookmarksに追加 ブクマのサジェストつくってみた(重い。。。)をtwitterにポスト
というわけで、作ってみました。
私はpost2sbmでdeliciousとtwitterとはてなに対していっぺんにブックマークをポストしているのですが、今見てるページはどんなタグでブックマークされているのかなー?とかいう機能をつけてみたい!というとこから作ってみました(クライアント側は作ってないです)。
タグの集計までは結構さくさくいくのですが、欲が出てその先のそのタグを付けた人は、他に同じタグでどんなページをブクマしているのか?ってのも欲しくなって、これを実装したらアホみたいに重くなりました。
PHPで実装しているのですが、ちょっといろいろダメだろこれ的なところが沢山ありそうです。XMLパーサはサーバがPHP4だからそういう作りになっちゃいました。PHP5になればsimpleXMLとかが使えるらしいのですがよくわからん。
クライアントのグリモンとかubiquityコマンドはまだ手つかずなのですが、もしかしたら全部クライアントでやった方が体感早いのかもしれません。そうなったらそうなったでそうする。

gigazineのページを渡すとこんな感じで返してくる。ブックマークレットにすると↓な感じ。
javascript:void(location.href="http://mojalog.com/mojascript/hatena.php?p="+encodeURI(location.href))
とりあえずやってみたかったのは、
・ブクマしようとしているページをはてブのRSSからひろう。
・で、タグを集計する
・タグの嵩みが多い順にソートする
・そのタグを付けたユーザのブクマRSSを拾う。
・このページをブックマークしているユーザはこんなタグで他のこんなページもブックマークしてますよ的な表示をさせてあわよくば*あとで読むタグを付けながら一緒にブクマできるようなインターフェイスを設ける
てことをやりたい。恥ずかしながらソースを載せてみる(股間を隠しry)。ここは普通こうすんだろJK的な事があったら教えてほしいです><(←><ってやると優しく教えてくれるらしいよってvipに載ってた)(うそ)
<?php
    $targetUrl = $_GET[ "p" ];
    mb_internal_encoding('UTF-8');
    mb_http_output('UTF-8');
    mb_detect_order('ASCII,JIS,UTF-8,EUC-JP,SJIS');

    class xml {

        var $parser;
        var $refTag;
        var $suggestUser;
        var $curData;
        
        var $keyList;
        var $suggestList;
        var $urlList;

        function xml(){
            $this->keyList = array();
            $this->suggestList = array();
            $this->urlList = array();

            $this->suggestUser = "";
            $this->curData = "";
            
            $this->parser = xml_parser_create( 'UTF-8' );
            xml_set_object( $this->parser, $this );
            xml_set_element_handler( $this->parser, "TagOpen", "TagClose" );
            xml_set_character_data_handler( $this->parser, "CData" );
        }
        
        function parse( $data ){
            xml_parse( $this->parser, $data );
        }

        function TagOpen( $parser, $tag, $attributes ){
            $this->refTag = $tag;
        }

        function CData( $parser, $cdata ){
            if( strcmp( $this->refTag, "TITLE" ) == 0 ){
                $this->suggestUser = trim( $cdata );
            }

            if( strcmp( $this->refTag, "DC:SUBJECT" ) == 0 || strcmp( $this->refTag, "LINK" ) == 0 ){
                $this->curData .=  $cdata;
            }
        }

        function TagClose( $parser, $tag ){

            if( strcmp( $tag, "DC:SUBJECT" ) == 0 ){
                $this->keyList[ $this->curData ] = ( isset( $this->keyList[ $this->curData ] ) )
                    ? $this->keyList[ $this->curData ] + 1
                    : 1;
                $this->suggestList[ $this->curData ] = ( isset( $this->suggestList[ $this->curData ] ) )
                    ? $this->suggestList[ $this->curData ] . ',' . $this->suggestUser
                    : $this->suggestUser;
            }

            if( strcmp( $tag, "LINK" ) == 0 ){
                $this->urlList[ $this->curData ] = $this->suggestUser;
            }

            if( strcmp( $tag, "DC:SUBJECT" ) == 0 || strcmp( $tag, "LINK" ) == 0 || strcmp( $tag, "TITLE" ) == 0 ){
                $this->curData = "";
            }
            $this->refTag = "";

        }

        function getSuggestList(){
            return $this->suggestList;
        }

        function getKeyList(){
            return $this->keyList;
        }

        function getUrlList(){
            $ary = $this->urlList;
            $this->urlList = array();
            return $ary; 
        }
    }

    $suggestList = array();
    $keyList = array();
    require_once( 'HTTP/Request.php' );
    $req =& new HTTP_Request( "http://b.hatena.ne.jp/entry/rss/" . $targetUrl );
    $req->setMethod( HTTP_REQUEST_METHOD_GET );
    if ( !PEAR::isError( $req->sendRequest() ) ) {
        $res = $req->getResponseBody();
        $xml_parser = new xml();
        $xml_parser->parse( $res );
        $suggestList = $xml_parser->getSuggestList();
        $keyList = $xml_parser->getKeyList();
        unset( $xml_parser );
    }
    $req->clearPostData();

    arsort( $keyList );

    header('Content-Type: text/xml');
    $xml =<<< EOD
<?xml version="1.0" encoding="UTF-8" ?>
<itemlist>
EOD;
    echo $xml . "\n";

    $loopCount = 0;
    while( list( $key, $val ) = each( $keyList ) ) {

        echo "<elem>\n";
        echo "<tagname>" . htmlspecialchars( $key ) . "</tagname>\n";

        $usersList = split( ",", $suggestList[ $key ] );
        $userBkm =& new HTTP_Request( "http://b.hatena.ne.jp/" . $usersList[ rand( 1, count( $usersList ) -1 ) ] . "/rss?tag=" . urlencode( $key ) );
        $userBkm->setMethod( HTTP_REQUEST_METHOD_GET );
        if ( !PEAR::isError( $userBkm->sendRequest() ) ) {
            $res = $userBkm->getResponseBody();
            $xml_parser = new xml();
            $xml_parser->parse( $res );
            $tempList = $xml_parser->getUrlList();
            $nLoopCount = 0;
            while( list( $nkey, $nval ) = each( $tempList ) ) {
                $nLoopCount++;
                if( $nLoopCount < 2 ){
                    continue;
                }
                echo "<suggest>\n";
                echo "<title>" . htmlspecialchars( $nval ) . "</title>\n";
                echo "<link>" . htmlspecialchars( $nkey ) . "</link>\n";
                echo "</suggest>\n";
            }
            unset( $xml_parser );
        }
        $userBkm->clearPostData();

        echo "</elem>\n";
        $loopCount++;
        if( $loopCount >= 3 ) break;
    }
    echo "</itemlist>";
?>