2011年07月01日

【iPhone SDK】アメーバブログなどにAtom APIを使ってアクセス

アプリからブログ記事を投稿したい。

仕事でそういった案件が舞い込んできました。
対象ブログサイトは「アメーバブログ」

調べてみたところ、こちらのサイトにて各ブログサイトを運営する会社ごとに仕様が異なるようですが、
大きく分けて、「XML-RPC」と「Atom API」に分かれるようです。

はてなブックマークなどのサービスも同じAtom APIで情報を取得できるようですね。
実際に解説がありました。

では、アメーバブログではどうでしょうか?
調べてみたところ、アメーバブログのAtom APIの仕様一部異なる部分があるようです。

細かく解説されているサイト様はいくつかありましたので、貼っておきます。
徒然Blog様
アメばた会議様
脱オタはぢめました様

どのサイト様もおっしゃっているように
Atom APIの通常の仕様と比較し、
パスワードの部分を一度MD5でエンコードする必要があることが異なります。

はてなブックマーク、ライブドアブログ、So-netブログなどは通常のAtom APIとなっているので、
パスワードをMD5でエンコードする必要はありません。

そしてアメーバブログのエンドポイントURLですが
公式にAtom APIですとは明記されていないようですが、
他サイトツールの連携について、明記しているヘルプ画面にて

このURL情報が掲載されています。

http://atomblog.ameba.jp/servlet/_atom/blog

ブログの情報を取得するためには上記のURLにて
X-WSSE認証をパスする必要があります。

2006年〜2010年の記事にてたくさんの方が挑戦して悩んでいらっしゃったようです。
自分も一日はまっていましたが、なんとか解決したのでメモ

文字列をエンコードするものとして
MD5、Sha1、Base64の3つの処理が必要になります。

まずはその関数を用意しましょう
Google先生で検索すると結構でてきますね
MD5とSha1はライブラリを使います。

#import <CommonCrypto/CommonDigest.h>

// MD5化して文字列で返す
- (NSString*)NSStringToMD5String: (NSString*)sourceString{
 const char *cStr = [sourceString cStringUsingEncoding: UTF8String];
 unsigned char md5_cStr[CC_MD5_DIGEST_LENGTH];
 // MD5エンコード
 CC_MD5( cStr, strlen(cStr), md5_cStr );

 // NSStringに格納
 char tmp[3];
 NSMutableString* result;
 for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++){
  tmp[0] = tmp[1] = tmp[2] = 0;
  sprintf(tmp, "%02x", md5_cStr[i]);
  [result appendString: [NSString stringWithUTF8String:tmp]];
 }
 return result;
}

// Sha1化して文字列で返す
- (NSString*)NSStringToSha1String: (NSString*)sourceString{
 const char *cStr = [sourceString cStringUsingEncoding: UTF8String];
 unsigned char sha1_cStr[CC_SHA1_DIGEST_LENGTH];
 // SHA1エンコード
 CC_SHA1( cStr, strlen(cStr), sha1_cStr );

 // NSStringに格納
 char tmp[3];
 NSMutableString* result;
 for(int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++){
  tmp[0] = tmp[1] = tmp[2] = 0;
  sprintf(tmp, "%02x", sha1_cStr[i]);
  [result appendString: [NSString stringWithUTF8String:tmp]];
 }
 return result;
}

// Sha1化してバイナリで返す
- (NSString*)NSStringToSha1String: (NSString*)sourceString{
 const char *cStr = [sourceString cStringUsingEncoding: UTF8String];
 unsigned char sha1_cStr[CC_SHA1_DIGEST_LENGTH];
 // SHA1エンコード
 CC_SHA1( cStr, strlen(cStr), sha1_cStr );
 return [NSData dataWithBytes: sha1_cStr length: CC_SHA1_DIGEST_LENGTH];
}
残るはBase64です。
こちらのサイト様のプロジェクトに入っているBase64変換処理を参考にさせていただきました。
プロジェクトに入っている「Base64EncDec」を使いましょう

さて、前準備はここまでですね。
あとはObjective-CでX-WSSEヘッダをつくってAtom APIの認証をクリアしましょう。

// ユーザー名とパスワードを入力しておきましょう
NSString* username = @"ユーザー名";
NSString* password = @"パスワード";

// パスワードをMD5にエンコード
password = [self NSStringToMD5String: password];

// Nonceを作成(ランダム生成
srand((unsigned)time(NULL));
NSString* tmp = [NSString stringWithFormat:@"%d", rand()];
NSString* nonce = [self NSStringToSha1String: tmp]; // Sha1エンコードにて固定長文字列を生成する

// createdを作成
NSDate* today = [NSDate date];
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"];
NSString* created = [dateFormatter stringFromDate: today];

// PasswordDigestを作成
NSString* tmpPasswordDigestStr = [NSString stringWithFormat: @"%@%@%@", nonce, created, password];
NSData* tmpPasswordDigestData = [self NSStringToSha1Data: tmpPasswordDigest]; // バイナリ取得
NSString* passwordDigest = [tmpPasswordDigestData stringEncodedWithBase64]; // Base64エンコード

// ヘッダ作成
NSString* nonceBase64 = [nonce stringEncodedWithBase64];
NSString* headerValue = [NSString stringWithFormat:
            @"UsernameToken Username=\"%@\", PasswordDigest=\"%@\", Nonce=\"%@\", Created=\"%@\"",
            username, passwordDigest, nonceBase64, created];

NSURL* url = [NSURL URLWithString: @"http://atomblog.ameba.jp/servlet/_atom/blog"];
NSMutableURLRequest* urlReq = [NSMutableURLRequest requestWithURL: url];
// ヘッダ情報追加
[urlReq addValue: headerValue forHTTPHeaderField: @"X-WSSE"];
[urlReq addValue: @"application/x.atom+xml" forHTTPHeaderField: @"Content-Type"];
// GET通信
[urlReq setHTTPMethod: @"GET"];

NSURLConnection* urlConnection = [NSURLConnection connectionWithRequest: urlReq delegate: self];
if(urlConnection){
 m_webData = [[NSMutableData alloc] init];
}


以上で設定終わりです。
NSURLConnectionのデリゲードが返ってくるので
受信時にデータを貯めこみましょう。
受信完了時にデータを解析して必要な情報を取り出します。

// データ受信時
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
 [m_webData appendData: data];
}

// 通信完了時
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
 NSString* xml = [[NSString alloc] initWithBytes: [m_webData mutableBytes]
                   length: [m_webData length]
                   encoding: NSUTF8StringEncoding];
 NSLog(@"XML = %@", xml);
}

ログをみて、XMLの中身が表示されていれば成功です。


【送料無料】萌え萌えブログの作り方遊び方

【送料無料】萌え萌えブログの作り方遊び方
価格:1,470円(税込、送料別)

ラベル:iPhone Xcode
posted by ヒイロ at 13:37| 福岡 ☁| Comment(0) | TrackBack(0) | プログラム | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。

この記事へのトラックバック