ページ

ラベル TwitPic の投稿を表示しています。 すべての投稿を表示
ラベル TwitPic の投稿を表示しています。 すべての投稿を表示

2010年4月13日火曜日

Twitpicアップローダ開発(5) ソース公開

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

とりあえず動くものができたのでGitHub へソースをアップ。
xcatsan's twitpic.up at master - GitHub

現状でも SimpleCap と連携して簡単にアップできる。


残りは...
・エラーハンドリング
・Twitpic系(サイズオーバー、形式違い、...)
・ネットワーク系(タイムアウト他)
・チェック強化
・ドラッグ&ドロップのサポート
・メッセージの多言語化
・アイコン作成
・Keychain周り整理
・プリファレンス用意(Keychain削除、実行モード設定など)

他の開発の合間に少しづつ進め、頃合いをみて正式版をリリースする。

2010年4月12日月曜日

Twitpicアップローダ開発(4) 2回目以降の認証失敗解決〜Keep-Aliveをオフにする

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

(前回)Cocoaの日々: Twitpicアップローダ開発(3) 開発中

2回目以降のアップロードに失敗する件について調査した。

現象は1回目のアップロード成功後、2回目が失敗する。失敗時のエラーは "1001 - Invalid twitter username or password"
1回目と2回目で同じ username/password を使っていることは確認済。

ネット上で情報を探した限りでは同様の問題については1件だけみつかった。
Twitpic not working, Posterous is... why? - Stack Overflow

ただ解決していない様子。


さらに調査したところ、1回目の成功後,60秒すぎると2回目でも成功するようになることがわかった。また別プロセスでほぼ同時にアップロードを行った場合も両プロセスともに成功した。

このことからなんらかのセッション管理が影響を及ぼしているのだと考えてリクエストヘッダやレスポンスをダンプしてみた。

リクエストヘッダ

twitpic.up[25881:80f] requestHeaders : {
    "Accept-Encoding" = gzip;
    "Content-Length" = 39135;
    "Content-Type" = "multipart/form-data; charset=utf-8; boundary=0xKhTmLbOuNdArY";
    Cookie = "__qca=P0-1902714012-126624....(略)";
    "User-Agent" = "twitpic.up 1.0 rv:0.1 (Macintosh; Mac OS X 10.6.3; ja_JP)";
}

レスポンスヘッダ
twitpic.up[25881:80f] responseHeaders: {
    "Access-Control-Allow-Origin" = "*";
    Connection = "keep-alive";
    "Content-Encoding" = gzip;
    "Content-Type" = "application/xml";
    Date = "Mon, 12 Apr 2010 14:28:35 GMT";
    Server = "nginx/0.6.35";
    "Transfer-Encoding" = Identity;
    "X-Powered-By" = "PHP/5.2.10";
}

リクエスト時に Cookie が渡されているが、これはどうも WebKit の Cookie が使われているようだ。WebKit の Cookie は以前のブログで見たようにすべてのアプリで共通に使われる。実際、別のサイト(例えば google.comなど)に ASIHTTPRequest からリクエストを送ると、初めてにもかかわらず Googleサイト用の Cookie が飛んでいた。

Cookie が怪しそうだ。

前回のコメントで [ASIHTTPRequest setSessionCookies:nil]; を呼ぶと2回に1回は成功する様になるとのアドバイスをもらったので、試したところ確かにそのような結果となった。やはり Cookie なのか? ただ2回に1回というのがよくわからない。

その後、ASIHTTPRequest やレスポンスヘッダを眺める内に Connecion = "keep-alive" が気になった。そういえば 60秒後に成功するというのはなんとなくだが keep-alive のタイムアウトっぽい。そこで試しにこれを切ってみる。ASIHTTPReuqest には shouldAttemptPersistentConnection というプロパティがあるのでこれに NO を入れてやれば良い。

request.shouldAttemptPersistentConnection = NO;

すると...成功。連続で何度やっても成功した。おお、原因は Keep-Alive だったのか。

レスポンスを見ると Connection= close になっているので当たりのようだ。
twitpic.up[25839:80f] responseHeaders: {
    "Access-Control-Allow-Origin" = "*";
    Connection = close;
    "Content-Encoding" = gzip;
    "Content-Type" = "application/xml";
    Date = "Mon, 12 Apr 2010 13:34:22 GMT";
    Server = "nginx/0.6.35";
    "Transfer-Encoding" = Identity;
    "X-Powered-By" = "PHP/5.2.9";
}

Twitpicサーバ側ではなく、クライアント側(ASIHTTPRequestの設定)が原因だったか。ネットで探しても解決策がなかなか見つからないわけだ。


- - - -
Keep-Aliveだと失敗する理由はわかりません。誰か分かる人、コメント投稿をどうぞ。

2010年4月9日金曜日

Twitpicアップローダ開発(3) 開発中

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

こんな感じ。

Send を押すと初回のみ認証。
アップロード中。
終了後は画面を自動的に閉じる。

- - - - -
2回目以降の認証が必ず失敗してハマっている。

2010年4月5日月曜日

Twitpicアップローダ開発(2) 開発中

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

(前回)Cocoaの日々: Twitpicアップローダ開発(1) 開始

ただいま開発中。下図は SimpleCapからの呼び出て連携させたところ。

一段落したところでソースを公開する予定。

2010年4月3日土曜日

Twitpicアップローダ開発(1) 開始

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

これまでの検証を元に Twitpicアップローダを作ってみる。いろいろな技術を試すにはこのAPIは仕組みが単純でちょうどいい。

名前は "twitpic.up"

イメージはこう。


INPUTは、SimpleCapなどとの連携を意識している。

画面はこんな感じ。1ファイル毎に1ウィンドウが立ち上がるイメージ。


利用するライブラリは次の通り。

TBXML V1.3 - The very fast, light-weight XML parser for Apple iPad, iPhone & iPod Touch

ASIHTTPRequest Documentation - All-Seeing Interactive


- - - -
なお既に Mac用のアップローダは存在する。
Download TwitPic Uploader 1.0 - Free Mac application for uploading images to TwitPic - Softpedia
参考まで。

2010年4月2日金曜日

Keychain Services 調査 (25) Keychain Item を削除する

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

(前回)Cocoaの日々: Keychain Services 調査 (24) twitpic へ画像をアップロード(その4)レスポンスXMLを処理

登録してある Keychain Item を削除する。削除には SecKeychainItemDelete を使う。
Mac Dev Center: Keychain Services Reference - SecKeychainItemDelete

-[AccountManager deleteLoginAccoun] に実装する。

AccountManager.m

- (BOOL)deleteLoginAccount:(LoginAccount*)loginAccount
{
OSStatus status;
const char *serviceNameUTF8 = [loginAccount.serviceName UTF8String];
const char *loginIdUTF8 = [loginAccount.loginId UTF8String];
SecKeychainItemRef itemRef = nil;

status = SecKeychainFindGenericPassword(NULL,
strlen(serviceNameUTF8),
serviceNameUTF8,
strlen(loginIdUTF8),
loginIdUTF8,
NULL,
NULL,
&itemRef);
if (status == errSecSuccess) {
status = SecKeychainItemDelete(itemRef);
if (status == errSecSuccess) {
return YES;
} else {
NSLog(@"ERROR:SecKeychainItemDelete");
return NO;
}
} else {
NSLog(@"ERROR:SecKeychainFindGenericPassword:%d", status);
return NO;
}

if (itemRef) {
CFRelease(itemRef);
}
}

SecKeychainFindGenericPassword で SecKeychainItemRef を取得し、それを SecKeychainItemDelete へ渡す。SecKeychainItemRef は最後に CFRelease するのを忘れずに。

組み込んで実行してみる。既に Keychain Item が登録された状態から始める。
アプリを起動し delete ボタンを押して -[AccountManager deleteLoginAccount:] を呼び出す。

すると消えた。

- - - -
ここまでで Keychain の単純な使い方はわかった(寄り道が多かったが)。
次回からは Twitpic アップローダの制作に入る。一通りちゃんと動くものを使って公開する予定。

2010年4月1日木曜日

Keychain Services 調査 (24) twitpic へ画像をアップロード(その4)レスポンスXMLを処理

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

前回試した TBXML を twitpic アップローダサンプルへ組み込んでみた。
XML解析部はおおまか前回と同じなので詳しくはソースを見て欲しい。
KeychainSample2 at 2010-04-01 from xcatsan's SampleCode - GitHub

まずは認証成功のケース。

正しい Username/Password を入れるとログに成功したレスポンスが出力される。

KeychainSample2[2412:80f] result=1, {
    mediaid = 1caykw;
    mediaurl = "http://twitpic.com/1caykw";
    statusid = 11403125595;
    userid = 125498948;
}


出た。

次にわざとパスワードを間違えてみる。

KeychainSample2[2962:80f] result=0, {
    errorCode = 1001;
    errorMsg = "Invalid twitter username or password";
}


サーバからのエラー番号とメッセージが取得できた。

- - - -
Twitpic のレスポンスの結果ステータス属性は成功の場合は status で,失敗の時は stat となっているので注意。

2010年3月29日月曜日

Keychain Services 調査 (23) twitpic へ画像をアップロード(その3)画像をアップロード

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

(前回)Cocoaの日々: Keychain Services 調査 (22) twitpic へ画像をアップロード(その2)asi-http-request を使う

いよいよ twitpic へ画像をアップロードする。今回は sample.jpg を用意してこれをアップロードしてみよう。


asi-http-request ではフォームデータ送信用のクラス ASIFormDataRequest が用意されており、これを使うと multipart/form-data なリクエストも数行で送信することができる。使い方は How to use it の中の Sending data with POST or PUT requests に書かれている。

ASIHTTPRequest example code - All-Seeing Interactive

ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url]; 
[request setPostValue:@"Ben" forKey:@"first_name"]; 
[request setPostValue:@"Copsey" forKey:@"last_name"]; 
[request setFile:@"/Users/ben/Desktop/ben.jpg" forKey:@"photo"];

やってみよう。sample.jpg を xcodeのプロジェクトへ追加した後、下のコードを書く。

NSURL *url = [NSURL URLWithString:@"http://twitpic.com/api/uploadAndPost"];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];

[request setPostValue:loginAccount.loginId forKey:@"username"];
[request setPostValue:loginAccount.password forKey:@"password"];

NSString* filepath = [[NSBundle mainBundle] pathForImageResource:@"sample"];
NSLog(@"filepath=%@", filepath);

[request setFile:filepath forKey:@"media"];
[request setPostValue:@"Hello twitpic!" forKey:@"message"];
[request startSynchronous];

NSError* error = [request error];
if (!error) {
NSString* response = [request responseString];
NSLog(@"%@", response);
} else {
NSLog(@"error: %@", error);
}


実行してみよう。ID, パスワードを入力する。
Login を押すとリクエストが飛ぶ。ログを見るとうまく行っているようだ。

KeychainSample2[3461:80f] updated keychain item
KeychainSample2[3461:80f] filepath=/Users/hashi/development/SampleCode/KeychainSample2/build/Debug/KeychainSample2.app/Contents/Resources/sample.jpg
KeychainSample2[3461:80f]
 111...
 1254....
 1bh2pu
 http://twitpic.com/1bh2pu



Twitpic のページを表示してみる。

出た。ちょっとうれしい。

2010年3月27日土曜日

Keychain Services 調査 (22) twitpic へ画像をアップロード(その2)asi-http-request を使う

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

(前回)Cocoaの日々: Keychain Services 調査 (21) twitpic へ画像をアップロード(その1)調査

asi-http-request ライブラリを使うことにする。まずはサンプルプログラムへライブラリを組み込んで動作確認をやってみる。

組み込み方法はサポートページに図入りで詳しく書いてある。
How to use ASIHTTPRequest in your projects - All-Seeing Interactive


まずライブラリのソースコードをダウンロードする。
Downloads for pokeb's asi-http-request - GitHub

今回は v1.6.1 の zip を落としてみた。解凍すると Xcodeのプロジェクト一式が入っている。

Classes 内のファイル(11個)をサンプルプログラムのプロジェクトへコピーする。
次にサンプルプログラムのプロジェクトへフレームワークと動的ライブラリを追加する。追加するのは次の2つ。



Mac OS X の場合はこれで終わり。iPhone の場合はもういくつかのファイルを追加擦る必要がある。


動作確認で google.com のページを GET してみよう。サポートページの "How to use it" を参考に同期リクエストを投げてみる。
ASIHTTPRequest example code - All-Seeing Interactive


NSURL *url = [NSURL URLWithString:@"http://www.google.com/"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request startSynchronous];
NSError* error = [request error];
if (!error) {
NSString* response = [request responseString];
NSLog(@"%@", response);
} else {
NSLog(@"error: %@", error);
}

実行結果



(続く)

2010年3月26日金曜日

Keychain Services 調査 (21) twitpic へ画像をアップロード(その1)調査

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

(前回)Cocoaの日々: Keychain Services 調査 (20) 認証フロー(REST向け)Keychain item 更新

さて今回からこれまで作ってきた keychain servicesを使った認証実装を使い、 twitpic へ画像をアップロードするサンプルアプリを作ってみる。

まずは調査から。

Twitpic - Share photos on Twitter

twitpic では簡単な API が用意されていて、POSTで画像をアップロードすると XMLでレスポンスが返ってくる。アップロードには multipart/form-data を使う。


METHOD: http://twitpic.com/api/uploadAndPost


Use this method to upload an image to TwitPic and to send it as a status update to Twitter.


Fields to post in
(post data should be formatted as multipart/form-data):
- media (required) - Binary image data
- username (required) - Twitter username
- password (required) - Twitter password
- message (optional) - Message to post to twitter. The URL of the image is automatically added.


Sample response:

 1111
 11111
 abc123
 http://twitpic.com/abc123
このAPIを使うと twitter への投稿も一緒にやってくれる。なお http だと username / password が盗聴/改ざんされる危険があるのが気になる。


Objective-C の実装についてはいくつか情報が見つかった。

iPhoneアプリからTwitpicに画像をアップロードする方法 - Tomute’s Notes

Using TwitPic API from ObjectiveC/iPhone - Stack Overflow

どちらも ASIHTTPRequest というライブラリを使っているようだ。

pokeb's asi-http-request at master - GitHub

READMEを引用すると:
ASIHTTPRequest is an easy to use wrapper around the CFNetwork API that makes some of the more tedious aspects of communicating with web servers easier. It is written in Objective-C and works in both Mac OS X and iPhone applications.
It is suitable performing basic HTTP requests and interacting with REST-based services (GET / POST / PUT / DELETE). The included ASIFormDataRequest subclass makes it easy to submit POST data and files using multipart/form-data.

今回 multipart/form-data で POST するので、このライブラリを使うのが便利そうだ。

(続く)