そういえばブックマーク関連で。
はてなブックマークでは、Atomフィードを配布しています。そして、これを応用してブラウザ外からファイルを送受信したり、リストを得たりする――いわゆる「はてなブックマークAtomAPI」が使用できます。これを使えば、学校と家で同じブックマークを共有出来る。プライベートなブックマークについても、サブアカウントを作ってプライベートモードのブックマークを使えばいいことだし。
ということで、AtomAPIについて調査。日本にはAtomAPIの情報は少ないです、探し方が悪いのか。Perlなどのコードは見つかりましたが、XML::Atom::Feedという、未知のライブラリを使われてるので移植は難しそう。
その後、英語のページでは一応見つかりました。とはいえ、AtomAPI?という、これまた未知のクラスが使われており、サンプルとするのは難しいです(ソースを見たところusingにはフレームワークの名前空間しか使われていないし、独自クラスというわけではないようだし…)。
ただ、とりあえずこれだけでも、表示するまでには至りました。HttpWebRequest関連も全くだったし、結構ややこしいです(>_<)
WCCS認証周りは怪しいなあ、とりあえず見よう見まねでやってみたものの、これでうまくいくかどうか不安。上のサンプルコードではこれまた未知のクラスが使われていたようですし。認証しようとして失敗したら、403でも返ってくるのかと思ったんですが、そうではないみたい。
でもちらっと見たときのAjaxのリクエストコードもこんな感じだったし。このあたりから慣れておかないといけないんだろうなあ。
// 認証用クラス(参照変数にnullを指定したいがためにクラスにした) public class AuthorizeKey { public string Username; public string Password; public AuthorizeKey(string username, string password) { this.Username = username; this.Password = password; } public string GetWSSEString() { System.Security.Cryptography.SHA1 sha1 = new System.Security.Cryptography.SHA1CryptoServiceProvider(); string nonce = Convert.ToBase64String( sha1.ComputeHash(Encoding.Default.GetBytes (DateTime.Now.ToString()))); string created = DateTime.Now.ToString("g"); byte[] pDigest = sha1.ComputeHash(Encoding.Default.GetBytes(nonce + created + Password)); return string.Format("UsernameToken Username=\"{0}\", " + "PasswordDigest=\"{1}\", " + "Nonce=\"{2}\", Created=\"{3}\"", Username, Convert.ToBase64String(pDigest), nonce, created); } }
中略
public static string LoadFromURL(string url, AuthorizeKey authorize, IBookmarkList feedList) { string nextURL = url; string title = ""; do { // HTTP GET HttpWebRequest request = (HttpWebRequest)WebRequest.Create(nextURL); request.ContentType = "application/atom+xml"; if(authorize != null) request.Headers.Add("X-WSSE", authorize.GetWSSEString()); request.Headers.Add("UserAgent", typeof(AtomFeed).FullName); request.Method = "GET"; HttpWebResponse responce = (HttpWebResponse)request.GetResponse(); if*1; nextURL = ""; // ドキュメント解析 System.IO.StreamReader reader = new System.IO.StreamReader(responce.GetResponseStream()); try { XmlDocument doc = new XmlDocument(); doc.LoadXml(reader.ReadToEnd()); foreach(XmlElement elm in doc["feed"]) { if(elm.Name == "title") title = elm.InnerText; if(elm.Name == "link" && elm.Attributes["rel"].Value == "next") nextURL = elm.Attributes["href"].Value; if(elm.Name == "entry") { // entryの取得 IBookmark bookmark = feedList.AddBookmark(); foreach(XmlElement entryNode in elm.ChildNodes) { if(entryNode.Name == "title") bookmark.SiteName = entryNode.InnerText; if(entryNode.Name == "link" && entryNode.Attributes["rel"].Value == "related") bookmark.SiteURL = entryNode.Attributes["href"].Value; if(entryNode.Name == "summary") bookmark.Summary = entryNode.InnerText; if(entryNode.Name == "issued") bookmark.Created = DateTime.Parse(entryNode.InnerText); if(entryNode.Name == "dc:subject") bookmark.Directory += "/" + entryNode.InnerText; } } } }finally{ reader.Close(); } }while(nextURL != ""); return title; }
さて、タグの処理もしてやらなくちゃなあ、タグまわりはAPIが提供されてないことですし、全部自分でやらなくちゃいけないですね。
*1:int)responce.StatusCode >= 400) throw new WebException(string.Format("{0} - {1}", (int)responce.StatusCode, responce.StatusCode