Hatena::Groupperl

local $PERL_MEMO;

March 07, 2010

[][]\(hoge) -> ?

print \(a..z);
# SCALAR(0x182fe2c)SCALAR(0x182fe38)...SCALAR(0x182ff4c)SCALAR(0x182ff58)

なにこのミラクル構文。リスト(配列じゃなくてリスト構文)のリファレンス取ろうとすると中身のリファレンスのリスト返すのか。すげー

追記

@a = 0..9; @b = A..Z; @c = a..z;

print \(@a);
# SCALAR(0x182fd8c)SCALAR(0x182fd98)...SCALAR(0x182fec4)SCALAR(0x182fed0)

print \(@a,@b,@c);
# ARRAY(0x182f984)ARRAY(0x182fb04)ARRAY(0x182fde0)

リストの中身が複数に分かれると、それぞれのリファレンスを返すみたい。

ちなみに、複数の配列のすべての中身のリファレンスが欲しい時は

print \(@_=(@a,@b,@c));
# SCALAR(0x2861ac)SCALAR(0x286284)...(many)...SCALAR(0x1830368)SCALAR(0x1830374)

のように、一つの配列に代入してやるといいみたい。いいシュガー発見した気がする。

追記2

print \(@{[@a,@b,@c]});

こっちのほうがスマートですね。

[][][]配列をshuffle(ランダムに並べ替えたい)/take potluck(ランダムに抜き出したい) - 爆速編

前回の更新ではベンチ取らないでやってたので今回は高速化に挑戦。

まずはベンチマーク

使ったコードはこちら。

#!perl
use Benchmark qw(timethese cmpthese);
use List::Util;
my @a = 'Aa'..'Zz'; # 0 .. 675

cmpthese(timethese(10000, {
  'L::U::shuffle' => sub { List::Util::shuffle(@a) },
  shuffle_simple  => sub { shuffle_simple(@a) },
  shuffle         => sub { shuffle(@a) },
  L_U_shuffle     => sub { L_U_shuffle(@a) },
}));


sub shuffle_simple { return sort { int(rand 3) -1 } @_ }

sub shuffle {
  my @old = @_; local $_;
  my ($i, $new) = ($#old+1, 0);
  map {
    $_ = $old[$new = rand $i--];
    $old[$new] = $old[$i];
    $_;
  } 0 .. $#old
}

sub L_U_shuffle {
  my @old = \(@_);
  my $n; my $i = @_;
  map {
    (${$old[$n = rand $i--]}, $old[$n] = $old[$i])[0];
  } @_
}

L_U_shuffleはList::Util::shuffleのpure perl版です。

で、結果が以下。

                   Rate shuffle L_U_shuffle L::U::shuffle shuffle_simple
shuffle           215/s      --        -73%          -97%          -100%
L_U_shuffle       794/s    270%          --          -90%           -99%
L::U::shuffle    7622/s   3453%        859%            --           -94%
shuffle_simple 125000/s  58171%      15635%         1540%             --

…(shuffle_simpleはともかく)勝負にならんな!あとXSのshuffle速すぎ。

なんでこんなに差がつくかというと、L_U_shuffleは実体をコピーするのではなくさっきの記事の方法を使ってリファレンスのリストを作ってそいつを回しているのが原因だと思う。余計な代入も一切発生しない。あと僕の作ったshuffleはmap回すのに0..$#oldみたいないらん配列作ってるしさらに遅い。で、3倍近く差がつく。この点を改良して最速shuffle/take potluckを作ります。

並べ替え

sub shuffle_fast(@) {
  my @old = \(@_);
  my $n; my $i = @_;
  map {
    (${$old[$n = rand $i--]}, $old[$n] = $old[$i])[0];
  } @_;
}

ええパクリです。でも僕の環境だとpure perlのList::Util::shuffleの倍は出ます。何故か。mapの中を1行にしただけなのに。

参考ベンチ(試行回数1000)
              Rate      shuffle  L_U_shuffle shuffle_fast
shuffle      216/s           --         -46%         -72%
L_U_shuffle  396/s          84%           --         -49%
shuffle_fast 774/s         259%          95%           --

適当に抜き出す

sub potluck_fast($;$) {
  my $i = my @a = \(@{+shift});
  my $n = shift || int rand $i;
     $n = $i if $n > $i;
  map {
    (${$a[$n = rand $i--]}, $a[$n] = $a[$i])[0];
  } 0 .. $n-1;
}
warn potluck_fast([0..9,A..Z,a..z],20);
# XK7kgQq6Dn1RLVa8ozOW

ぱくぱく。使い方は前回同様、第1引数に配列のリファレンスを、第2引数に抜き出したい数を渡します。

参考ベンチ(試行回数1000)
              Rate      potluck potluck_fast
potluck      248/s           --         -73%
potluck_fast 925/s         273%           --

おしまい

爆速って程でもなかったかな。しかし既存のshuffleよりはずっと速くなったはず。そのへんのよりは3倍速い。

List::Util使えるんだったらshuffleはList::Util使いましょう。爆速です。potluckみたいなことしたいときも

(List::Util::shuffle('Aa'..'Zz'))[0..rand(676)]

とかすれば爆速間違いなし。XSにはどう頑張っても勝てんわ。

cf.

MarcusMarcus2013/02/02 03:24Wonderful explanation of facts avaliable here.

aljpnasaljpnas2013/02/02 19:315v9ahV <a href="http://cpisumrqicws.com/">cpisumrqicws</a>

einmvsyipeinmvsyip2013/02/04 12:44KzH6ZP <a href="http://rkhlctayydot.com/">rkhlctayydot</a>

March 05, 2010

[][]Encode::Entity::NCR v0.0.1 Release!

  • XML::RSSが日本語を数値実体参照で返しやがるのに適当なデコーダがHTML::Entitiesくらいしか見つからない
  • Encode.pmはエンコードできるけどデコードの仕方が分からない
  • 毎回replaceかくのだるいし出来ればEncode.pmでなんとかしてほしい

ので作った!

ダウンロード

Download Sourceってところから落とせます。

URL変わりました。

使い方

use Encode;
use Encode::Entity::NCR;
$ncr  = encode("Entity-NCR", $utf8);
$utf8 = decode("Entity-NCR", $ncr);

あとはpod見て。

Encode.pmだけでやる

use Encode qw(encode decode :fallbacks);
$dec_ncr = encode('ascii', $str, FB_HTMLCREF); # 10進数
$hex_ncr = encode('ascii', $str, FB_XMLCREF);  # 16進数
$dec_ncr =~ s/&#(\d+);/chr $1/eg;
$hex_ncr =~ s/&#x([\da-f]+);/chr hex $1/eig;
$ncr =~ s/&#(x)?([\da-f]+);/chr($1?hex $2:$2)/eig; # 両方いっぺんに

デコードがわかんないのでこれを毎回書くわけですけど、めんどい!エンコードのほうも :fallbacks とか覚えられない!

おしまい

何気にmakeするモジュール初めて作ったので楽しかった。一回うっかりして module-starter で上書きしちゃったのもいい経験。いろいろ気付いたことがあったので今度はモジュールの作り方を記事にしよう。

FrenchieFrenchie2011/06/05 15:59Walking in the presence of giants here. Cool thinking all arunod!

xfimugfxhxfimugfxh2011/06/05 18:14ZQWGoL <a href="http://wcvmdvwbmwfs.com/">wcvmdvwbmwfs</a>

DollDoll2011/06/05 21:09Good to see a tanlet at work. I can’t match that.

bhgexmbhgexm2011/06/06 23:23RcdD4s , [url=http://vrwahvyypoaq.com/]vrwahvyypoaq[/url], [link=http://weomrireqfxh.com/]weomrireqfxh[/link], http://qistkodzangp.com/

tlmchwtlmchw2011/06/07 18:359cvKCK <a href="http://ympguridusyx.com/">ympguridusyx</a>

rmctzrcrmctzrc2011/06/09 19:082WmlOV , [url=http://oteehvbukvqk.com/]oteehvbukvqk[/url], [link=http://inijznmksduz.com/]inijznmksduz[/link], http://yxxtutwvudaw.com/

MadhukarMadhukar2012/11/01 22:38Me and this article, sititng in a tree, L-E-A-R-N-I-N-G!

wkdhcgsgnwkdhcgsgn2012/11/02 10:326Xf0HG <a href="http://fxjiofvcfuhu.com/">fxjiofvcfuhu</a>

hkyalkobyhkyalkoby2012/11/02 15:03Z6VnZF , [url=http://beupvryzbvcl.com/]beupvryzbvcl[/url], [link=http://zcbiwcewmxul.com/]zcbiwcewmxul[/link], http://hqtwliwehdgm.com/

czmqhjkwnavczmqhjkwnav2012/11/04 23:427z7Obi <a href="http://drhmxswddnsd.com/">drhmxswddnsd</a>

btwkgbwmsyybtwkgbwmsyy2012/11/05 12:58b05OhP , [url=http://czszfxeuziaa.com/]czszfxeuziaa[/url], [link=http://ssnthjwfowdj.com/]ssnthjwfowdj[/link], http://ekablygensfg.com/

March 04, 2010

[][][]配列をshuffle(ランダムに並べ替えたい)/take potluck(ランダムに抜き出したい)

たまーに配列を適当に並べ替えたり、そこからいくつか抜き出したいってことがあります。そんなときのためのTIP。

並べ替え

お手軽に
sub shuffle {
  return sort { int(rand 3) - 1 } @_
}
print shuffle(0 .. 9);
# 0123456789 => 6517840923

非常に簡単です。ただ元の配列の並びの影響を受けやすいので、内容が1020個程度の配列なら気にならないですが、それ以上になるとあまり役に立ちません。

きちんと
sub shuffle {
  my @old = @_; local $_;
  my ($i, $new) = ($#old+1, 0);
  map {
    $_ = $old[$new = rand $i--];
    $old[$new] = $old[$i];
    $_;
  } 0 .. $#old
}
print shuffle(0..9,A..Z,a..z);
# before: 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
# after : qBwNj3uiMgtLG9TKs6Ry7fpmZvVUSDQOdEeaJWoX8nlr5Cc0h2xbH4FIAPkYz1

ややこしいですがどんだけ大きな配列を入れようがランダムです。

適当に抜き出す

お手軽に
sub shuffle {
  return sort { int(rand 3) - 1 } @_
}
print ((shuffle(0..9,A..Z,a..z))[0..9]);
# iOKq7r1GL8

適当に並べ替えた奴の先頭から10個取ってるだけですね。簡単簡単。でも低ランダム。(元の配列の頭のほうばっかり取ってきます)

元の配列が抜き出したい数だけあるか分からないとき(上の例なら10個あるか分からないとき)は undef 抜くために

print grep { defined } ((shuffle(0..rand 9))[0..9]);

とかしましょう。元がundef入りの配列だと厄介だが。

かっつり
sub potluck {
  my @old = @{+shift}; local $_;
  my ($i, $new) = ($#old+1, 0);
  my $count = shift || int rand $i;
     $count = $i if $count > $i;
  map {
    $_ = $old[$new = rand $i--];
    $old[$new] = $old[$i];
    $_;
  } 0 .. $count-1
}
print potluck([0..9,A..Z,a..z]);
# hx9Py6m83ERG5JfarLqMeBwQozuZCYUv4i02KbntTDdpjs7NHgXO1WAI
print potluck([0..9,A..Z,a..z],10);
# o5fjvETbBJ

さっきのsub shuffleをちょっといじっただけです。配列のリファレンスを渡します。第2引数に抜き出したい数を渡すとその分だけ取ってきます。元の配列の大きさは超えません。

番外: List::Utilを使う

use List::Util qw(shuffle);
print shuffle(0..9,A..Z,a..z);
# 81D9moCj3n0zPO4VwIpGu5aFJR2ftTlyEgvxMHebhcXZYkqUiB6SWdAKrQNs7L

List::Utilはuseしただけでは関数をエクスポートしてくれないので使いたい関数は必ずインポートしましょう。

List::Utilはこれ以上ないくらい洗練されてる(と思う)のでv5.7.3以降のperlを使ってる人はこれ使うといいですね。

抜き出すのはないっぽいから自前で何とかしよう!

追記

  • 「お手軽に抜き出す」に追記。あと0..1011個ですね…
  • 丸め込みのこととかいろいろ考慮してなくて真面目なsub shuffle/potluckがおかしなこと*1になってたので修正しました

さらに追記

*1$old[rand $#old]だと配列の末尾が取れないとか、potluck(\@hoge,10)11個返すとか

NyannaNyanna2011/06/05 09:47Home run! Great slgungig with that answer!

yikfqnoyikfqno2011/06/05 18:02NgKXa8 <a href="http://ytwaiwllkaqd.com/">ytwaiwllkaqd</a>

LorrenLorren2011/06/05 21:19Your answer was just what I nedeed. It’s made my day!

mpusalcmpusalc2011/06/06 23:07fZNUyi , [url=http://fxmxjhkixatn.com/]fxmxjhkixatn[/url], [link=http://xlzdgbhgjqsh.com/]xlzdgbhgjqsh[/link], http://xffxfxayqpgo.com/

xicfqdquxicfqdqu2011/06/07 18:12VSQMgx <a href="http://ohsmkfuuaqow.com/">ohsmkfuuaqow</a>

hgucshczgplhgucshczgpl2011/06/09 19:27zzfuU2 , [url=http://uiqorlryztty.com/]uiqorlryztty[/url], [link=http://keydymymivxx.com/]keydymymivxx[/link], http://ctmxknborxko.com/

March 03, 2010

[][][]WWW::Mechanizeの$mech->contentと$res->decoded_contentがややこしい

LiveDoorReaderのAPIをごにょごにょする用事ができたのでAPI叩いてリダイレクトされたらWWW::Mechanizeでログインするようなコードを書いていたのですが、ちょっと詰まった。

use JSON::XS;
use WWW::Mechanize;
$mech = WWW::Mechanize->new;
$res = $mech->get('http://reader.livedoor.com/api/config/load');
$content = $res->content;
$json = json_decode($content);

上記のようなことをすると、LDR(というかライブドアのいろんなところ)だとgzip圧縮されて送られてくるので、もちろんバイナリ突っ込んでるのでjsonのパースでこける。

でもちょっとだけ書き方変えてみて

$mech->('http://reader.livedoor.com/api/config/load');
$content = $mech->content;

だと$contentはなぜかgzipが解けている。なんでなんで。$mech->contentって$res->contentとは違うの?

ということでちょっと調べてみた

gzipされたコンテンツをテキストに戻すにはHTTP::Response->decoded_contentを呼び出すのが一般的だと思うので、この現象もたぶんWWW::MechanizeのどっかでHTTP::Response->decoded_contentを呼び出してるから起こってるはず。検索。あった。

    # Try to decode the content. Undef will be returned if there&#39;s nothing to decompress.
    # See docs in HTTP::Message for details. Do we need to expose the options there?
    my $content = $res->decoded_content();
    $content = $res->content if (not defined $content);

sub _update_pageにあった。sub requestから呼び出してる。つまり、$mechのオブジェクトにcontentを記録する際に、自動でデコードしているわけだ。普段WWW::Mechanize使わないから気付かなかったけど、ブラウジングが目的のモジュールだから裏で起こってることに気を使わなくていいように設計してあるのか。

とりあえず、原因が分かってよかったです。

まとめると

  • $mech->content
    • レスポンスヘッダを呼んで自動でデコードする。デコードしないとかいう選択肢はない。とにかくする。するんだ。
  • $res->content
    • レスポンスヘッダから下をそのまま返す。かってにいじらない。すべての入力をすべて自動でチェックするというのはちょっとめんどいのでいっそのこと全部手動で確認したい派の僕はこっちのほうがありがたい。
  • $mech->decoded_content
    • 存在しない。
  • $res->decoded_content
    • レスポンスヘッダから推測してよきに計らってくれる。明示的なので書き手のわかっててやってるというのが感じられてベネ。

わかりにくい

わかりにくいですね。わかりにくいです。

WWW::Mechanizeの目的を考えると間違いなく自動でやってくれたほうがいいのですが

$mech->get();
$content = $meck->content;

$content = $mech->get()->content;

で挙動が、というか混乱するからHTTP::Responseオブジェクト返すなよ。

とにかく僕は json_decode したいので勝手にperlのutfフラグ付文字列に変換してもらっては困るし、かといってgzip解凍するのはdecoded_contentが一番楽だ。ああもうもう一回utf8でエンコードすればいいんだろともうなげやりです。なやましい。ねむい。

結論

use utf8;
use strict;
use warnings;
use WWW::Mechanize;
{ no warnings; *WWW::Mechanize::decoded_content = *WWW::Mechanize::content; }

として、レスポンスからコンテンツを取得するときは全部decoded_contentを通した!これで好きなように書いてもデコードされてたりされてなかったりというふらふらした問題は起きん!解決!

LettieLettie2011/06/05 14:23Posts like this brighten up my day. Thanks for taknig the time.

toainvnpdcytoainvnpdcy2011/06/05 18:206B3Hl7 <a href="http://agwauffemhzn.com/">agwauffemhzn</a>

xcyzionpkvixcyzionpkvi2011/06/06 23:09oUloUp , [url=http://octxbchmojcx.com/]octxbchmojcx[/url], [link=http://jbzxirbzkajz.com/]jbzxirbzkajz[/link], http://bgexnmjazfie.com/

mpzzhifsmpzzhifs2011/06/07 17:27uA8xKB <a href="http://btmmykeouaqr.com/">btmmykeouaqr</a>

vliskoyovliskoyo2011/06/09 19:21WgzPtD , [url=http://wqshikjjkaxs.com/]wqshikjjkaxs[/url], [link=http://iwotqequcate.com/]iwotqequcate[/link], http://dqhuyqdnvxvq.com/

April 29, 2009

[][][][]User-Agentとencoded-wordについて (Encode.pmmime encodingする)

User Agentを変更してオリジナリティ溢れるサーバログを撒き散らしたいなーと思い、User Agent Switcherアドオンを導入したり、日本語をUAに使うにはどうしたらいいかを調べているうちに、

  • UAにはascii以外と一部の記号は使えない
  • 使いたいときはRFC2047(原文)で定められている方法、つまりencoded-wordに変換する

ということがわかりました。そういうわけで、今日はmime encodingについてのメモ。

User Agentとは

ユーザーエージェントとは、閲覧者が使っているソフトやハードのこと。ここでは特に、使用している言語、ウェブブラウザ、OS、ディスプレイなどの閲覧環境の情報を指します。

HTTPリクエストの際にブラウザがUser-Agentヘッダをサーバに送信することで、サーバあるいはコンテンツ作成者は閲覧者がどのような環境でウェブサイトを閲覧しているか知ることができ、その情報を元に、閲覧者の環境に合わせたより良いコンテンツを提供できるようになることが期待できます。

User-Agentヘッダの書式

RFC2616によれば以下のような感じ。

User-Agent      = "User-Agent" ":" 1*( product | comment )
 
product         = token ["/" product-version]
product-version = token
token           = 1*<any CHAR except CTLs or separators>
separators      = "(" | ")" | "<" | ">" | "@"
                | "," | ";" | ":" | "\" | <">
                | "/" | "[" | "]" | "?" | "="
                | "{" | "}" | SP | HT

CHAR            = <any US-ASCII character (octets 0 - 127)>
 
comment         = "(" *( ctext | quoted-pair | comment ) ")"
ctext           = <any TEXT excluding "(" and ")">
TEXT            = <any OCTET except CTLs, but including LWS>
OCTET           = <any 8-bit sequence of data>
CTL             = <any US-ASCII control character (octets 0 - 31) and DEL (127)>
LWS             = [CRLF] 1*( SP | HT )
Hypertext Transfer Protocol -- HTTP/1.1 - User-Agent

(まとめるのがめんどくさくてコピペしてしまった…)

簡単に言えば、User-Agent: (product | comment)+ですね。productはhoge/fuga、commentは任意の文字、そして文字列はUS-ASCIIのみという感じ。なのでUser-AgentにはISO_8859_1以外の文字コードは出現出来ないことになってるんですが、Words of *TEXT MAY contain characters from character sets other than ISO-8859-1 [22] only when encoded according to the rules of RFC 2047 [14].*とあるように、RFC 2047に書かれている方法でエンコードすればコメントには他の文字コードも使えますよ、ということらしい。そして、そのほかの方法というのが、encoded-wordというわけだ。

じゃあencoded-wordって?

使用の都合で、MIME-Headerに使用できる文字(記号)が非常に少なくなってしまった。それを解消するために、使用出来ない文字列をエンコードすることでMIME-Headerに埋め込めるようにしよう、ということで出来た仕様がencoded-word...なのかな?

これは他のエンコード技術も混ざってくるので簡潔に書くと、

encoded-word = "=?" charset "?" encoding "?" encoded-text "?="

となります。例えば、=?iso-8859-1?q?this=20is=20some=20text?=など。文字コードセット名と変換方法と変換後のテキストのセットになっています。

このencoded-wordならUser-Agentヘッダのコメント部分に書いてもいいよ、と定められているみたい。User-Agentヘッダで日本語を使うには、このencoded-wordに変換しなくてはいけないのですね。

Perlでencoded-wordを作るには

やっと本題です。

このencoded-wordは、RFC2047のタイトルにもあるように、MIME(Multipurpose Internet Mail Extensions)のメッセージヘッダ拡張のための仕様なので、MIMEヘッダあたりのモジュールで何とかしなくてはいけないのかと思ったのですが、うれしいことに標準モジュールのEncode.pmMIME-Headerの変換に対応しています。

use Encode;

$encoded = encode('MIME-Header', decode('utf8', 'ほげほげ'));
# $encoded => '=?UTF-8?B?44G744GS44G744GS?='

$utf8 = decode('MIME-Header', $encoded);
# $utf8 => 'ほげほげ'

以上のように非常に簡単に変換が出来ました。弾さんすばらしい! dankogai++

v5.008_008以降にはEncode::MIME::Header::ISO_2022_JPが含まれているので、文字コードにISO_2022_JPを指定してエンコードすることも出来るようです。UTF-8を使用出来ない環境ではencode('MIME-Header-ISO_2022_JP')を使用するといいのかな。

$encoded = encode('MIME-Header-ISO_2022_JP', decode('utf8', 'ほげほげ'));
# $encoded => '=?ISO-2022-JP?B?GyRCJFskMiRbJDIbKEI=?='

$utf8 = decode('MIME-Header', $encoded);
# $utf8 => 'ほげほげ'

使用上の注意

ソースを読んだ感じではちょっと癖がありそうなので注意点をまとめてみます。

  • encode('MIME-Header')には通常のencodeと同じく内部Unicode文字列で渡してあげる。
  • decode('MIME-Header')はencoded-word以外は文字コードの変換をしない。よって通常の文字列とencoded-wordが混在するテキストは、まず最初にdecode('utf8')を行ってからdecode('MIME-Header')に渡すといい(encoded-wordASCIIのみで構成されているのでこの順序ならエラーは発生しない)。
  • encode('MIME-Header-ISO_2022_JP')は空白文字の連続を一つの空白に置き換えてしまうと思う。空白を纏められたくないときは s/\s+$//o に引っかからないようにうまく変換してから突っ込まないといけないっぽい。

おわり

mime encodingが出来るようになった!

(=?ISO-2022-JP?B?GyRCS00kLDgrJEYkayRoITwbKEI=?=)をUAに追加したのでどこかで見かけたらアレアレアレしたりするといいです。CardCaptor/1.0 (さくら怪獣じゃないもんブラウザ)のほうがよかったかな。これを機にみなさんもガンガンUAを偽装したり解析ツールのUAの項目でmime decodeするようにしたりすればいい。

最後に。User-Agentヘッダはコメントに括弧以外のASCII使えるから、標準にこだわらなければ日本語部分は文字実体参照でいいんじゃないかな。

cf.

JaylanJaylan2011/06/05 22:06Your awsenr was just what I needed. It’s made my day!

uncggzquncggzq2011/06/06 18:07VkzW2b <a href="http://bazssydhulju.com/">bazssydhulju</a>

rnotiknmernotiknme2011/06/06 22:516W6jyg , [url=http://vjlrqqsuarfu.com/]vjlrqqsuarfu[/url], [link=http://oeohkpmelmrv.com/]oeohkpmelmrv[/link], http://lalaqariytii.com/

veouwlvxzveouwlvxz2011/06/09 00:02epmGVP <a href="http://apsbpliumimg.com/">apsbpliumimg</a>

KatjaKatja2012/11/03 13:50I read your post and wsehid I'd written it

pgamkipgamki2012/11/04 05:54QFUHkU <a href="http://tirvpgeshoxg.com/">tirvpgeshoxg</a>

ncglcpncglcp2012/11/05 14:048Nqo20 , [url=http://vlordrxnqozv.com/]vlordrxnqozv[/url], [link=http://wrjynzgkehnl.com/]wrjynzgkehnl[/link], http://twifqduguylk.com/

kyjifrkyjifr2012/11/07 22:297Ok1SN <a href="http://zibsbcepneqq.com/">zibsbcepneqq</a>