Post to Hatena-Diary / Hatena-Fotolife with Atom Publishing Protocol
Post to Hatena-Diary / Hatena-Fotolife with Atom Publishing Protocol
// AtomAPI での投稿は既に「はてなダイアリーにAtomPubで投稿する - INOHILOG」で実現していたんですが、今回ははてなfotolifeにAtomPubで投稿です。
とりあえず今回はC#で出来ておしまいでは無いので、説明はいつか書く。
このコードでアップロードされた画像 -> f:id:InoHiro:20090404041804p:image - InoHiro's fotolife
using System; using System.Text; using System.Net; using System.IO; using System.Security.Cryptography; namespace HatenaFotolife_AtomPub { class Program { static void Main( string[] args ) { string username = "InoHiro"; string password = "password"; string title = "img_title"; string imgDataPath = @"C:\titleimg.png"; string folderName = "Development"; string generator = "Console_Uploader"; Console.WriteLine( Post( username, password, title, imgDataPath, folderName, generator ) ); Console.ReadKey(); } private static string Post( string username, string password, string title, string imgDataPath, string folderName, string generator ) { string header = CreateWsseHeader( username, password ); // Base64 Encoding FileStream fileStm = new FileStream( imgDataPath, FileMode.Open, FileAccess.Read ); byte[] bytes = new byte[fileStm.Length]; int readBytes = fileStm.Read( bytes, 0, ( int )fileStm.Length ); fileStm.Close(); string encodedImgFile = System.Convert.ToBase64String( bytes ); StringBuilder xml = new StringBuilder(); xml.Append( "<?xml version=\"1.0\" encoding=\"utf-8\"?>" ); xml.Append( "<entry xmlns=\"http://purl.org/atom/ns#\">" ); xml.Append( String.Format( "<title>{0}</title>", title ) ); xml.Append( String.Format( "<content type=\"image/png\" mode=\"base64\">{0}</content>", encodedImgFile ) ); xml.Append( String.Format( "<dc:subject>{0}</dc:subject>", folderName ) ); xml.Append( String.Format( "<generator>{0}</generator></entry>", generator ) ); HttpWebRequest request = ( HttpWebRequest )WebRequest.Create( "http://f.hatena.ne.jp/atom/post" ); request.Method = "POST"; request.Headers.Add( "X-WSSE", header ); request.ContentType = "application/x.atom+xml"; Stream requestream = request.GetRequestStream(); byte[] data = Encoding.UTF8.GetBytes( xml.ToString() ); requestream.Write( data, 0, data.Length ); requestream.Close(); HttpWebResponse response = ( HttpWebResponse )request.GetResponse(); if( response.StatusCode == HttpStatusCode.Created ) return "created!"; else return "failed..."; } static string CreateWsseHeader( string username, string password ) { // HTTPリクエスト毎に生成するセキュリティ・トークン(ランダム文字列) byte[] b_nonce = new byte[8]; Random rand = new Random(); rand.NextBytes( b_nonce ); // nonce 生成時の日時 string created = DateTime.Now.ToUniversalTime().ToString( "o" ); byte[] b_created = Encoding.UTF8.GetBytes( created ); byte[] b_password = Encoding.UTF8.GetBytes( password ); SHA1Managed sh1 = new SHA1Managed(); sh1.Initialize(); // Nonce, Created, パスワードを連結 byte[] origin = new byte[b_nonce.Length + b_created.Length + b_password.Length]; Array.Copy( b_nonce, 0, origin, 0, b_nonce.Length ); Array.Copy( b_created, 0, origin, b_nonce.Length, b_created.Length ); Array.Copy( b_password, 0, origin, b_nonce.Length + b_created.Length, b_password.Length ); // ハッシュ値を生成 byte[] passwordDigest = sh1.ComputeHash( origin ); string header = string.Format( "UsernameToken Username=\"{0}\", PasswordDigest=\"{1}\", Nonce=\"{2}\", Created=\"{3}\"", username, Convert.ToBase64String( passwordDigest ), Convert.ToBase64String( b_nonce ), created ); return header; } } }