PageRenderTime 50ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/HatenaPhotLife/HatenaPhotLifeClient.cs

https://bitbucket.org/ugaya40/instant-image-uploader
C# | 124 lines | 106 code | 18 blank | 0 comment | 3 complexity | cea1659afb418bd4466a8f69bcda1f26 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Reactive;
  6. using System.Reactive.Linq;
  7. using System.Security.Cryptography;
  8. using System.Net;
  9. using System.IO;
  10. using System.Xml.Linq;
  11. using System.Xml;
  12. namespace HatenaPhotLife
  13. {
  14. public class HatenaPhotLifeClient
  15. {
  16. private string _userId;
  17. private string _password;
  18. public HatenaPhotLifeClient(string userId, string password)
  19. {
  20. _userId = userId;
  21. _password = password;
  22. }
  23. public IObservable<string> UploadAsObservable(string imageFilePath,string folder)
  24. {
  25. XNamespace ns = "http://purl.org/atom/ns#";
  26. return Observable.Defer(() =>
  27. {
  28. var request = (HttpWebRequest)HttpWebRequest.Create("http://f.hatena.ne.jp/atom");
  29. request.Headers.Add("X-WSSE", GetWSSEHeader(_userId, _password));
  30. request.ContentType = "application/x.atom+xml";
  31. return Observable.FromAsyncPattern<WebResponse>(request.BeginGetResponse, request.EndGetResponse)();
  32. })
  33. .GetResponseAsXElement()
  34. .Select(responseXElement =>
  35. (string)responseXElement.Descendants(ns + "link")
  36. .Where(element => (string)element.Attribute("rel") == "service.post")
  37. .First()
  38. .Attribute("href"))
  39. .SelectMany(url => Observable.Defer(() =>
  40. {
  41. var request = (HttpWebRequest)HttpWebRequest.Create(url);
  42. request.Method = "POST";
  43. request.Headers.Add("X-WSSE", GetWSSEHeader(_userId, _password));
  44. request.ContentType = "application/x.atom+xml";
  45. using (var requestStream = request.GetRequestStream())
  46. using (var writer = new XmlTextWriter(requestStream, Encoding.UTF8))
  47. {
  48. GenerateXml(imageFilePath,folder).WriteTo(writer);
  49. }
  50. return Observable.FromAsyncPattern<WebResponse>(request.BeginGetResponse, request.EndGetResponse)();
  51. }))
  52. .GetResponseAsXElement()
  53. .Select(responseXElement => responseXElement.Descendants(ns + "link").Where(element => (string)element.Attribute("rel") == "alternate"))
  54. .Select(elements => (string)elements.First().Attribute("href"));
  55. }
  56. private static string GetWSSEHeader(string userid, string password)
  57. {
  58. var createdAtTime = DateTime.Now.ToUniversalTime().ToString("s");
  59. var nonce = new byte[40];
  60. new Random().NextBytes(nonce);
  61. string passwordDigest;
  62. var digestSource = nonce.Concat(createdAtTime.GetUTF8Bytes()).Concat(password.GetUTF8Bytes());
  63. using (SHA1Managed sha = new SHA1Managed())
  64. {
  65. passwordDigest = Convert.ToBase64String(sha.ComputeHash(digestSource.ToArray()));
  66. }
  67. return string.Format(@"UsernameToken Username=""{0}"", PasswordDigest=""{1}"", Nonce=""{2}"", Created=""{3}""",
  68. userid,
  69. passwordDigest,
  70. Convert.ToBase64String(nonce),
  71. createdAtTime
  72. );
  73. }
  74. private static XElement GenerateXml(string imageFilePath,string folderName)
  75. {
  76. XNamespace ns = "http://purl.org/atom/ns#";
  77. XNamespace dc = "http://purl.org/dc/elements/1.1/";
  78. var root = new XElement(ns + "entry", new XAttribute(XNamespace.Xmlns + "dc", dc));
  79. var contentElement = new XElement("content", Convert.ToBase64String(File.ReadAllBytes(imageFilePath)));
  80. contentElement.SetAttributeValue("mode", "Base64");
  81. contentElement.SetAttributeValue("type", "image/png");
  82. root.Add(contentElement);
  83. if (!string.IsNullOrEmpty(folderName))
  84. {
  85. var folderElement = new XElement(dc + "subject", folderName);
  86. root.Add(folderElement);
  87. }
  88. var toolElement = new XElement("generator", "InstantImageUploader");
  89. root.Add(toolElement);
  90. return root;
  91. }
  92. }
  93. public static class CommonExtension
  94. {
  95. public static byte[] GetUTF8Bytes(this string source)
  96. {
  97. return Encoding.UTF8.GetBytes(source);
  98. }
  99. public static IObservable<XElement> GetResponseAsXElement(this IObservable<WebResponse> source)
  100. {
  101. return source.Select(response => response.GetResponseStream())
  102. .Select(stream => new StreamReader(stream).ReadToEnd())
  103. .Select(responseText => XElement.Parse(responseText));
  104. }
  105. }
  106. }