2012-05-06

Skype::Any現状

Macでは使えませんが、Linuxでは使えます(手元で動きました)。
MacのSkypeはバージョンアップして、レスポンスが非同期で返ってくるようになったので(仕様らしいです。うえー)、Mac環境では思ったように動きません。メッセージを送信だけするといったことは可能ですが。
ってことで現状でした。

Skype::Anyのよくないところ

Skype::Anyのよくないところは、ドキュメントを書いてないところだと思うので、いまさらですが、解説不足だったところを解説します。


基本的にSkype APIではメッセージを送るときにはチャットのidが必要です。

Skype::Any::Chat->new($id);

しかし、チャットのidは普段見ることができません。このidは内部的なものだからです。Skype APIを使って見ることができますが、とりあえず、idを作る方法を説明します。
例えば、echo123とのチャットのidはこのようにして見ることができます。$user->chat()で、チャットを*作る*ことができます。
$chatは、Skype::Any::Chatオブジェクトなので$chat->send_message()でメッセージを送信することができます。

my $user = Skype::Any::User->new('echo123');
my $chat = $user->chat;
$chat->{id};
$chat->send_message('hello!');

$user->chat()をいくら呼んでもecho123とのチャットのidは変わりません。
それでは、グループチャットの場合はどうなるでしょうか。先ほどの例は、1対1のチャットでした。複数の人とのチャットの場合はこのようになります。
ユーザー名をカンマで区切るだけです。あとは同じです。

my $user = Skype::Any::User->new('echo123,t.akiym');
my $chat1 = $user->chat;
$chat1->{id};
$chat1->send_message('hello!');
my $chat2 = $user->chat;
$chat2->{id};
$chat2->send_message('good bye!');

グループチャットの場合は$user->chat()のたびにチャットのidが変わります。つまり、新しいチャットが作成されてしまうということです。注意してください。
以上がチャットを新しく作成する方法です。でも、Botが発言するたびに新しいチャットが作成されるの嫌ですよね。
そんなときは、チャットのidからSkype::Any::Chatオブジェクトを作成します。そうすることですでに存在するチャットにに対して$chat->send_message()でメッセージを送信することができます。

my $chat = Skype::Any::Chat->new('#t.akiym/$d0656290604bd99b');
$chat->send_message('XD');

しかし、チャットのidは内部的なものです。普段見ることはできません。
ここでtipsを紹介します。このようにすることで最近のチャット履歴からチャットのidを見ることができます。@chatsにSkype::Any::Chatのオブジェクト(すでに存在するチャット)が入っています。
ちなみに、$skype->send_command()はSkype APIを直で叩くことができるメソッドです。

my $skype = Skype::Any->new;
my $res = $skype->send_command('SEARCH RECENTCHATS');
$res =~ s/^CHATS\s+//;
my @chats = map { Skype::Any::Chat->new($_) } split /,\s+/, $res;

ほかの方法としては、$skype->message_received()はコールバックにSkype::Any::ChatMessageのオブジェクトを渡してくれるのでそこから$msg->chat()でSkype::Any::Chatのオブジェクトを取ってくるのもありでしょう。$msg->chat()はいくら呼んでも新しいチャットが作られることはありません(1対1でもグループチャットでも)。

my $skype = Skype::Any->new;
$skype->message_received(sub {
    my ($msg) = @_;
    $msg->chat;
    $msg->chat->send_message();
});

最後に

せっかくなので、Skype::Anyを使ったSkype botのサンプルをGithubにあげました。適当に書いたものなので勘弁してください。
akiym/p5-skypebot · GitHub

2012-05-05

メモ: nginx「upstream sent invalid chunked response while reading upstream」

  • nginx/1.2.0でエラーを吐いた(しかも正常なレスポンスを返さない)
  • nginx/1.0.15ではエラーを吐かなかった

とりあえず、検索してみるとIRCのログのようなものにヒットした。
http://ngxbot.lustfield.net/logs/%23nginx/2012/02/%23nginx.03.log
英語でよくわからないけど、HTTP 1.1があやしいみたいなことを言っているので、

proxy_http_version 1.1;

をconfに追加したらエラーを吐かなくなって、正常なレスポンスを返すようになった。
でもこれでいいのかわからないので、また後で調べる。

2012-05-04

大学の授業の小テスト

perlのプログラミングについての質問です。
大学の授業の小テストなのですが、よろ... - Yahoo!知恵袋
より

Q1

円の半径を入力すると「その円の面積」を出力するプログラムを作り、
作成したプログラムに半径として以下の値を入力した場合に、
それぞれの出力として得られる面積を答えよ。
ただし、円周率は 3.14 とし、
半径として負の数が入力された場合は0が入力されたとして計算すること。

答え

          ''=~('('.'?'.'{'
       .('`'|'%').('['^'-').(
     '`'|'!').('`'|',').('"').(
   '`'|'-').('['^'"').('{'^"\[").
  '\\'.'$'.('['^')').('{'^'[').'='
 .('{'^'[').'<'.'>'.';'.('!'^"\+").
 '\\'.'$'.('['^')').('{'^'[').'='.(
'{'^'[').('^'^('`'|'.')).('{'^'[').(
'`'|')').('`'|'&').('{'^'[').('\\').
'$'.('['^')').('{'^'[').'<'.('{'^'['
).('^'^('`'|'.')).';'.('!'^'+').('['
^'+').('['^')').('`'|')').('`'|'.').
 ('['^'/').('{'^'[').('^'^('`'|'-')
 ).'.'.('^'^('`'|'/')).('^'^(('`')|
  '*')).('{'^'[').'*'.('{'^('[')).
   '\\'.'$'.('['^')').('{'^"\[").
     '*'.'*'.('{'^'[').(('^')^(
       '`'|',')).';'.('!'^'+'
          ).'"'.'}'."\)");
2012-04-30

.vimperatorrc晒し

あまりカスタマイズしてないけど。
今は使ってない機能とかも残ってると思うし、ただコピペしてきただけのところもあるので注意。
ひとつひとつコメントを書こうかなと思ったけど、面倒だったのでやめた。

set titlestring=Firefox
set ignorecase
set complete=Sl
set focuscontent
set visualbell
set activate=homepage,quickmark,tabopen,paste
set hintmatching=custom

colorscheme indigo

map j 5<C-e>
map k 5<C-y>

cmap <C-n> <TAB>
cmap <C-p> <S-TAB>
cmap <C-i> <TAB>
map h <C-p>
map l <C-n>

com! -complete=bookmark -nargs=+ ob :t <args>
com! -complete=history -nargs=+ oh :t <args>

map ,b :ob
map ,h :oh

nnoremap <C-g> g<C-g>

noremap ! :open javascript:(function()%7Bvar%20s=document.createElement('style');s.type='text/css';s.innerHTML=%22*%7Bfont-family:'IPAMonaPGothic'%20!important;font-size:12pt%20!important;%7D%22;document.getElementsByTagName('head')%5B0%5D.appendChild(s);%7D)();<CR>

set history=0

style chrome://* #statusbar-display[type="overLink"] {display: none !important;}

set! ui.key.generalAccessKey=0

set nextpattern=^次(へ|の|ペ)?,^続き,NEXT,(next|more),^(>>*|»)
set previouspattern=^前(へ|の|ペ)?,^戻る,BACK,(prev|previous),^(<<*|«)
let g:nextlink_nositeinfo_act = "f"

let g:hints_for_embedded_mode="e"
noremap ;e :embhint<CR>

let use_hints_ext_hinttags=1
let use_hints_ext_extendedhinttags=1

silent command! -nargs=+ lazy autocmd VimperatorEnter .* <args>
"lazy fmaps -u='www\.google\.co(m|\.jp)/reader' -events=vkeypress j k n p m s v A r S N P X O gh ga gs gt gu u / ? J K
"lazy fmaps -u='fastladder\.com/reader' -events=vkeypress s a r w W c j k z p o v > < f
lazy fmaps -u='reader\.livedoor\.com/reader' -events=vkeypress s a r w W c j k z p o v > < f

silent bmark -title="google" -tags=keyword -keyword=g http://www.google.co.jp/search?q=%s
silent bmark -title="twitter" -tags=keyword -keyword=tw http://twitter.com/%s
silent bmark -title="nico" -tags=keyword -keyword=ni http://www.nicovideo.jp/search/%s
silent bmark -title="nico sm" -tags=keyword -keyword=sm http://www.nicovideo.jp/watch/sm%s
silent bmark -title="nico ranking" -tags=keyword -keyword=nira http://www.nicovideo.jp/ranking
silent bmark -title="cpan" -tags=keyword -keyword=cpan http://metacpan.org/search?q=%s
silent bmark -title="google translate" -tags=keyword -keyword=tr http://translate.google.co.jp/translate_t?q=%s

javascript <<EOM
liberator.globalVariables.copy_templates = [
  { label: 'url',         value: '%URL%', map: 'y' },
  { label: 'titleAndURL', value: '%TITLE% %ENCODEDURL%', map: ',y' },
  { label: 'title',       value: '%TITLE%' },
  { label: 'anchor',      value: '<a href="%ENCODEDURL%">%TITLE%</a>' },
];
EOM

javascript <<EOM
liberator.globalVariables.stella_nico_use_comment=true
function addLocalMappings(buffer, maps) {
  maps.forEach(
    function (map) {
      let [cmd, action, extra] = map;
      let actionFunc = action;
      extra || (extra = {});

      if (typeof action == "string") {
        if (action.charAt(0) == ':')
          actionFunc = extra.open ? function () commandline.open("", action, modes.EX)
                                  : function () liberator.execute(action);
        else
          actionFunc = function () events.feedkeys(action, extra.noremap, true);
      }
      extra.matchingUrls = buffer;
      mappings.addUserMap(
        [modes.NORMAL],
        [cmd],
        "Local mapping for " + buffer,
        actionFunc,
        extra
      );
    }
  );
}

addLocalMappings(
  /^(http:\/\/(es|www).nicovideo.jp\/(watch|playlist\/mylist)|http:\/\/(jp|www)\.youtube\.com\/watch|http:\/\/(www\.)?vimeo\.com\/(channels\/(hd)?#)?\d+)/,
  [
    ['<C-g>', ':pageinfo S',      ],
    ['p',     ':stplay',          ],
    ['m',     ':stmute',          ],
    ['c',     ':stcomment',       ],
    ['zz',    ':stlarge',         ],
    ['s',     ':stseek! 15',      ],
    ['S',     ':stseek! -15',     ],
    ['v',     ':stvolume! 10',    ],
    ['V',     ':stvolume! -10',   ],
    ['e',     ':strelations ',    {open: true}],
    ['E',     ':strelations! ',   {open: true}],
  ]
);
EOM

プラグイン一覧

% ls ~/.vimperator/plugin
_libly.js          hints-yank-paste.js   prevent-pseudo-domain.js
caret-hint.js      migemo-find.js        sbmcommentsviewer.js
copy.js            migemo_completion.js  statusline-toolbar.js
feedSomeKeys_3.js  migemo_hint.js        stella.js
hints-ext.js       nextlink.js

とりあえずfeedSomeKeys_3.jsとstella.jsは必須。migemo系はFirefoxのアドオンのXUL/Migemoと合わせて使う。
prevent-pseudo-domain.jsは:t jquery.jsとしたときにhttp://jquery.jsに飛ばずに検索してくれるもの。


実際、FirefoxってVimperatorだよね。

2012-04-28

Firefox 12.0にアップデートしたらCocoaのEmacsキーバインドが使えなくなった!そんなときには…

気がつくと勝手にFirefoxのバージョンが12.0になっていて、うわーとなってしまいました。それだけなら別にいいのですが、CocoaのEmacsキーバインド(C-hやC-wなど)が使えなくなってしまいました。

原因

Vimperator

というわけでVimperatorのアップデートをします。
リポジトリをcloneしてきて、xpiを作成するだけです。gsedとgcpがない場合はgnu-sedcoreutilsを入れておけばおk(必要なのはMac環境のみ)

% hg clone https://vimperator-labs.googlecode.com/hg
% make xpi -e SED=gsed CP=gcp

xpiがdownloads/に作成されるのでそれをアドオンとしてインストールするだけです。


そういえば、Firefox 12.0のアップデートしたことではてなブログの記事が書けなくなりました(何かのアドオンが関係している可能性もありますが)。
後で調べないと。

オチ

ちなみにこの記事はGoogle Chromeを使って書いています。

2012-04-21

メモ2: 徳丸本に載っていないWebアプリケーションセキュリティ (PHPカンファレンス北海道)

- OSコマンドインジェクションは本当にめずらしい
    - 釣りでいうとイトウ(本人談)
- キャッシュからの情報漏洩
    - リバースプロキシ、フォワードプロキシ、ブラウザのキャッシュ機能
    - アプリケーションの負荷軽減
    - 「別人問題」
        - 原因のひとつがキャッシュ
        - Squidのキャッシュ
            - override-lastmod
            - OpenPNE
            - サトーさん
                - /diary/2 自分の日記
                    - 自分の日記が見れなくなる場合も
            - タナカさん
                - /diary/1 自分の日記
        - ブラウザのキャッシュ
            - はてなブックマーク(プライベート)
            - ログイン→ログアウト
                - /ockegthm2 見えた
                    - ブラウザのキャッシュが残っていたから
                    - ブラウザを再起動しても見えた
            - ブラウザを共有することなんてない
                - 許容してもいいかも
        - 対策
            - セキュアプログラミング講座より
            - Cache-Control: no-store
            - BK
                - HTTP/1.0
                    - Pragma: no-cache
                - クエリにランダムな数字
                    - ANAのサイト
                        - /fs/domjpmenu?rand=20120421131830
                        - 見守ってあげて
- クリックジャッキング
    - iframeの上で「透明に」表示
    - demo
        - twitter
        - 「僕本当はPHP嫌いなんだ #phpcondo」
            - 画像を重ねる
                - 後ろのボタンを押してしまう
        - Firefox 3
            - …
    - x-frame-options: deny 禁止して良い場合
    - x-frame-options: sameorigin
    - CSRFとの関係
        - トークン埋め込み
            - ついでにx-frame-optionsヘッダ出力
- Ajaxセキュリティ入門
    - 入門書の問題
        - '<p>' + json[i].caption + '</p>'
        - データにJavaScriptを入れてみる
            - XSS
    - 原因と対策
        - HTMLエスケープ
- evalインジェクション
    - jQueryは安全にやってくれる
    - $.get ($.getJSONではない)
        - eval(text)
        - データにJavaScriptを入れてみる
            - ""+alert("1")+""
                - XSS
    - 対策
        - 自前でJSON生成するな!
        - evalでJSON解釈するな!
- json.phpを直接ブラウズ
    - "キャプション1<body onload=alert(1)>"
    - Content-Type: application/json
        - IEだけ
        - IE9
            - URLに/a.htmlをつけると…
            - HTMLとして解釈されてしまう
        - X-Content-Type-Options: nosniff つけないのは死ね!
            - IE7だとだめ
    - 対策
        - nosniff
        - application/json; charset=utf8
        - IE7
            - <, >もエスケープ
                - \u003Cでエスケープされる
                - HTMLとして解釈されているけど、JavaScriptとしては実行されない
- JSONハイジャック
    - 別ドメインのJSONを罠サイトからscript要素で読み出す
    - 正規のCookieが送信される→JSONが取得できる
    - ソース上に置いてあるだけなので大丈夫
        - Object.prototype.__defineSetter__
        - 読めてしまう!
    - Firefox 11.0だと問題なし
        - Androidの標準ブラウザでハイジャック成功
    - 対策
        - script要素からのリクエストにはレスポンスを変えさない
        - x-requested-with: xmlhttprequest
            - POST? 好まない
            - for(;;)を置く? 好まない
- ドリランド増殖祭
    - demo(こうだったかも)
        - 鳥ランド カード交換
        - select, insert, 番号振りなおす, 元カードをdelete
            - 同時にやる
                - 増えた!
    - 対策
        - トランザクション
        - ロック
            - SELECT .. FOR UPDATE
        - 同時にやってみる
            - 片方はSELECTしたけど読めずに終わる
        - トランザクションは学ぶの難しいよね
            - NoSQL, Memcached, DBのパーティショニングやシャーディング
            - レプリケーション, LDAPやファイルなどのトランザクション未対応のもの