Archive for 2月, 2010

今回は、airxmailのちょっと変わった使い方とでもいうのでしょうか?
(airxmailの説明はこちらをご覧ください。)

まあ、技術的にはSMTPでメールを送っているだけですが、こんなこともできますよーという一例の紹介です。

最近、Google バズというものがあるらしく、そこにAirxmailを使ってバズって(っていうの?)見ました。

google_buzz

と実は、これ簡単。
前回、「airxmailでGmailを使ってメールを送信する」の応用です。

といってもほとんど同じ、変わるところは以下の2つ。

1)宛先を buzz@gmail.comにすること。
2)メールのヘッダの文字コードをUTF-8にすること。

さて、

sender = new SMTPSender();
sender.setParameter(SMTPSender.HOST,"smtp.gmail.com");
sender.setParameter(SMTPSender.PORT,465);

//  SMTP-AUTHの使用
sender.setParameter(SMTPSender.AUTH,true);
sender.setParameter(SMTPSender.USERNAME,username);
sender.setParameter(SMTPSender.PASSWORD,password);

// STARTTLSの使用
sender.setParameter(SMTPSender.SOCKET_OBJECT,new com.hurlant.crypto.tls.TLSSocket());

は前回と一緒。
ここからが、ちょっと違う。

AirxMailConfig.setDefaultBodyCharset("UTF-8");
AirxMailConfig.setDefaultHeaderCharset("UTF-8");
			
var mimeMsg:MimeMessage = new MimeMessage();
			
var from:INetAddress = new INetAddress();
from.personal = "おれじゃ";  //  特に何も反映されないようですが・・・
from.address = this.fromEmail;
			
mimeMsg.setFrom(from);
var toAddr:INetAddress = new INetAddress("buzz@gmail.com","buzz");
mimeMsg.addRcpt(RecipientType.TO,toAddr);
// set mail subject
mimeMsg.setSubject("初めてのBuzzzzzzz! From airxmail");
mimeMsg.setTextBody("");  //  ここで、本文はなくても、空で設定が必要。現在、airxmailのバグ
			
sender.send(mimeMsg);
sender.close();

ということです。

AirxMailConfig.setDefaultBodyCharset("UTF-8");
AirxMailConfig.setDefaultHeaderCharset("UTF-8");

の2つで、本文とヘッダのデフォルトの文字コードを変えることができます。

もしくは、サブジェクトだけの文字コードを変えるのであれば、

mimeMsg.setSubject("これでもだいじょうぶだよー。Buzzzzzzz! From airxmail","UTF-8");

でも、問題ありません。

今日は、クラウドの構成、事例を聞いてきた。

そこで、あれ、ちょっと待てよ、「そもそもクラウドになったらロードバランサーって必要か?」
ということを思った。
っていうか、必要になるようにしか構成を結局組めないのか?というのが本音だ。

ただ、WEBのコンテンツを提供しているようなメディアは除外していただきたい。
対象は、いわゆるSIerにハード構築を依頼するようなレベルの話だ。

(ただ、自社ですべてやっている場合なら、必要であれば、自分たちでロードバランサーもどきなんて作ってしまえとも思ったりもする。それで充分なのだから。)

あくまでもこれからの前提は私が見てきたサーバ構成ですが、たいていはネットワーク構成の教科書にあるような構成なので、
多くのケースが当てはまるのではと思う。

さて本題にもどり、なぜ私たちのサービスにはロードバランサーが必要なのだろうか?
冗長性を・・・・2重化を・・・・

と、こんな感じの答えが聞こえやしないだろうか?

じゃ、クラウドでハードが壊れることをあまり考慮しなくても?やっぱり?いる?

ロードバランサーがあれば、高負荷にも耐えられるじゃないか?

でも、じゃ、高負荷でボトルネックになるDBは、それ以上にロードバランスができるようなDB設計になってるの?
っていうか、DBは1つしかないですよ。
あっても、故障時に切り替えられるようになっているだけじゃないですか。
(わたしは、サービスをやるときにはテーブルを移動できるようにするため、基本的にリレーションははらないが・・・・、
昔、遊びで、1つのシステムのコンテンツのDBがDB2と、MySQLとPostgreSQLに分割してって遊んだことがあるなー。
いや、遊びといってもテストですよ。テスト。)

じゃ、WEBも故障時に切り替えられればいいんじゃないの?そのレベルでいいのでは?
これは思えば、「TOC:チェンジ・ザ・ルール」で言っていたケースだ。

クラウドにより制約がなくなった。もしくは、無視してもいいようになってきた。
にも関わらず、相変わらず、構成は昔のままなので、その対策であったポリシー自体が今度はボトルネックになってしまうのだ。

(というか、個人的には、ロードバランサがあり、また、WEBの多段層化のおかげで、
その後工程でとまどっているにも関わらず、次から次へとリクエストを受け付けて中間層でパンクしてどうにもならない。というケースをよく見た。
まあ、要するにアプリがバグっているのだが・・・ApacheやDBにほぼバグは発生しないことを考えればしょうがないが・・・
ただ、だったら、WEBでリクエストを絞って受け付けないほうがまだ顧客のためだ!という思いもある・・・)

私の今のクラウドの理解が正しければの話ですが・・・・・
いやー、このあたりが本当かどうかを実際にためしてみたいものですが・・・・

mod_chxjは、現在、端末の識別設定をXMLで行います。

補足)mod_chxjとは、ドコモ向けにに書かれたhtmlをサーバ側で自動的に各キャリアごとにhtmlの変換やら、画像サイズの変換やらをやってくれるApacheのモジュールです。

まあ、XMLというフォーマット自体もちょっと面倒といえば面倒なのだが、
それ以上に、端末の識別が正規表現というのが非常にめんどくさい。

かといって、CSVやTSVから端末IDからすべて設定というのも、オープンソースという性質から考えてちょっと不親切ですよね。
(だって、端末情報を含めてきちんと提供できるわけでもないわけですから・・・)

特に最近は、「3Gの端末で、とりわけひどい状況にならなければいいんじゃないの!」

という感じで携帯サイトを運用したいと考えれば、1つ1つの端末に対する設定ということをしなくてもいいという判断もあり得ます。

であれば、正規表現でいいのだが、それだと、例外が面倒です。

もちろん正規表現は非常にパワフルなので、できることはできるのだが、例外くらい個別に指定できる方が直感的に理解しやすい。

たとえば、DoCoMo/2.0の端末はほぼ、XHTMLのフォーマットが使えるらしい。
ただしDoCoMo/2.0にも関わらず、D2101V、P2101V、SH2101V、T2101V、N2001、N2002、P2002の端末がXHTMLはだめらしい。

と、ここでふつうにやりたくなるのは、パターンでDoCoMo/2.0の端末はすべてXHTMLでフォーマット。
D210V、・・・・は、個別に例外で除外。つまり、ほかのフォーマットを適用。

ということをしようとすれば、何らかのパターン表現のフォーマット+個別指定のフォーマットというのが理解しやすいいうことになる。

ということで、mod_chxjにTSVから端末情報を読み取り、上書きできるようなパッチを作成し、オリジナルに返しました。
(まだ、反映はされていませんが・・また、以前述べたよう(下記、関連する記事を参照)にこれ以外にも、XHTML関連のCSS対応も返しているので、こちらと合わせて、
だいたい私的に、XHTML端末のサイトを運用するのに、mod_chxjでカバーできるようになったとおもう。)

最近、端末性能が良くなって、以前ほど、画像サイズだ、なんだと気にしなくてもよくなってきたので、
ルーズな運用用途のニーズもあるのではないでしょうか?
まあ、そんな運用にも耐えやすいのは、オープンソースという特性ならではでないでしょうか。

でも、きちんとサービスを継続していくと、結局、個別の指定も必要になってしまうんだけどね。
そこまでの過程としても、いいだろうし・・・・

ということで、結局、個別の指定が必要なんだよねとなってしまったサイトにも、メリットがあるように、
さらに、ちょっとしたおまけとして、TSVでは任意の項目を定義できるようにしました。

mod_chxjで管理していない端末情報をリクエストヘッダに設定するようにしましたので、
使い方によっては、もっと応用できると思います。

オリジナルに反映される頃には、具体的な指定方法とか、使い方を記述できたらと思います。

ちょっと、たまたま、あるサイトのURLで検索をかけたら、以下のサイトの結果が検索対象になった。

http://bizinformation.org/jp/

まあ、ちょっと面白そうなので、自分でもやってみた。
ほー、金額はいざ知らず、PVやユーザ数がなかなか近いではないか。
少なくとも、オーダーはあっている。

ほかに、PVなどを知っているサイトをやってみたが、これもなかなか近いのである。
んー、どうやって、そのあたりを予測しているのか、それが興味がある。。。。。

あとは、どうして、こういうサイトの結果が検索エンジンに引っかかるのかなーと疑問に思ったが、
まあ、これは自分の行動で読めた。

まあ、こうやるからだ。
自分で原因つくってりゃ、そりゃそうだわな。

さて、今回は前回の宣言どおり、configure;make;などの流れです。
これらのツールを autoconf と automakeといいます。

といっても、私も意味がわからないので、とりあえずは、以下を参考にしました。
http://www.02.246.ne.jp/~torutk/cxx/automake/automake.html

autoconfや、automakeで検索すると参考になるようなサイトはそれほどないので、それぞれ見てみるのもいいと思います。
最初は意味を理解して処理をしているのではなく、手順として処理をしているので、
ディレクトリ構造のちょっとした違いだけでもはまってしまいます。(しまいました。)

これらを参考に私も、ほぼ同じように作ってみました。

用意したのは、
/Makefile.am
/src
+– part1.c
+– Makefile.am

par1.cの内容

#include <stdio .h>
#include <stdlib .h>

int main(int argc, char const *const *argv, char const *const *env)
{
  printf("Hello \n");
}

と例の単なるHelloを表示するだけのプログラムです。

しかし、処理のいたるところでワーニングが出まくります。
無視していいとは書いてありますが、記載ている内容と行っているないように違いがなければ無視していいかもしれませんが、
なんせ、ただ真似ているだけの身として、結果としてうまくいかなかったときに、ただやみくもに探しては時間がかかります。

そこで、もう一度、gccなどを使って、プログラム自体に間違うがないということを確認する上でも、コンパイルだけでもできるようにしておきましょう。

gcc -o part1 part1.c

と、実行してください。-o で出力するファイル名が指定できます。
いやー、恥ずかしながら、私はこのレベルから調べ始めなおしました。

さて、今回の復習。

1)プロジェクトのTOPディレクトリに Makefile.am を用意し、ソースのパスを指定する。
2)ソースディレクトリにMakefile.amを用意する。

3)autoscanを実施し、その結果(configure.scan)からconfigure.ac を作成する
 このファイルを編集し、utomakeを使うための記述を行う。

私の場合には、以下の2行を編集・追加を行いました。そのほかは、変わりありません。

AC_INIT(part1, 1.0,[coltware@localhost] )
AM_INIT_AUTOMAKE([foreign])

4)以下のように処理を行う。

aclocal
autoheader
automake -a -c
autoconf

の順に処理を行う。
これで、configureの作成完了。あとは、いつもの通り。

さて、ここまでは、ほぼ、このプロジェクトのみで依存関係が完結しているために、
簡単でしたが次回からは、ここに、aprというApacheで使われている基本的なライブラリを使うあたりまで説明したいと思います。
そして、libxml2とtidyなどを使っていきたいと思っています。

今回はPOP3で接続する方法を記載します。

接続までの流れ

必要なクラスは以下のようなクラスになります。

import com.coltware.airxmail.MimeMessage;
import com.coltware.airxmail.pop3.POP3Client;
import com.coltware.airxmail.pop3.POP3Event;
import com.coltware.airxmail.pop3.POP3ListEvent;
import com.coltware.airxmail.pop3.POP3MessageEvent;

送信時には、Senderというようになるべくプロトコルを意識しないようにしましたが、POP3ではまだそれらができていません。
将来的に、IMAP4もできたときにそれらができるようにしていきたいと思っています。

さて、それではおおよその流れですが・・・

var client:POP3Client = new POP3Client();
client.host = "pop.foo.com";
// client.port = 25; // デフォルトは25
client.setAuth("username","password");

client.connect();
 :
 ここで何らかの処理を書く
 :
client.quit();

が一連の流れになります。
ちょっとした注意点ですが、

client.disconnect();

を実行しますと、現在はSocketの切断になってしまいます。
(これは間違えやすいような気がしますので・・・)
将来は、このあたりを変えようと思っておりますので、どのバージョンでもきちんと切断するには、quit()を使ったほうがとりあえずはいいかもしれません。

メールの一覧を取得する

メールの一覧では2つの処理が必要です。
1)一覧を取得するハンドラメソッドを記述する
2)一覧を取得する命令を投げる

です。
また、メールの一覧を取得するにはPOP3で2つのコマンドがあります。
・ list
・ uidl

uidlは、すべてのPOP3サーバでサポートされているわけではありませんが、私はサポートされていないPOP3サーバを知りません。

また、airxmailでもおおよそ同じような流れで取得できます。
では、取得方法です。

// listコマンドの結果
client.addEventListener(POP3ListEvent.POP3_RESULT_LIST,resultList);
// uidlコマンドの結果
client.addEventListener(POP3ListEvent.POP3_RESULT_UIDL,resultList);

private function resultList(e:POP3ListEvent):void{
  for(var i:int = 0 ; i< e.length; i++){
    trace("item [" + i + "] => " + e.getNumber(i) + "=" + e.getValue(i)); 
  }
  client.quit();
}

ここで、e.getNumber()とe.getValue()のかえる値が listコマンドとuidlコマンドでは多少ことなります。

listコマンドの結果

item [0] => 1=1182
item [1] => 2=1182
item [2] => 3=1065709
item [3] => 4=1065695
item [4] => 5=1065694
item [5] => 6=1065694
item [6] => 7=1065691
item [7] => 8=1065691
item [8] => 9=1065691

uidlコマンドの結果

item [0] => 1=000000014b5cd9ba
item [1] => 2=000000024b5cd9ba
item [2] => 3=000000034b5cd9ba
item [3] => 4=000000044b5cd9ba
item [4] => 5=000000054b5cd9ba
item [5] => 6=000000064b5cd9ba
item [6] => 7=000000074b5cd9ba
item [7] => 8=000000084b5cd9ba
item [8] => 9=000000094b5cd9ba

e.getNumber(i)の値は、ともに変わらないのですが、
e.getValue(i)がlistコマンドでは、メッセージのサイズに、uidlコマンドでは、POP3が発行するユニークなメールを識別するIDとなります。

したがって、後でメールを削除する場合などは、自然とuidlコマンドのほうを使うことになると思います。

メール(メッセージ)を取得する

メッセージの取得も、ハンドラと処理の2つのセットになっています。
また、実際のメッセージの取得は、listもしくはuidlコマンドの結果の中でおこないます。
したがって、先ほどと合わせたときのソースはこのようになります。


// uidlコマンドの結果
client.addEventListener(POP3ListEvent.POP3_RESULT_UIDL,resultList);
// メッセージの取得
client.addEventListener(POP3MessageEvent.POP3_MESSAGE,messageHandler);

private function resultList(e:POP3ListEvent):void{
for(var i:int = 0 ; i< e.length; i++){ client.retr(e.getNumber(i),e.getValue(i)); } client.quit(); } private function messageHandler(e:POP3MessageEvent):void{ var msg:MimeMessage = e.getMimeMessage(); trace("SUBJECT:" + msg.subjectUTF8); : ここでいろいろと本文に関する処理をする : } [/as3] retrメソッドは第1引数は、listでも、uidlでも同じですが、第2引数はpop3のuidとなっています。 ここで、指定すると、後でMimeMessageのプロパティとしても取得が可能となります。 次回からは、受信したときのMimeMessageの中身を見ていくことにします。

年末くらいから、mod_chxjというApacheのモジュールを触っており、そこで、C言語をとりまく環境とでもいうのだろうか?

こういった部分がよくわからなく、非常にこまった(現在も困っている)。

たとえば、オープンソースを使ってコンパイルとかリンクするにはどうしたらいいの?とかだ。

今はすでに先人がMakefileを作ってくれているので、このあたりをまったく考えなくてもいいのだが・・・やはり、新たにゼロからと考えると、どこから入ればいいのかわからない。

そもそも、私は今、C言語をsyntaxとして触ってはいるが、C言語という環境をつかう経験がない。

したがって、見よう見まねで、見たことがあることは同じようにできるが、ちょっと深ーくなるとどこから触っていいものやら・・・・

そもそも、学生時代にC言語を勉強して、自分で卒論のために書くことにしたときにどうしても、ヘッダファイルだ、リンクだ・・・なんだかんだと環境がめんどくさく、C++Builderや、Javaに乗り換えてしまったのが、今頃になってあだになるとは・・・

個人的には、結構多くの方が、C言語というsyntaxではなく、文化とでもいうのだろう?それに抵抗を感じるのだ。

Linuxを使ってJavaやPHPなどでプログラムをしている。ミドルウェアなども関連して使っている。

Cのソースにちょっと見て、そこの動きがどうなっているのかぐらいはやってもいい。でも、こと環境面までかんがえると・・・と、そういう部分に距離感を感じ、足を踏み込めないということもあるのではなかろうか?

そこで、真面目にC言語の環境というのを基本から勉強することにした。

ただし、一般の本屋さんでふつーに並んでいることをここで書く気にはなれないので、

今まで、

configure

make

make install

と呪文のようにやっているが、自分でつくるプログラムもこれと同じようにできないとともっている。

これがわかれば、たとえ自分でC言語を使わないまでも、オープンソースのインストールなどでつまずいても、自分で糸口がつかみやすいのではないだろうか?

それに、もともと、こういった部分を自分で1つ1つ解決していくのが面倒なのも、C言語からはなれた理由なので、これを自動化することができれば、より自分にとっても身近になるはずだ。

それと、やはり、「郷に入れば郷に従え」で、私もC言語を使ったプログラムはこれでいけるとおもっているので、これに従うほうがいろいろと便利だろう。

ということで、今後、この

configure; make; make install

を見ていく。

ただ、具体的なアプリも作りたいので、やはりApacheのモジュールを例題として考えていこうと思う。

またそこで使う(使いたいと思っている)、aprやlibxml、DB(sqlite,mysql)など具体的に構築する上での環境構築方法を載せられたらと思う。

といっても、今時点、本当によくわからないので、いろいろと間違いや勘違いがふくまれていくとは思いますが・・・・

subversionのリポジトリをgitに変換はよくあると思うが、gitのリポジトリをSubversionに変換というのを今回やりたい。

というのも、何度もいっているが、中央には、Subversionで、各ワークをgitで私は使いたいからだ。
(これは、Tracとはviewvcとか、すでに構築してしまった環境を変えるのも面倒というのもある。)

しかし、今回はとりあえず、ネットにつながっていない環境で初めてしまったgitのリポジトリをSubversionに変換して、
再度、git-svnで再開したいのだ。

こんな用途を持っている人はあまりいないのか、WEBで方法を探したがすぐには見つからなかったので、
自分なりに、次のような手順でログ情報だけでも取り込むことにした。

Subversionのリポジトリを作成

ここでは、Subversionでのリポジトリを作成する方法は述べない。
で、svnで、trunk , tags, branches のディレクトリを作成し、コミットしておく。
これで、リビジョンは、[1]になったわけだ。

※どうやら、log情報がないとこれからやる処理がうまくいかないらしく、リビジョン1を作成するためにやった。

git-svnで、リポジトリの情報を取得

git svn clone svn://・・・・・ -T trunk -t tags -b branches

これで、gitとしてのワークができあがったことになる。

gitで育ててしまったワークをgit-svn のワークのリモートとして登録する。

ここでは、/home/foo/local.git がgitのリポジトリとする。
また、その名前を”org”としてつけた。

もちろん、このコマンドはgit-svn のワークの中で行う。

git remote add org /home/foo/local.git
git fetch org

パッチファイルを作成する。

ここで、git-mergeをはじめ行ったが、それでは、リビジョン1の前のログとなってしまい、Subversionにログを登録することができなかった。
そのために、git-format-patch を使った。

git format-patch -o patches master..org/master
git am patches/*.patch

できあがったログをSubversionにコミットする。

git svn dcommit

で終了だ。

ある文字と、ある文字が違うところを探そうということを、
ロジカルにやろうとすると、実は結構めんどくさい。

一文字、一文字順次見ていき、違うかどうかを見ていっても、
そこそこうまくいくが、ある条件を超えるとうまくいかなかったりする。

でも、すでに世の中に存在するので、うまくやろうと発明する必要はないが、このようなアルゴリズムってどこを探せばいいのかな?と思う。

で、より分かりやすいサイトを見つけたので、メモ。
ここです。

実は、ここにたどり着く前に、いろいろ調べて、アルゴリズムの名前を見つけて、解決できるようになって、自分で必要なくなってから、それをもっとよく知るための情報が見つかるんですよね。

さて、今回は上記サイトを参考(そのまま?)に、ActionScript3用に書き直し、
それをもとに簡単ではありますが、動作を確認できるようにしました。

ソースのダウンロードは、下のFlashのソースViewからできるようになっています。

元ネタは「アドビ、スマートフォン向け「AIR」をリリースへ–まず「Android」から」

前々から、Adobe関連のサイトでは言っていたことなので、それほど、記事の内容としてはびっくりするようなことでもないし、
新しいことでもないのだが、改めてAIRというものを考えるいい起点だと思うので、取り上げてみた。

そもそも、私がAIRという技術に目をつけたのは、ある失敗(だと思う)したという思いがあったためだ。
私は2005年にあるASPの立上げを行った。そこで、リッチクライアントという技術を採用することを決めた。

おんなじような要件がある会社はFlashを採用していたが、私は当時、FlashもActionScriptも知らないし、
何より、ローカルPCにある資源を活用できないという点が気に入らなかった。

まあ、ASPにも関わらず、ブラウザベースではないというあたりは、かなり斬新ではなかったのではないかとおもう。
(ちなみに今もそのサービスは稼働している。)

そして、採用したのが、EclipseのRCPだ。

そこで感じたのが、WEBシステムとクライアントシステムの文化(ノウハウ)の違いだ。

とくに、一番の問題と感じたのが「圧倒的な自由度」だろう。(WEBに比べてという意味)

WEBといういわば、バッチ的なプログラムでよかった。
HTMLとSQLと言語(ロジック)というように、レイヤーが3つにわかれており、さらに通信という手段は選択できないに等しい。
でも、通常のクライアントアプリはちがう。
どこで、どのような手段で通信するかも、どうレイヤーを分けるかも、ルールベースでの抽象論的なものであり、
WEBのような超えられない(超えてはいけない)壁のように立ちはだかる制限はない。

これが、たまらなく、きついのだ。ルールが保てない。
つまり、設計の品質が保てない。

AIR(とその周辺)は、それに比べれば、つよい制約があるから素晴らしい。
アニメーション(Flash)・画面(MXML)・デザイン(CSS)、ロジック(ActionScript)・・・・
1つのアプリを作るのに、いろいろな言語を覚えなくてはいけないのはWEBと同じだ。

そして、ほとんどのアプリ(サービス)が、ブラウザベースのアプリにちょっと気持ちをたしたレベルで満足できるのである。
そのレベルのアプリケーションプラットフォームを求めていた。

これは、かつて、WEBアプリ = JAVAというような感じになったのに近くないだろうか?
サーバ=JAVA
クライアント=???

と。

そしてそのクライアントとして、新しく、しかも影響力がつよくあらわれてきたのが、SmartPhoneだ。
ビジネスツールとして考えれば、携帯のアプリがあればいいのはわかっていたが、それを行うコストが高すぎた。

しかし、SmartPhoneという今までよりももっとPCに近い、「携帯」が普及しはじめたことで、そのコストも下がってくる。
そして、何より、携帯ならではのデバイスと連携するための手段が必要になるのでブラウザの制限の外に出る必要があるのだ。

サーバで生じた、ある制限のもとでの共通プラットフォームが、PCに広まりきらないうちに、携帯(SmartPhone)に来てもおかしくはないのではないかと思っている。

その候補として、iPhoneは「携帯アプリ」としてその火つけをしてくれたが、iPhoneを離れて、
オフィスでMacが使われるようになるとは思えない。

HTML5が、クライアントツールのデファクトとなってしまうのも、役割がおかしい。
(もし、そうなれば、今度はWEBブラウザの代わりと、機能限定版のHTMLが必要になってしまう。依然としてたんなるViewerレベルでしか機能しないツールは必要なのだ。)

AIRが本気になって、SmartPhoneにおけるプラットフォームとして機能するのであれば、AIRは非常に魅力的で、将来性が高まってくるのではないだろうか?

お仕事のご依頼・相談
この記事に関連するお仕事のご依頼やご相談をお待ちしております。 詳しくは、こちら
ソフトウェア&ライブラリ




ライブラリ
airxmail(en)
AIR版メール送受信ライブラリ
airxzip
AIR版ZIP圧縮・解凍ライブラリ
執筆書籍
本、雑誌等

WEB記事:CodeZine
執筆記事はこちら
カレンダー
2010年2月
« 1月   3月 »
1234567
891011121314
15161718192021
22232425262728

カスタム検索
RSS
Add to Google < !–adsense–>
アーカイブ
カテゴリ
にほんブログ村 IT技術ブログへ