PageRenderTime 43ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/branches/0.15.x/src/MDownloader.Hostings/Providers/EasyShare/SiteBrowser.cs

#
C# | 248 lines | 197 code | 45 blank | 6 comment | 11 complexity | 4183f3b81dfa1ff73cc5cd49af6c73e0 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, CC-BY-SA-3.0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Text.RegularExpressions;
  7. using Html.Engine.Browsing;
  8. using Html.Engine.Domain;
  9. using Html.Engine.Domain.Core;
  10. using Html.Engine.Domain.Forms;
  11. using MDownloader.Hostings.Common;
  12. using MDownloader.Hostings.Core;
  13. using MDownloader.Hostings.Exceptions;
  14. using MDownloader.Hostings.Providers.EasyShare.Stages;
  15. using Melon.Commons.Extensions;
  16. using Html.Engine.Domain.Scripting;
  17. namespace MDownloader.Hostings.Providers.EasyShare
  18. {
  19. [HostingProvider]
  20. public sealed class SiteBrowser : HostingBase<SiteInfo>
  21. {
  22. #region Constants
  23. private static readonly string MainPage = @"http://www.easy-share.com/";
  24. private static readonly Regex GeneratedResourceRegex = new Regex("\"(?<link>http://www.easy-share.com/[0-9]+/[^\"]+)\"");
  25. private static readonly Regex DeleteLinkRegex = new Regex("http://www.easy-share.com/del/[0-9a-zA-Z]+.html");
  26. #endregion
  27. #region Overriden Members
  28. public override IHostingInfo GetInfo()
  29. {
  30. return SiteInfo.Instance;
  31. }
  32. protected override bool OnCanHandle(Uri link)
  33. {
  34. return link.Host.EndsWith("easy-share.com");
  35. }
  36. public override ResourceMetadata GetResourceMetadata(IDownloadContext context, IRetrievable target, DownloadSpecification specification)
  37. {
  38. var browser = context.CreateBrowser();
  39. this.ConfigureBrowser(browser, specification);
  40. var page = browser.NavigateTo(target.Link.ToString());
  41. this.CheckIfRemoved(page);
  42. var section = page.GetElementById("ucontent");
  43. var iName = section.GetDescendants<Literal>().First(x => x.GetOwner().ClassName == "px18 pb10");
  44. var iSize = iName.GetOwner().GetDescendants<Literal>().Last();
  45. var size = ResourceSizeHelper.FindSizeFromTheEnd(iSize.Content);
  46. var name = ResourceNameHelper.RemoveStringReferences(iName.Content);
  47. return new ResourceMetadata(name, size);
  48. }
  49. protected override ResourceData OnGetResourceData(IDownloadContext context, IRetrievable target, DownloadSpecification specification)
  50. {
  51. byte[] iCaptcha = null;
  52. string tCaptcha = null;
  53. var browser = context.CreateBrowser();
  54. this.ConfigureBrowser(browser, specification);
  55. var configuration = SiteInfo.Instance.GetConfiguration();
  56. var page = browser.NavigateTo(target.Link.ToString());
  57. // If user wants to use registered account we must log in first.
  58. if (configuration.Accounts.Preferences == AccountsSectionPart.UsagePreferences.Registered)
  59. {
  60. var account = configuration.Accounts.GetAccounts().RandomOrDefault();
  61. if (account != null)
  62. {
  63. var loginStage = new LogInStage(page);
  64. loginStage.SetCredentials(account.Username, account.Password);
  65. loginStage.LogIn(browser);
  66. }
  67. }
  68. this.CheckIfRemoved(page);
  69. this.CheckIfBusy(page);
  70. context.Wait(TimeSpan.FromSeconds(20));
  71. var tRegex = new Regex("w\\s*=\\s*'(?<seconds>[0-9]+)'");
  72. var tQuery = from script in page.GetScripts()
  73. where !String.IsNullOrEmpty(script.Content)
  74. let tMatch = tRegex.Match(script.Content)
  75. where tMatch.Success
  76. select Int32.Parse(tMatch.Groups["seconds"].Value);
  77. context.Wait(TimeSpan.FromSeconds(tQuery.FirstOrDefault()));
  78. var cRegex = new Regex("u\\s*=\\s*'(?<url>[^']+)'");
  79. var cQuery = from script in page.GetScripts()
  80. where !String.IsNullOrEmpty(script.Content)
  81. let cMatch = cRegex.Match(script.Content)
  82. where cMatch.Success
  83. select cMatch.Groups["url"].Value;
  84. var cForm = browser.NavigateToAs<Form>(cQuery.First());
  85. var cFormId = new Uri(cForm.Action.Location).Segments[4].Trim('/');
  86. var cScript = browser.NavigateToAs<ScriptElement>(cQuery.First());
  87. var hRegex = new Regex("Recaptcha\\.create\\s*\\(\\s*\"(?<id>[^\"]+)\"");
  88. var hQuery = hRegex.Match(cScript.Content).Groups["id"].Value;
  89. var gUrl = String.Format("http://www.google.com/recaptcha/api/challenge?k={0}&ajax=1&cachestop=0.03379133495216441", hQuery);
  90. var iUrl = String.Empty;
  91. var iChallenge = String.Empty;
  92. using (var resource = browser.GetResourceData(gUrl, ResourceRange.Default))
  93. {
  94. var java = resource.OpenStream().ReadStringToEnd();
  95. var regex = new Regex("challenge\\s*:\\s*'(?<id>[^']*)'");
  96. var match = regex.Match(java);
  97. iChallenge = match.Groups["id"].Value;
  98. iUrl = String.Format(@"http://api.recaptcha.net/image?c={0}", iChallenge);
  99. }
  100. using (var resource = browser.GetResourceData(iUrl, ResourceRange.Default))
  101. {
  102. iCaptcha = resource.OpenStream().ReadBytesToEnd();
  103. tCaptcha = context.Recognize(CaptchaRecognitionMode.Default, iCaptcha, new CaptchaDescriptor());
  104. }
  105. using (var resource = browser.GetResourceData(new CaptchaRequest(cForm.Action.Location, cFormId, iChallenge, tCaptcha), this.GetResourceRange(specification)))
  106. {
  107. if (!resource.IsBinaryStream())
  108. throw new BadPasscodeException(iCaptcha, tCaptcha, this.GetInfo());
  109. return new ResourceData(resource.OpenStream(), resource.Size, ResourceDataType.Binary);
  110. }
  111. }
  112. protected override Common.AccountInfo[] OnGetAvailableAccounts()
  113. {
  114. var accounts = from account in SiteInfo.Instance.GetConfiguration().Accounts.GetAccounts()
  115. select new Common.AccountInfo(account.Id, account.Username);
  116. return accounts.ToArray();
  117. }
  118. protected override UploadResult OnUploadData(IDownloadContext context, IUploadable target, UploadSpecification specification)
  119. {
  120. var browser = context.CreateBrowser(TimeSpan.FromMinutes(2));
  121. this.ConfigureBrowser(browser, specification);
  122. var configuration = SiteInfo.Instance.GetConfiguration();
  123. var uploadPage = browser.NavigateTo(SiteBrowser.MainPage);
  124. var account = configuration.Accounts.GetAccounts().FirstOrDefault(x => x.Id == target.Account);
  125. if (account != null)
  126. {
  127. var loginStage = new LogInStage(uploadPage);
  128. loginStage.SetCredentials(account.Username, account.Password);
  129. loginStage.LogIn(browser);
  130. }
  131. var uploadStage = new UploadStage(uploadPage);
  132. var form = uploadStage.SetData(target.Name, target.Description, target.Size, target.OpenDataStream());
  133. using (var result = browser.GetResourceData(form, ResourceRange.Default))
  134. {
  135. var data = result.OpenStream().ReadStringToEnd();
  136. var link = SiteBrowser.GeneratedResourceRegex.Match(data).Groups["link"].Value;
  137. var delete = SiteBrowser.DeleteLinkRegex.Match(data).Value;
  138. return new UploadResult(new Uri(link), new Uri(delete));
  139. }
  140. }
  141. #endregion
  142. #region Private Members
  143. private void CheckIfRemoved(Page page)
  144. {
  145. if (page.GetElementById("tabCaptcha") == null)
  146. throw new NotFoundException();
  147. }
  148. private void CheckIfBusy(Page page)
  149. {
  150. var form = page.GetElementById("tabCaptcha");
  151. //var timer = page.GetElementById("freeTimer").GetChildren().First() as Literal;
  152. //if (form == null && timer != null)
  153. // throw new PostponeException(Convert.ToInt32(ResourceSizeHelper.FindNumberFromTheBeginning(timer.Content)));
  154. //if (form == null)
  155. // throw new PostponeException();
  156. }
  157. #endregion
  158. private class CaptchaRequest : ISubmittable
  159. {
  160. private readonly string location;
  161. private readonly string id;
  162. private readonly string challenge;
  163. private readonly string response;
  164. public CaptchaRequest(string location, string id, string challenge, string response)
  165. {
  166. this.location = location;
  167. this.id = id;
  168. this.challenge = challenge;
  169. this.response = response;
  170. }
  171. #region IResourceable Members
  172. public string Location
  173. {
  174. get { return this.location; }
  175. }
  176. public string Method
  177. {
  178. get { return @"POST"; }
  179. }
  180. public string Encoding
  181. {
  182. get { return @"application/x-www-form-urlencoded"; }
  183. }
  184. public ResourceParameter[] Parameters
  185. {
  186. get
  187. {
  188. return new[]
  189. {
  190. new ResourceParameter("id", this.id),
  191. new ResourceParameter("recaptcha_challenge_field", this.challenge),
  192. new ResourceParameter("recaptcha_response_field", this.response),
  193. };
  194. }
  195. }
  196. ResourceParameter[] IResourceable.Headers
  197. {
  198. get { return new ResourceParameter[] { }; }
  199. }
  200. #endregion
  201. }
  202. }
  203. }