そういえばブックマーク関連で。
はてなブックマークでは、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