bitcasaDiff

(目的)
BitcasaAPI経由で取得できるファイルリストは、アップロードが完了したファイルのみが取得できるので
APIで取得したBitcasaのファイルリストとローカルのファイルリストを比較することにより、
アップロード忘れや不完全ファイルなどのアップロード失敗ファイルを検出する
API経由でダウンロードできるか確かめてハッシュを計算する

(改版履歴)
1.0.0.1(2014/04/14)
公開バージョン
1.0.0.2(未公開)
ラッパーを除去してC++で直接呼ぶように変更
1.0.0.3(未公開)
保存しているトークンを外部から窃用されないように難読化
メモリ上にダウンロードしてハッシュを計算できるように
バグ修正
1.0.0.4(未公開)
ファイルの日時やサイズを表示するオプション
1.0.0.5(2014/07/14)
メッセージを修正
1.0.0.6(2014/07/16)
APIが正常な応答を返さないときに無限にリトライしていたのを失敗させるように

(実行に必要な環境)
Microsoft .NET Framework 4.0
Visual Studio 2013 の Visual C++ 再頒布可能パッケージ

(コンパイルに必要なもの)
Visual Studio 2013 pro(他のバージョンでは確かめていない)
openssl (dllコンパイルしてつけてある)

C++/CLI->opensslでBitcasa APIを叩きます。

(中身)
src\
 ssl\ opensslからコンパイルと実行に必要なものを持ってきた
 BitcasaDLL\ opensslによりBitcasaAPIを叩く足回り
 WebWindow\ はじめの認証をWeb表示するモジュール
 BitcasaDiff\ 本体
 bin\ コンパイルしたらここにコピーされます

bin_x64\ 64bitコンパイル実行ファイル(dllは全部要るはず)
bin_x86xp\ 32bitコンパイル実行ファイル(dllは全部要るはず)

(実行時の注意)
/hash オプションをつけてlist, diffを実行すると、Bitcasaからのダウンロードが発生します。
このとき、最大スレッド数*64MiB*3+順不同のブロック数*64MiB+α のメモリを消費します。
デフォルトで64bit版は10スレッド(1.9GiB)、32bit版は4スレッド(768MiB)になっていますが
メモリ消費を抑えたい場合は/maxthread オプションでそれより少ない数を指定してください。

(使い方)
簡単な使い方は以下の通りですが、オプションの説明は howtouse_jp.html
にまとめたので参照してください。

Bitcasaのフォルダ内容リストを表示する(I:\直下)
> BitcasaDiff list \
Bitcasaのフォルダ内容リストを表示する(本当のルート)
> BitcasaDiff list \\

ローカルのフォルダリストを表示する(D:\)
> BitcasaDiff local d:\

BitcasaのI:\TVdata\ 以下と、ローカルのD:\TVdata\ 以下のファイルリストの一致を見る
> BitcasaDiff diff d:\TVdata\ \TVdata\

BitcasaのI:\test\ の*.isoファイルをメモリ上にダウンロードしてハッシュを計算する。
(メモリ上の内容はハッシュ計算の後、捨てられます)
> BitcasaDiff list \test\*.iso /hash MD5,SHA1

BitcasaのI:\TVdata\ 以下と、ローカルのD:\TVdata\ 以下のファイルリストの一致を調べ
一致した場合さらに両者のSHA256ハッシュを取って比較する。
> BitcasaDiff diff d:\TVdata\ \TVdata\ /hash SHA256


(技術的情報と注意)
IEコンポーネントのバージョン問題で、Web表示できずログインできないので
レジストリに一カ所書きに行きます。
src\WebWindow\Form1.csのこのあたり
Microsoft.Win32.Registry.CurrentUser.CreateSubKey(@"Software\Microsoft\Internet Explorer\Main\FeatureControl\" + feature))

ログインに必要な一時キーを取得するauthenticate APIコールにおいて
リダイレクト先をBitcasaに要求されています。
この目的のため、https://www.lithium03.info/login/login_success.html?authorization_code=xxx
のページにリダイレクトしています。
authorization_codeはログイン時にClientSecretと共にaccess_token APIに提示することで
アカウントにアクセスできるトークンを取得するのに使います。
302応答のLocationに入っているところで抽出すれば、うちのサイトへのGETアクセスはしなくてよいのですが、
IEコンポーネントで自動的にリダイレクトして飛び先から抽出した方が容易なので今の形にしています。

初回ログイン時にパスワードを要求するウインドウは、WebWindowによってIEコンポーネントを使って出しています。
フォームのタイトルに、現在表示中のURLが出ています。
ログインが成功してauthorization_codeが提示されるまでの間のページは、すべてBitcasa側のサイトです。
ログインページ
https://developer.api.bitcasa.com/v1/oauth2/authenticate?client_id=aaefc0f0&redirect=https://www.lithium03.info/login/login_success.html

ログイン動作時の詳細なページ遷移については、\src\BitcasaDLL\BitcasaAPI.cppにある
int BitcasaAPI::authenticate() を参考にしてください。
この関数は、WebWindowと同等の動作(BitcasaAPI::authenticate())をするCUIの関数ですが、
現在のコードでは使用していません。
ここで行っているように、手パースすると余計な場所に一切アクセスしないでauthorization_codeを
取得できるのですが、ログイン時の遷移をBitcasaが予告なしに時々変更してしまうことと、
権限を要求する画面を加工してしまうのがまずいので、現在はWebWindowを使うことにしています。

いったん有効なトークンを取得できたら、移行の接続はすべてdeveloper.api.bitcasa.com:443への
SSL接続のみで行われます。
developer.api.bitcasa.comの名前はラウンドロビンで複数のIPアドレスが時間によって切り替わっている
模様です。opensslモジュールの自動接続により、よきにはからって切り替わります。

(注意事項)
APIコールはBitcasaサイトの条件を読んで、用法用量を守ってください。
サーバーに高負荷をかける行為は規約で禁じられています。
あまり連続して呼び出すとAPI回数切れになるので、数分後にもう一度試してください。

ソースコードのうち、私が書いている部分(openssl以外)はパブリックドメインです。
