diff --git a/README.md b/README.md index 175b15f..10e3011 100644 --- a/README.md +++ b/README.md @@ -5,18 +5,18 @@ Yet another mass downloader for FurAffinity.net. [Download stable win32 builds.](https://github.com/crouvpony47/furdown/releases) -### Changelog (v.0.5.5.0) -- adapt to site changes +### Changelog (v.2.0.1.0) +- Switched to Edge-based embedded browser for authentification and human verification. ### A note about CF's "I'm Under Attack" mode -- If you are already logged in but are shown the login form anyway, simply navigate to the FA main page. +- If you are already logged in but are shown the login form anyway, simply navigate to the FA front page. ### System requirements -- Windows 7 or newer, might not work on server editions -- .NET 4.6.2 -- IE11 (for systems where IE11 is not available, compile Furdown from source after adjusting `src/Program.cs:WebBrowserEmulationSet()` accordingly) +- Windows 7 SP1, 8.1, or 10+. Windows 10 or 11 recommended. +- .NET Framework 4.6.2 +- Microsoft Edge WebView2 (usually preinstalled on Windows 10 or newer) -IE11 requirement can be bypassed if you implement an alternative cookie provider, see "Advanced options" section below. +Edge WebView2 requirement can be bypassed if you implement an alternative cookie provider, see "Advanced options" section below. ### Portable mode @@ -66,7 +66,7 @@ Override descriptions naming template with TMPLT. __*__ __*__ As templates use the syntax much like that used for environment variables, you may get unexpected results if, say, %FILEPART% is an existing variable. **Other notes**: -- You must login in GUI mode at least once before using batch/CLI mode. +- You must login in GUI mode at least once before using batch/CLI mode unless the cookies/user-agent are provided using the environment variables. - For non-overridden parameters the value from a current configuration file (the same file used in GUI mode) is used. **Examples**: @@ -78,6 +78,6 @@ Note that `%` might need to be escaped as `%%` in batch scripts. ### Advanced options -The builtin authentication mechanism based on the embedded Internet Explorer can be bypassed by setting FURDOWN_COOKIES and FURDOWN_USERAGENT environment variables to the appropriate values. If only FURDOWN_USERAGENT is set, furdown and its embedded IE will use the User-Agent value provided, and if only FURDOWN_COOKIES is set, it is your responsibility to match the User-Agent of the cookies source and the one used by furdown. +The builtin authentication mechanism based on the embedded Edge can be bypassed by setting `FURDOWN_COOKIES` and `FURDOWN_USERAGENT` environment variables to the appropriate values. Setting just the `FURDOWN_USERAGENT` has no effect. -Note that the FURDOWN_COOKIES is expected to contain the entire cookie header value (something like `b=XXX; __gads=XXX; a=XXX; s=XXX; __qca=XXX; sz=XXX; cc=XXX; __cfduid=XXX` where `XXX`s are some values) +Note that the `FURDOWN_COOKIES` is expected to contain the entire cookie header value (something like `b=XXX; __gads=XXX; a=XXX; s=XXX; __qca=XXX; sz=XXX; cc=XXX; __cfduid=XXX` where `XXX`s are some values) diff --git a/src/AppCore.cs b/src/AppCore.cs index 806da19..b6a22be 100644 --- a/src/AppCore.cs +++ b/src/AppCore.cs @@ -44,16 +44,6 @@ public class AppCore public bool isInitialized = false; - /// - /// Gets all, including http-only, cookies from WebBrowser component - /// - /// URI which is used to get the cookies for - /// - private static string GetGlobalCookies(string uri) //fixme - { - return CookiesStorage.GetCookieString(); - } - /// /// Reads network stream to another stream, throwing excepton if no data was received in reasonable time /// @@ -153,6 +143,7 @@ public async Task Init() { Console.WriteLine("Warning :: could not determine the username to use for the default target gallery url"); } + isInitialized = true; return true; } else diff --git a/src/Program.cs b/src/Program.cs index c54da45..3895405 100644 --- a/src/Program.cs +++ b/src/Program.cs @@ -21,6 +21,7 @@ static void Main() var args = Environment.GetCommandLineArgs(); if (args.Count() < 2 || args[1] != "-b") { + // GUI mode if (args.Count() >= 2) { Console.WriteLine("Note: found some invalid command line arguments"); @@ -28,13 +29,27 @@ static void Main() } Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); - var af = new authForm(); - Application.Run(af); + Application.Run(new authForm()); } else { - bool AuthRes = AppCore.Core.Init().Result; - if (!AuthRes) + // batch mode + bool hasEnvCookies = (Environment.GetEnvironmentVariable("FURDOWN_COOKIES") != null); + bool authRes = false; + if (hasEnvCookies) + { + authRes = AppCore.Core.Init().Result; + } + else + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + var aForm = new authForm(); + aForm.BackgroundMode = true; + Application.Run(aForm); + authRes = AppCore.Core.isInitialized; + } + if (!authRes) { Console.WriteLine("Not authorized! Log in at least once using GUI first."); Console.WriteLine("Alternatively, provide the 'cookie' and 'user-agent' header values"); diff --git a/src/Properties/AssemblyInfo.cs b/src/Properties/AssemblyInfo.cs index fa894f4..6f48836 100644 --- a/src/Properties/AssemblyInfo.cs +++ b/src/Properties/AssemblyInfo.cs @@ -16,7 +16,7 @@ [assembly: Guid("8b45577e-b5d1-4056-96e6-b2647e18b867")] -[assembly: AssemblyVersion("2.0.0.0")] -[assembly: AssemblyFileVersion("2.0.0.0")] +[assembly: AssemblyVersion("2.0.1.0")] +[assembly: AssemblyFileVersion("2.0.1.0")] [assembly: NeutralResourcesLanguage("en")] diff --git a/src/app.manifest b/src/app.manifest index 03f9094..4af2df1 100644 --- a/src/app.manifest +++ b/src/app.manifest @@ -1,6 +1,6 @@  - + diff --git a/src/authForm.cs b/src/authForm.cs index 9ab888b..c1ed402 100644 --- a/src/authForm.cs +++ b/src/authForm.cs @@ -27,15 +27,27 @@ public async Task Start() // initialize WebView2 fully await edgeWebView.EnsureCoreWebView2Async(null); // initialize request interception - edgeWebView.CoreWebView2.AddWebResourceRequestedFilter( - "https://www.furaffinity.net/*", - CoreWebView2WebResourceContext.Document, - CoreWebView2WebResourceRequestSourceKinds.All); + try + { + edgeWebView.CoreWebView2.AddWebResourceRequestedFilter( + "https://www.furaffinity.net/*", + CoreWebView2WebResourceContext.Document, + CoreWebView2WebResourceRequestSourceKinds.All); + } + catch (Exception) + { + // fallback to an older (deprecated) filter interface + // for legacy WebView versions (i.e. v.109 on Win 7) + edgeWebView.CoreWebView2.AddWebResourceRequestedFilter( + "https://www.furaffinity.net/*", + CoreWebView2WebResourceContext.Document); + } edgeWebView.CoreWebView2.WebResourceRequested += async delegate ( object _sender, CoreWebView2WebResourceRequestedEventArgs args) { var uri = new Uri(args.Request.Uri); - if (uri.AbsolutePath.ToString() == "/" || uri.AbsolutePath.ToString().StartsWith("/user")) + if (uri.AbsolutePath.ToString() == "/" || uri.AbsolutePath.ToString().StartsWith("/user") + || (uri.AbsolutePath.ToString().StartsWith("/login") && uri.Query.ToString().Contains("__cf"))) { CoreWebView2HttpRequestHeaders requestHeaders = args.Request.Headers; if (requestHeaders.Contains("Cookie")) @@ -67,6 +79,11 @@ public async Task Start() private void OnAuthSuccessful() { + if (BackgroundMode) + { + Close(); + return; + } Hide(); taskForm tf = new taskForm(this, AppCore.Core.defaultUserId); tf.Show(); @@ -99,6 +116,11 @@ private async void WebViewLoginFlow() else { Console.WriteLine("Does not seem to be authorized (or need to pass CF validation)..."); + if (BackgroundMode) + { + Close(); + return; + } // set up a new login callback onShouldValidateCookies = async delegate () @@ -160,8 +182,14 @@ private async void authForm_Shown(object sender, EventArgs e) private void authForm_Load(object sender, EventArgs e) { Icon = System.Drawing.Icon.ExtractAssociatedIcon(Application.ExecutablePath); + if (BackgroundMode) + { + WindowState = FormWindowState.Minimized; + } } + public bool BackgroundMode = false; + delegate Task CookieValidationCallback(); private CookieValidationCallback onShouldValidateCookies = null; }