PageRenderTime 44ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/GoogleReaderNotifier/GoogleReaderNotifier.ReaderAPI/GoogleReader.cs

http://reader-notifier-mod.googlecode.com/
C# | 417 lines | 330 code | 72 blank | 15 comment | 49 complexity | 0efb98a3ff37e0a52a9a915ffa91b78e MD5 | raw file
  1. using System;
  2. using System.Net;
  3. using System.Text;
  4. using System.IO;
  5. using System.Xml;
  6. using System.Collections.Generic;
  7. using GoogleReaderNotifier.ReaderAPI.Data;
  8. using System.Reflection;
  9. using System.Windows.Forms;
  10. using System.Drawing;
  11. namespace GoogleReaderNotifier.ReaderAPI
  12. {
  13. /// <summary>
  14. /// Summary description for GoogleReader.
  15. /// </summary>
  16. public class GoogleReader
  17. {
  18. #region Private variables
  19. private CookieCollection _Cookies = new CookieCollection();
  20. private CookieContainer _cookiesContainer = new CookieContainer();
  21. private bool _loggedIn = false;
  22. private string[] _loginAuth;
  23. private XmlDocument xdocAll;
  24. #endregion
  25. #region Public variables
  26. public string LoginError = "";
  27. public string[] ProxyUser = new string[3];
  28. #endregion
  29. public bool LoggedIn
  30. {
  31. get { return _loggedIn; }
  32. }
  33. #region Application Code
  34. // https://www.google.com/reader/atom/user/-/state/com.google/reading-list // get full feed of items
  35. public string Login(string username, string password)
  36. {
  37. _loggedIn = false;
  38. LoginError = "";
  39. HttpWebRequest req = CreateRequest("https://www.google.com/accounts/ClientLogin?service=reader");
  40. string exc = PostLoginForm(req, String.Format("accountType=GOOGLE&Email={0}&Passwd={1}&service=reader&source=GRaiN-Notifier-" + Assembly.GetExecutingAssembly().GetName().Version, Uri.EscapeDataString(username), Uri.EscapeDataString(password)));
  41. if (exc.IndexOf("System.Net.WebException") != -1)
  42. {
  43. LoginError += exc + "\r\n";
  44. if (ProxyUser[0] == "request")
  45. return "ProxyAuthRequired";
  46. return "CONNECT_ERROR";
  47. }
  48. try
  49. {
  50. string _helper = GetResponseString(req);
  51. _loggedIn = (_helper.IndexOf("error", StringComparison.OrdinalIgnoreCase) == -1) && (_helper.IndexOf("auth", StringComparison.OrdinalIgnoreCase) != -1);
  52. if (_loggedIn == true)
  53. {
  54. _loginAuth = _helper.Split('\n');
  55. foreach (string st in _loginAuth)
  56. {
  57. if (st != string.Empty)
  58. {
  59. string[] coo = st.Split('=');
  60. if (coo[0] == "SID")
  61. _cookiesContainer.Add(new Cookie(coo[0], coo[1], "/", ".google.com"));
  62. }
  63. }
  64. }
  65. else
  66. {
  67. LoginError += _helper + "\r\n";
  68. }
  69. }
  70. catch (Exception ex)
  71. {
  72. _loggedIn = false;
  73. string _exc = ex.ToString();
  74. LoginError += "Exception in GetResponseString. \r\n" + _exc + "\r\n";
  75. }
  76. if (!_loggedIn)
  77. return "AUTH_ERROR";
  78. else
  79. LoginError = string.Empty;
  80. return string.Empty;
  81. }
  82. private delegate string LocateUnreadItemIdentifierDelegate(string identifierSource);
  83. private string LocateFeedIdentifier(string identifierSource)
  84. {
  85. return identifierSource.Substring(identifierSource.LastIndexOf("/http") + 1);
  86. }
  87. private string LocateTagIdentifier(string identifierSource)
  88. {
  89. return identifierSource.Substring(identifierSource.LastIndexOf("/label/") + "/label/".Length);
  90. }
  91. public bool CollectUnreadFeeds(UnreadItemCollection unreadFeeds)
  92. {
  93. System.Diagnostics.Debug.Assert(unreadFeeds != null, "unreadFeeds must be assigned.");
  94. return CollectUnreadItems(unreadFeeds, null, null);
  95. }
  96. public bool CollectUnreadTags(UnreadItemCollection unreadTags, List<string> tagFilterList)
  97. {
  98. System.Diagnostics.Debug.Assert(unreadTags != null, "unreadTags must be assigned.");
  99. return CollectUnreadItems(null, unreadTags, tagFilterList);
  100. }
  101. public void CollectTags(List<String> tags)
  102. {
  103. System.Diagnostics.Debug.Assert(tags != null, "tags must be assigned.");
  104. if (!LoggedIn)
  105. {
  106. throw new Exception("Must be logged in to collect tags");
  107. }
  108. XmlDocument xdoc;
  109. string identifier;
  110. xdoc = this.GetTagListXMLDocument();
  111. tags.Clear();
  112. foreach (XmlNode node in xdoc.SelectNodes("//object/string[contains(.,'/label/') and contains(.,'user/')]"))
  113. {
  114. identifier = LocateTagIdentifier(node.InnerText);
  115. tags.Add(identifier);
  116. }
  117. }
  118. public bool CollectUnreadItems(UnreadItemCollection unreadFeeds, UnreadItemCollection unreadTags, List<string> identifierFilterList)
  119. {
  120. bool result = true;
  121. //int unreadCount;
  122. XmlDocument xdoc;
  123. result = LoggedIn;
  124. if (result)
  125. {
  126. xdoc = this.GetAllUnreadCountsXMLDocument();
  127. xdocAll = this.GetSubscriptionListXMLDocument();
  128. // Collect feed information
  129. if (unreadFeeds != null)
  130. {
  131. unreadFeeds.Clear();
  132. CollectUnreadItemsBySelectedNodes(xdoc, "//object/string[contains(.,'user/') and contains(.,'/state/com.google/reading-list')]", unreadFeeds, LocateFeedIdentifier, null);
  133. }
  134. // Collect tag information
  135. if (unreadTags != null)
  136. {
  137. unreadTags.Clear();
  138. CollectUnreadItemsBySelectedNodes(xdoc, "//object/string[contains(.,'/label/') and contains(.,'user/')]", unreadTags, LocateTagIdentifier, identifierFilterList);
  139. }
  140. }
  141. return result;
  142. }
  143. private void CollectUnreadItemsBySelectedNodes(XmlDocument xdoc, string nodeSelection, UnreadItemCollection unreadItems, LocateUnreadItemIdentifierDelegate locateIdentifierDelegate, List<string> identifierFilterList)
  144. {
  145. int unreadCount;
  146. UnreadItem unreadItem;
  147. string identifier;
  148. string feedName;
  149. bool addToList;
  150. foreach (XmlNode node in xdoc.SelectNodes(nodeSelection))
  151. {
  152. unreadCount = Convert.ToInt32(node.ParentNode.SelectSingleNode("number").InnerText);
  153. identifier = locateIdentifierDelegate(node.InnerText);
  154. feedName = GetFeedNameById(identifier);
  155. addToList = (unreadCount > 0) && ((identifierFilterList == null) || identifierFilterList.Contains(identifier));
  156. if (addToList)
  157. {
  158. unreadItem = new UnreadItem();
  159. unreadItem.Identifier = identifier;
  160. unreadItem.FeedName = feedName;
  161. unreadItem.ArticleCount = unreadCount;
  162. unreadItems.Add(unreadItem);
  163. }
  164. }
  165. }
  166. private XmlDocument GetAllUnreadCountsXMLDocument()
  167. {
  168. string url = "https://www.google.com/reader/api/0/unread-count?all=true";
  169. string theXml = GetResponseString(CreateRequest(url));
  170. XmlDocument xdoc = new XmlDocument();
  171. xdoc.LoadXml(theXml);
  172. return xdoc;
  173. }
  174. private XmlDocument GetTagListXMLDocument()
  175. {
  176. string url = "https://www.google.com/reader/api/0/tag/list";
  177. string theXml = GetResponseString(CreateRequest(url));
  178. XmlDocument xdoc = new XmlDocument();
  179. xdoc.LoadXml(theXml);
  180. return xdoc;
  181. }
  182. private XmlDocument GetSubscriptionListXMLDocument()
  183. {
  184. string url = "https://www.google.com/reader/api/0/subscription/list";
  185. string theXml = GetResponseString(CreateRequest(url));
  186. XmlDocument xdoc = new XmlDocument();
  187. xdoc.LoadXml(theXml);
  188. return xdoc;
  189. }
  190. private string GetFeedNameById(string feedId)
  191. {
  192. try
  193. {
  194. XmlNode node = xdocAll.SelectSingleNode("//string[@name='id' and .='feed/" + feedId + "']/../string[@name='title']");
  195. if (node != null)
  196. return node.InnerText;
  197. else
  198. return " - ";
  199. }
  200. catch{
  201. return " - ";
  202. }
  203. }
  204. #endregion
  205. #region HTTP Functions
  206. public string GetResponseStrEx(String url)
  207. {
  208. string xstr = GetResponseString(CreateRequest(url));
  209. return xstr;
  210. }
  211. private string GetResponseString(HttpWebRequest req)
  212. {
  213. string responseString = null;
  214. try
  215. {
  216. HttpWebResponse res = (HttpWebResponse)req.GetResponse();
  217. res.Cookies = req.CookieContainer.GetCookies(req.RequestUri);
  218. _Cookies.Add(res.Cookies);
  219. using (StreamReader read = new StreamReader(res.GetResponseStream()))
  220. {
  221. responseString = read.ReadToEnd();
  222. }
  223. res.Close();
  224. //_currentHTML = responseString;
  225. }
  226. catch (WebException ex)
  227. {
  228. using (StreamReader read = new StreamReader(ex.Response.GetResponseStream()))
  229. {
  230. responseString = read.ReadToEnd();
  231. }
  232. //res.Close();
  233. string exc = ex.ToString();
  234. LoginError += responseString+"\r\n" +exc + "\r\n";
  235. }
  236. catch (Exception ex)
  237. {
  238. string exc = ex.ToString();
  239. LoginError += exc + "\r\n";
  240. }
  241. return responseString;
  242. }
  243. private string PostLoginForm(HttpWebRequest req, string p)
  244. {
  245. string exc = string.Empty;
  246. req.ContentType = "application/x-www-form-urlencoded";
  247. req.Method = "POST";
  248. //req.Referer = _currentURL;
  249. byte[] b = Encoding.UTF8.GetBytes(p);
  250. req.ContentLength = b.Length;
  251. try
  252. {
  253. using (Stream s = req.GetRequestStream())
  254. {
  255. s.Write(b, 0, b.Length);
  256. s.Close();
  257. }
  258. }
  259. catch (Exception ex)
  260. {
  261. exc = ex.ToString();
  262. if (ex.GetType().Name == "WebException" && exc.IndexOf("(407)") != -1 && ProxyUser[0] !="missing")
  263. {
  264. ProxyUser[0] = "request";
  265. }
  266. }
  267. return exc;
  268. }
  269. private HttpWebRequest CreateRequest(string url)
  270. {
  271. HttpWebRequest req = WebRequest.Create(url) as HttpWebRequest;
  272. //WebProxy defaultProxy = WebProxy.GetDefaultProxy();
  273. IWebProxy defaultProxy = HttpWebRequest.GetSystemWebProxy();
  274. req.Proxy = defaultProxy; // if we wanted to disable proxying, can be done by setting to null I think
  275. if (ProxyUser[0] == "request")
  276. {
  277. DialogResult result = GetProxyUser(ref ProxyUser[1], ref ProxyUser[2]);
  278. if (result == DialogResult.OK && ProxyUser[1] != "" && ProxyUser[2] != "")
  279. {
  280. ProxyUser[0] = "exist";
  281. }
  282. else
  283. {
  284. ProxyUser[0] = "missing";
  285. }
  286. }
  287. if (ProxyUser[0] == "exist" && ProxyUser[1] != "" && ProxyUser[2] != "")
  288. {
  289. req.Proxy.Credentials = new NetworkCredential(ProxyUser[1], ProxyUser[2]);
  290. }
  291. //req.Proxy = null;
  292. //req.UserAgent = _user.UserAgent;
  293. req.UserAgent = "GRaiN/" + Assembly.GetExecutingAssembly().GetName().Version + "(Google Reader Notifier for Windows)";
  294. req.Referer = "http://yoni-zaf.appspot.com/notifier?version=" + Assembly.GetExecutingAssembly().GetName().Version;
  295. req.CookieContainer = _cookiesContainer;
  296. if (_loggedIn)
  297. req.Headers.Add("Authorization", "GoogleLogin auth=" + _loginAuth[2].Split('=')[1]);
  298. //req.Referer = _currentURL; // set the referring url properly to appear as a regular browser
  299. //_currentURL = url; // set the current url so the next request will have the right referring url ( might not work for sub pages )
  300. return req;
  301. }
  302. #endregion
  303. public static DialogResult GetProxyUser(ref string userName, ref string passWord)
  304. {
  305. Form form = new Form();
  306. Label label = new Label();
  307. TextBox textBoxUser = new TextBox();
  308. TextBox textBoxPass = new TextBox();
  309. Button buttonOk = new Button();
  310. Button buttonCancel = new Button();
  311. form.Text = "GRaiN";
  312. label.Text = "Proxy require username and password:";
  313. textBoxUser.Text = userName;
  314. textBoxPass.Text = passWord;
  315. textBoxPass.UseSystemPasswordChar = true;
  316. buttonOk.Text = "OK";
  317. buttonCancel.Text = "Cancel";
  318. buttonOk.DialogResult = DialogResult.OK;
  319. buttonCancel.DialogResult = DialogResult.Cancel;
  320. label.SetBounds(9, 20, 372, 13);
  321. textBoxUser.SetBounds(12, 40, 372, 20);
  322. textBoxPass.SetBounds(12, 65, 372, 20);
  323. buttonOk.SetBounds(228, 92, 75, 23);
  324. buttonCancel.SetBounds(309, 92, 75, 23);
  325. label.AutoSize = true;
  326. textBoxUser.Anchor = textBoxUser.Anchor | AnchorStyles.Right;
  327. textBoxPass.Anchor = textBoxPass.Anchor | AnchorStyles.Right;
  328. buttonOk.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
  329. buttonCancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
  330. form.ClientSize = new Size(396, 125);
  331. form.Controls.AddRange(new Control[] { label, textBoxUser, textBoxPass, buttonOk, buttonCancel });
  332. form.ClientSize = new Size(Math.Max(300, label.Right + 10), form.ClientSize.Height);
  333. form.FormBorderStyle = FormBorderStyle.FixedDialog;
  334. form.StartPosition = FormStartPosition.CenterScreen;
  335. form.MinimizeBox = false;
  336. form.MaximizeBox = false;
  337. form.AcceptButton = buttonOk;
  338. form.CancelButton = buttonCancel;
  339. DialogResult dialogResult = form.ShowDialog();
  340. userName = textBoxUser.Text;
  341. passWord = textBoxPass.Text;
  342. return dialogResult;
  343. }
  344. }
  345. }