<SubType>Code</SubType>
</Compile>
<Compile Include="Models\Hatena\BlogEntry.cs" />
+ <Compile Include="Models\Hatena\FotolifeEntry.cs" />
<Compile Include="Models\Hatena\HatenaDiary.cs" />
+ <Compile Include="Models\Hatena\HatenaFotolife.cs" />
<Compile Include="Models\Hatena\WsseAtomConnection.cs" />
<Compile Include="Models\Hatena\XmlNamespaces.cs" />
<Compile Include="Models\Model.cs" />
public class BlogEntry
{
public DateTime Edited { set; get; }
- public string BlogPage { set; get; }
+ public string BlogPageUri { set; get; }
public string Title { set; get; }
public string Html { set; get; }
public string HatenaSyntax { set; get; }
public BlogEntry(XElement xml)
{
this.Edited = DateTime.Parse(xml.Element(XmlNamespaces.AtomPub + "edited").Value);
- this.BlogPage = xml.Elements(XmlNamespaces.Atom + "link")
+ this.BlogPageUri = xml.Elements(XmlNamespaces.Atom + "link")
.Where(_ => _.Attribute("rel").Value == "alternate")
.Select(_ => _.Attribute("href").Value)
.FirstOrDefault();
--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Linq;
+using System.Text.RegularExpressions;
+
+namespace Azyobuzi.HatenaDiaryClient.Models.Hatena
+{
+ public class FotolifeEntry
+ {
+ public string Title { set; get; }
+ public string PageUri { set; get; }
+ public string Id { set; get; }
+ public DateTime Issued { set; get; }
+ public string Folder { set; get; }
+ public string ImageUri { set; get; }
+ public string ThumbnailUri { set; get; }
+ public string HatenaSyntax { set; get; }
+
+ public FotolifeEntry() { }
+ public FotolifeEntry(XElement xml, bool isRdf)
+ {
+ if (isRdf)
+ {
+ //TODO
+ }
+ else
+ {
+ this.Title = xml.Element(XmlNamespaces.Atom02Spec + "title").Value;
+ this.PageUri = xml.Elements(XmlNamespaces.Atom02Spec + "link")
+ .Where(_ => _.Attribute("rel").Value == "alternate")
+ .Select(_ => _.Attribute("href").Value)
+ .FirstOrDefault();
+ this.Id = Regex.Match(this.PageUri, @"\d+$").ToString();
+ this.Issued = DateTime.Parse(xml.Element(XmlNamespaces.Atom02Spec + "issued").Value);
+ this.Folder = xml.Element(XmlNamespaces.DublinCore + "subject").Value;
+ this.ImageUri = xml.Element(XmlNamespaces.HatenaNs + "imageurl").Value;
+ this.ThumbnailUri = xml.Element(XmlNamespaces.HatenaNs + "imageurlsmall").Value;
+ this.HatenaSyntax = xml.Element(XmlNamespaces.HatenaNs + "syntax").Value;
+ }
+ }
+ }
+}
using System.Collections.Generic;
using System.Linq;
using System.Net;
+using System.Text;
using System.Text.RegularExpressions;
using System.Xml.Linq;
var reXml = WsseAtomConnection.Post(
string.Format("http://d.hatena.ne.jp/{0}/atom/blog", this.userName),
CreatePostEntryXml(title, content, updated),
+ Encoding.UTF8,
this.userName,
this.password);
return new BlogEntry(reXml.Root)
var reXml = WsseAtomConnection.Put(
string.Format("http://d.hatena.ne.jp/{0}/atom/blog/{1}", this.userName, dateId),
CreatePostEntryXml(title, content, updated),
+ Encoding.UTF8,
this.userName,
this.password);
return new BlogEntry(reXml.Root)
var reXml = WsseAtomConnection.Post(
string.Format("http://d.hatena.ne.jp/{0}/atom/draft", this.userName),
CreatePostEntryXml(title, content, updated),
+ Encoding.UTF8,
this.userName,
this.password);
return new BlogEntry(reXml.Root)
var reXml = WsseAtomConnection.Put(
string.Format("http://d.hatena.ne.jp/{0}/atom/draft/{1}", this.userName, id),
CreatePostEntryXml(title, content, updated),
+ Encoding.UTF8,
this.userName,
this.password);
return new BlogEntry(reXml.Root)
--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO;
+using System.Xml.Linq;
+using System.Net;
+
+namespace Azyobuzi.HatenaDiaryClient.Models.Hatena
+{
+ public class HatenaFotolife
+ {
+ private string userName;
+ private string password;
+
+ public HatenaFotolife(string userName, string password)
+ {
+ this.userName = userName;
+ this.password = password;
+ }
+
+ public FotolifeEntry Upload(string title, string fileName, string folder = null)
+ {
+ string mimeType;
+ #region MIME Type判断
+ switch (Path.GetExtension(fileName).TrimStart('.').ToLower())
+ {
+ case "jpg":
+ case "jpeg":
+ mimeType = "image/jpeg";
+ break;
+ case "gif":
+ mimeType = "image/gif";
+ break;
+ case "png":
+ mimeType = "image/png";
+ break;
+ case "bmp":
+ mimeType = "image/x-bmp";
+ break;
+ case "mov":
+ mimeType = "video/quicktime";
+ break;
+ case "mpg":
+ case "mpeg":
+ case "m1v":
+ mimeType = "video/mpeg";
+ break;
+ case "wmv":
+ mimeType = "video/x-ms-wmv";
+ break;
+ case "avi":
+ mimeType = "video/avi";
+ break;
+ case "flv":
+ mimeType = "video/x-flv";
+ break;
+ case "3gp":
+ case "3gpp":
+ mimeType = "video/3gpp";
+ break;
+ case "3g2":
+ mimeType = "video/3gpp2";
+ break;
+ default:
+ throw new ArgumentException("対応してないファイルです。");
+ }
+ #endregion
+
+ var entry = new XElement(XmlNamespaces.Atom02Spec + "entry",
+ new XElement(XmlNamespaces.Atom02Spec + "title", title),
+ new XElement(XmlNamespaces.Atom02Spec + "content",
+ new XAttribute("mode", "base64"),
+ new XAttribute("type", mimeType),
+ Convert.ToBase64String(File.ReadAllBytes(fileName)))
+ );
+
+ if (!string.IsNullOrEmpty(folder))
+ entry.Add(new XElement(XmlNamespaces.DublinCore + "subject", folder));
+
+ var reXml = WsseAtomConnection.Post(
+ "http://f.hatena.ne.jp/atom/post",
+ new XDocument(entry),
+ Encoding.GetEncoding("shift_jis"),
+ this.userName,
+ this.password);
+ return new FotolifeEntry(reXml.Root, false);
+ }
+ }
+}
using System;
+using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
public static string CreateHeader(string userName, string password)
{
- var tmp = new byte[25];
- random.NextBytes(tmp);
- var nonce = Convert.ToBase64String(tmp);
- tmp = null;
+ var nonce = new byte[8];
+ random.NextBytes(nonce);
var created = DateTime.Now.ToUniversalTime().ToString("o");
var digest = Convert.ToBase64String(
new SHA1Managed().ComputeHash(
- Encoding.ASCII.GetBytes(nonce + created + password)
+ nonce.Concat(Encoding.ASCII.GetBytes(created)).Concat(Encoding.ASCII.GetBytes(password)).ToArray()
));
return string.Format(
@"X-WSSE:UsernameToken Username=""{0}"", PasswordDigest=""{1}"", Nonce=""{2}"", Created=""{3}""",
- userName, digest, nonce, created);
+ userName, digest, Convert.ToBase64String(nonce), created);
}
public static XDocument Get(string reqUri, string userName, string password)
req.GetResponse().Close();
}
- private static XDocument PostOrPut(string reqUri, string method, XDocument reqData, string userName, string password)
+ private static XDocument PostOrPut(string reqUri, string method, XDocument reqData, Encoding enc, string userName, string password)
{
var req = WebRequest.Create(reqUri);
req.Method = method;
req.Headers.Add(CreateHeader(userName, password));
- req.ContentType = "application/x.atom+xml; charset=utf-8";
- var bs = Encoding.UTF8.GetBytes(reqData.ToString());
+ req.ContentType = "application/x.atom+xml";
+ var bs = Encoding.GetEncoding("shift_jis").GetBytes(reqData.ToString());
req.ContentLength = bs.Length;
using (var stream = req.GetRequestStream())
stream.Write(bs, 0, bs.Length);
return XDocument.Load(res.GetResponseStream());
}
- public static XDocument Post(string reqUri, XDocument reqData, string userName, string password)
+ public static XDocument Post(string reqUri, XDocument reqData, Encoding enc, string userName, string password)
{
- return PostOrPut(reqUri, "POST", reqData, userName, password);
+ return PostOrPut(reqUri, "POST", reqData, enc, userName, password);
}
- public static XDocument Put(string reqUri, XDocument reqData, string userName, string password)
+ public static XDocument Put(string reqUri, XDocument reqData, Encoding enc, string userName, string password)
{
- return PostOrPut(reqUri, "PUT", reqData, userName, password);
+ return PostOrPut(reqUri, "PUT", reqData, enc, userName, password);
}
}
}
\ No newline at end of file