diff --git a/CertificateUtil.cs b/CertificateUtil.cs index 318d09d..0beedbc 100644 --- a/CertificateUtil.cs +++ b/CertificateUtil.cs @@ -215,7 +215,8 @@ public static X509Certificate2 MakeChainSignedCert(string certSubject, X509Certi */ // Save the certificate and return it. - FakeCertificates.Add(certSubject, certificateWithKey); + if (!FakeCertificates.ContainsKey(certSubject)) + FakeCertificates.Add(certSubject, certificateWithKey); return certificateWithKey; } } diff --git a/Converter.cs b/Converter.cs index 7523f48..b99b1e9 100644 --- a/Converter.cs +++ b/Converter.cs @@ -141,7 +141,12 @@ private Stream RunConverter(LogWriter Log, string ConvCommandLine, Stream InputS { if (InputStream != null) new Task(() => { - while (InputStream.CanRead && !ConvProc.HasExited) { }; if (!ConvProc.HasExited) ConvProc.Kill(); Console.WriteLine(); + while (InputStream.CanRead && !ConvProc.HasExited) + { + Thread.Sleep(5000); + if (InputStream.CanRead && !ConvProc.HasExited) Log.WriteLine(" Converter is still running."); + } + if (!ConvProc.HasExited) ConvProc.Kill(); Console.WriteLine(); }).Start(); new Task(() => @@ -162,6 +167,9 @@ private Stream RunConverter(LogWriter Log, string ConvCommandLine, Stream InputS #endif if (File.Exists(SourceTmpFile)) File.Delete(SourceTmpFile); if (File.Exists(DestinationTmpFile)) File.Delete(DestinationTmpFile); +#if DEBUG + Log.WriteLine(" Remove temporary files if any."); +#endif }).Start(); return ConvProc.StandardOutput.BaseStream; } @@ -181,8 +189,18 @@ private Stream RunConverter(LogWriter Log, string ConvCommandLine, Stream InputS #endif ConvProc.WaitForExit(); InputStream.Close(); - if (File.Exists(SourceTmpFile)) File.Delete(SourceTmpFile); - if (File.Exists(DestinationTmpFile)) File.Delete(DestinationTmpFile); + + new Task(() => + { + //wait 1 minute for let client time to download the file + Thread.Sleep(60000); +#if DEBUG + Log.WriteLine(" Remove temporary files."); +#endif + if (File.Exists(SourceTmpFile)) File.Delete(SourceTmpFile); + if (File.Exists(DestinationTmpFile)) File.Delete(DestinationTmpFile); + }).Start(); + return File.OpenRead(DestinationTmpFile); } } diff --git a/HttpRequestProcessor.cs b/HttpRequestProcessor.cs index 3550c7d..a56ef8c 100644 --- a/HttpRequestProcessor.cs +++ b/HttpRequestProcessor.cs @@ -193,7 +193,9 @@ private void ProcessClientRequest(object Backend, LogWriter Logger, string SslLo catch { Request.Url = new Uri(Request.RawUrl); } break; case RequestKind.AlternateProxy: - Request.Url = new Uri(Request.RawUrl[1..]); + string url = Request.RawUrl[1..]; + if (url.Contains(":/") && !url.Contains("://")) url = url.Replace(":/", "://"); + Request.Url = new Uri(url); break; case RequestKind.StandardSslProxy: Request.Url = null; diff --git a/HttpTransit.cs b/HttpTransit.cs index 4d074ca..09134ba 100644 --- a/HttpTransit.cs +++ b/HttpTransit.cs @@ -232,15 +232,18 @@ public void ProcessTransit() if (ClientRequest.Kind == HttpUtil.RequestKind.AlternateProxy) { - // "Local proxy mode" + // "Alternate proxy access mode" + // ex. "Local proxy mode" string FixedUrl = ClientRequest.RawUrl[1..]; + if (FixedUrl.Contains(":/") && !FixedUrl.Contains("://")) FixedUrl = FixedUrl.Replace(":/", "://"); RequestURL = new Uri(FixedUrl); Log.WriteLine(" Alternate: {0}", RequestURL); } if (ClientRequest.Kind == HttpUtil.RequestKind.DirtyAlternateProxy) { - // "Dirty local proxy mode", try to use last used host: http://localhost/favicon.ico = http://example.com/favicon.ico + // "Dirty alternate proxy access mode", try to use last used host: http://localhost/favicon.ico = http://example.com/favicon.ico + // ex. "Dirty local proxy mode" string FixedUrl = "http://" + new Uri(LastURL).Host + RequestURL.LocalPath; RequestURL = new Uri(FixedUrl); if (RequestURL.Host == "999.999.999.999") { SendError(404, "The proxy server cannot guess domain name."); return; } @@ -1186,6 +1189,11 @@ private void SendInternalPage(string InternalPageId, string Arguments) } return; default: + if (InternalPageId.ToLowerInvariant() == "/rovp.htm" && !Program.ToBoolean(ConfigFile.WebVideoOptions["Enable"] ?? "yes")) + { + SendRedirect("/norovp.htm", "ROVP is disabled on this server."); + return; + } if (CheckInternalContentModification(InternalPageId, ClientRequest.Headers["If-Modified-Since"])) { // send 304 Not Modified code @@ -2283,7 +2291,18 @@ private void SendStream(Stream Potok, string ContentType, bool Close = true) if (ex is FileNotFoundException) ErrNo = 404; SendError(ErrNo, "Cannot retreive stream.
" + ex.ToString().Replace("\n", "
")); } - else { Log.WriteLine("> CmdLineOptions = new List>(); @@ -147,36 +148,54 @@ static void Main(string[] args) if (HaveCrtKey) HaveCrtKey = (new FileInfo(ConfigFile.SslCertificate).Length > MinPemLentgh) && (new FileInfo(ConfigFile.SslPrivateKey).Length > MinPemLentgh); if (HaveCrtKey) { Log.WriteLine(false, false, "Using as SSL Certificate Authority: {0}, {1}.", ConfigFile.SslCertificate, ConfigFile.SslPrivateKey); } - else + else if (!RebuildCA) { - Log.WriteLine(true, false, "Creating root SSL Certificate & Private Key for CA..."); - CertificateUtil.MakeSelfSignedCert(ConfigFile.SslCertificate, ConfigFile.SslPrivateKey, ConfigFile.SslRootSubject, ConfigFile.SslHashAlgorithm); - Log.WriteLine(true, false, "CA Certificate: {0}; Key: {1}.", ConfigFile.SslCertificate, ConfigFile.SslPrivateKey); + CreateRootCertificate(); } - RootCertificate = new X509Certificate2(X509Certificate2.CreateFromPemFile(ConfigFile.SslCertificate, ConfigFile.SslPrivateKey).Export(X509ContentType.Pkcs12)); - Protocols += ", HTTPS 1.1"; - if (!DefaultPACoverriden) DefaultPAC += DefaultPAChttps; - - //check validness period - if (RootCertificate.NotAfter < DateTime.Now || RootCertificate.NotBefore > DateTime.Now) + if (RebuildCA) { - Log.WriteLine(true, false, "Warning! CA Certificate is out of date: {0}-{1}, now {2}.", RootCertificate.NotBefore, RootCertificate.NotAfter, DateTime.Now); + Console.WriteLine(); + Log.WriteLine(true, false, "CA Certificate will be new, so import it to browser(s) after build succeeds."); + CreateRootCertificate(); + RootCertificate = new X509Certificate2(X509Certificate2.CreateFromPemFile(ConfigFile.SslCertificate, ConfigFile.SslPrivateKey).Export(X509ContentType.Pkcs12)); + Log.WriteLine(true, false, "The new certificate is called \"" + RootCertificate.GetNameInfo(X509NameType.SimpleName, false) + "\"."); + Log.WriteLine(true, false, "WebOne will now exit."); + Environment.Exit(0); } - - if (RootCertificate.NotAfter < DateTimeOffset.Now.AddDays(ConfigFile.SslCertVaildAfterNow) || - RootCertificate.NotBefore > DateTimeOffset.Now.AddDays(ConfigFile.SslCertVaildBeforeNow)) + try { - Log.WriteLine(true, false, "Warning! CA Certificate is too fresh or expires too soon. Check configuration."); + RootCertificate = new X509Certificate2(X509Certificate2.CreateFromPemFile(ConfigFile.SslCertificate, ConfigFile.SslPrivateKey).Export(X509ContentType.Pkcs12)); + Protocols += ", HTTPS 1.1"; + if (!DefaultPACoverriden) DefaultPAC += DefaultPAChttps; + //check validness period + if (RootCertificate.NotAfter < DateTime.Now || RootCertificate.NotBefore > DateTime.Now) + { + Log.WriteLine(true, false, "Warning! CA Certificate is out of date: {0}-{1}, now {2}.", RootCertificate.NotBefore, RootCertificate.NotAfter, DateTime.Now); + } + + if (RootCertificate.NotAfter < DateTimeOffset.Now.AddDays(ConfigFile.SslCertVaildAfterNow) || + RootCertificate.NotBefore > DateTimeOffset.Now.AddDays(ConfigFile.SslCertVaildBeforeNow)) + { + Log.WriteLine(true, false, "Warning! CA Certificate is too fresh or expires too soon. Check configuration."); + } + } + catch (Exception CertLoadEx) + { + if (CertLoadEx.InnerException != null) + { + Log.WriteLine(true, false, "Unable to load CA Certificate: {0}.", CertLoadEx.InnerException.Message); + } + else + { + Log.WriteLine(true, false, "Unable to load CA Certificate: {0}.", CertLoadEx.Message); + } + ConfigFile.SslEnable = false; } } catch (Exception CertCreateEx) { Log.WriteLine(true, false, "Unable to create CA Certificate: {0}.", CertCreateEx.Message); - /* - Log.WriteLine(true, false, CertCreateEx.StackTrace.Replace("\n", " ; ")); //only for debug purposes at this moment - Log.WriteLine(true, false, "End of CA build error information. HTTPS won't be available!"); - */ ConfigFile.SslEnable = false; } @@ -196,7 +215,7 @@ static void Main(string[] args) if (!DefaultPACoverriden) DefaultPAC += DefaultPACfooter; if (!DefaultPACoverriden) ConfigFile.PAC = DefaultPAC; - Log.WriteLine(false, false, "Configured to http://{1}:{2}/, {3}", ConfigFileName, ConfigFile.DefaultHostName, ConfigFile.Port, Protocols); + Log.WriteLine(false, false, "Configured to http://{1}:{2}/, {3}", ConfigFileName, ConfigFile.DefaultHostName, ConfigFile.Port, Protocols); //initialize server try @@ -280,6 +299,16 @@ static void Main(string[] args) Shutdown(); } + /// + /// Create certificate and private key files for WebOne Certificate Authority + /// + private static void CreateRootCertificate() + { + Log.WriteLine(true, false, "Creating root SSL Certificate & Private Key for CA..."); + CertificateUtil.MakeSelfSignedCert(ConfigFile.SslCertificate, ConfigFile.SslPrivateKey, ConfigFile.SslRootSubject, ConfigFile.SslHashAlgorithm); + Log.WriteLine(true, false, "CA Certificate: {0}; Key: {1}.", ConfigFile.SslCertificate, ConfigFile.SslPrivateKey); + } + /// /// Shut down server and terminate process /// @@ -382,6 +411,9 @@ private static void ProcessCommandLine(string[] args) case "--dump-requests": //all will be processed in ProcessCommandLineOptions() break; + case "--rebuild-ca": + RebuildCA = true; + break; case "--daemon": DaemonMode = true; break; diff --git a/WebOne.csproj b/WebOne.csproj index d05238e..b3ce86e 100644 --- a/WebOne.csproj +++ b/WebOne.csproj @@ -5,7 +5,7 @@ Exe net6.0 Alexander Tauenis - 0.17.1 + 0.17.2 $(Version)$(VersionSuffix) World @@ -289,5 +289,7 @@ fi Always __MACOSX/%(Filename)%(Extension) + + diff --git a/WebVideoPlayer.cs b/WebVideoPlayer.cs index 4efc576..9699739 100644 --- a/WebVideoPlayer.cs +++ b/WebVideoPlayer.cs @@ -31,7 +31,8 @@ public WebVideoPlayer(NameValueCollection Parameters) if (!Program.ToBoolean(ConfigFile.WebVideoOptions["Enable"] ?? "yes")) { - Page.Content = "Sorry, proxy server administrator has disabled the online video download feature."; + Page.Content = "It's disabled."; + Page.HttpHeaders.Add("Refresh", "0;url=/norovp.htm"); return; } @@ -39,110 +40,11 @@ public WebVideoPlayer(NameValueCollection Parameters) { case "": case null: - string Frameset = - "
" + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - "
Video
FormatCodecs   (?)
" + - " Embed, " + - " WMP, " + - " VLC, " + - " WinMedia, " + - " NetShow, " + - " DynImg, " + - " HTML5, " + - " link, " + - " file" + - "
" + - "
" + - "" + - ""; ; - Page.Content = Frameset; + Page.Content = "

"; + Page.Content += "\"Click"; + Page.Content += "

Retro Online Video Player

"; + Page.Content += "

"; + Page.HttpHeaders.Add("Refresh", "5;url=/rovp.htm"); break; case "intro": Page.Content = "

Use the toolbar above to watch a video.

"; diff --git a/Win32-full/yt-dlp.exe b/Win32-full/yt-dlp.exe index 7c2f1fe..4b4b0bd 100644 Binary files a/Win32-full/yt-dlp.exe and b/Win32-full/yt-dlp.exe differ diff --git a/Win32-full/yt-dlp.txt b/Win32-full/yt-dlp.txt index 4da9fe4..a23bbb5 100644 --- a/Win32-full/yt-dlp.txt +++ b/Win32-full/yt-dlp.txt @@ -76,7 +76,9 @@ Options: stderr) to apply the setting to. Can be one of "always", "auto" (default), "never", or "no_color" (use non color terminal - sequences). Can be used multiple times + sequences). Use "auto-tty" or "no_color-tty" + to decide based on terminal support only. + Can be used multiple times --compat-options OPTS Options that can help keep compatibility with youtube-dl or youtube-dlc configurations by reverting some of the @@ -110,6 +112,9 @@ Options: --impersonate CLIENT[:OS] Client to impersonate for requests. E.g. chrome, chrome-110, chrome:windows-10. Pass --impersonate="" to impersonate any client. + Note that forcing impersonation for all + requests may have a detrimental impact on + download speed and stability --list-impersonate-targets List available clients to impersonate. -4, --force-ipv4 Make all connections via IPv4 -6, --force-ipv6 Make all connections via IPv6 @@ -163,8 +168,8 @@ Options: is not present, and "&" to check multiple conditions. Use a "\" to escape "&" or quotes if needed. If used multiple times, - the filter matches if atleast one of the - conditions are met. E.g. --match-filter + the filter matches if at least one of the + conditions is met. E.g. --match-filter !is_live --match-filter "like_count>?100 & description~='(?i)\bcats \& dogs\b'" matches only videos that are not live OR those that @@ -378,16 +383,17 @@ Options: The name of the browser to load cookies from. Currently supported browsers are: brave, chrome, chromium, edge, firefox, - opera, safari, vivaldi. Optionally, the - KEYRING used for decrypting Chromium cookies - on Linux, the name/path of the PROFILE to - load cookies from, and the CONTAINER name - (if Firefox) ("none" for no container) can - be given with their respective seperators. - By default, all containers of the most - recently accessed profile are used. - Currently supported keyrings are: basictext, - gnomekeyring, kwallet, kwallet5, kwallet6 + opera, safari, vivaldi, whale. Optionally, + the KEYRING used for decrypting Chromium + cookies on Linux, the name/path of the + PROFILE to load cookies from, and the + CONTAINER name (if Firefox) ("none" for no + container) can be given with their + respective separators. By default, all + containers of the most recently accessed + profile are used. Currently supported + keyrings are: basictext, gnomekeyring, + kwallet, kwallet5, kwallet6 --no-cookies-from-browser Do not load cookies from browser (default) --cache-dir DIR Location in the filesystem where yt-dlp can store some downloaded information (such as @@ -749,7 +755,7 @@ Options: --print/--output), "before_dl" (before each video download), "post_process" (after each video download; default), "after_move" - (after moving video file to it's final + (after moving video file to its final locations), "after_video" (after downloading and processing all formats of a video), or "playlist" (at end of playlist). This option @@ -809,4 +815,3 @@ Options: arguments for different extractors See full documentation at https://github.com/yt-dlp/yt-dlp#readme -Latest version: https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_x86.exe diff --git a/html/norovp.htm b/html/norovp.htm new file mode 100644 index 0000000..447ed35 --- /dev/null +++ b/html/norovp.htm @@ -0,0 +1,17 @@ + + + + + +Retro online video player + + + + + +

Sorry, proxy server administrator has disabled the online video download feature.

+ + diff --git a/html/rovp.gif b/html/rovp.gif new file mode 100644 index 0000000..f9700d4 Binary files /dev/null and b/html/rovp.gif differ diff --git a/html/rovp.htm b/html/rovp.htm index 5afb3bc..213732f 100644 --- a/html/rovp.htm +++ b/html/rovp.htm @@ -38,6 +38,7 @@ + Codecs