@@ -848,10 +848,12 @@ private void SendInternalPage(string InternalPageId, string Arguments)
848848 case "/" :
849849 case "/!" :
850850 case "/!/" :
851+ // Status page
851852 SendInternalStatusPage ( ) ;
852853 return ;
853854 case "/!codepages" :
854855 case "/!codepages/" :
856+ // Code page list
855857 string codepages = "<p>The following code pages are available: <br>\n " +
856858 "<table><tr><td><b>Name</b></td><td><b>#</b></td><td><b>Description</b></td></tr>\n " ;
857859 codepages += "<tr><td><b>AsIs</b></td><td>0</td><td>Keep original encoding (code page)</td></tr>\n " ;
@@ -896,6 +898,7 @@ private void SendInternalPage(string InternalPageId, string Arguments)
896898 return ;
897899 case "/!img-test" :
898900 case "/!img-test/" :
901+ // ImageMagick test v1
899902 if ( ConfigFile . EnableManualConverting )
900903 {
901904 SendError ( 200 , @"ImageMagick test.<br><img src=""/!convert/?src=logo.webp&dest=gif&type=image/gif"" alt=""ImageMagick logo"" width=640 height=480><br>A wizard should appear nearby." ) ;
@@ -907,6 +910,7 @@ private void SendInternalPage(string InternalPageId, string Arguments)
907910 return ;
908911 }
909912 case "/!imagemagicktest.gif" :
913+ // ImageMagick test v2
910914 foreach ( Converter Cvt in ConfigFile . Converters )
911915 {
912916 if ( Cvt . Executable == "convert" && ! Cvt . SelfDownload )
@@ -924,6 +928,7 @@ private void SendInternalPage(string InternalPageId, string Arguments)
924928 return ;
925929 case "/!convert" :
926930 case "/!convert/" :
931+ // File format converting
927932 if ( ! ConfigFile . EnableManualConverting )
928933 {
929934 SendInfoPage ( "WebOne: Feature disabled" , "Feature disabled" , "Manual file converting is disabled for security purposes.<br>Proxy administrator can enable it via <code>[Server]</code> section, <code>EnableManualConverting</code> option." , 500 ) ;
@@ -1064,6 +1069,12 @@ private void SendInternalPage(string InternalPageId, string Arguments)
10641069 return ;
10651070 case "/!webvideo" :
10661071 case "/!webvideo/" :
1072+ // ROVP video content processor
1073+ if ( ! ConfigFile . WebVideoOptions . ContainsKey ( "Enable" ) || ! Program . ToBoolean ( ConfigFile . WebVideoOptions [ "Enable" ] ?? "yes" ) )
1074+ {
1075+ SendRedirect ( "/norovp.htm" , "Video Converting and ROVP are disabled on this server." ) ;
1076+ return ;
1077+ }
10671078 Dictionary < string , string > VidArgs = new ( ) ;
10681079
10691080 foreach ( string UrlArg in System . Web . HttpUtility . ParseQueryString ( ClientRequest . Url . Query ) . AllKeys )
@@ -1113,10 +1124,12 @@ private void SendInternalPage(string InternalPageId, string Arguments)
11131124 }
11141125 case "/!player" :
11151126 case "/!player/" :
1127+ // ROVP
11161128 SendInfoPage ( new WebVideoPlayer ( System . Web . HttpUtility . ParseQueryString ( ClientRequest . Url . Query ) ) . Page ) ;
11171129 return ;
11181130 case "/!clear" :
11191131 case "/!clear/" :
1132+ // Clear temporary files
11201133 int FilesDeleted = 0 ;
11211134 foreach ( FileInfo file in ( new DirectoryInfo ( ConfigFile . TemporaryDirectory ) ) . EnumerateFiles ( "convert-*.*" ) )
11221135 {
@@ -1127,14 +1140,15 @@ private void SendInternalPage(string InternalPageId, string Arguments)
11271140 return ;
11281141 case "/!ftp" :
11291142 case "/!ftp/" :
1130- //FTP client
1143+ // FTP client
11311144 SendInfoPage ( new FtpClientGUI ( ClientRequest ) . GetPage ( ) ) ;
11321145 return ;
11331146 case "/!ca" :
11341147 case "/!ca/" :
11351148 case "/weboneca.crt" :
11361149 case "/weboneca.cer" :
11371150 case "/weboneca.der" :
1151+ // Root certificate (DER-encoded)
11381152 Log . WriteLine ( "<Return WebOne CA (root) certificate." ) ;
11391153 if ( ! ConfigFile . SslEnable )
11401154 {
@@ -1161,6 +1175,7 @@ private void SendInternalPage(string InternalPageId, string Arguments)
11611175 return ;
11621176 case "/weboneca.pem" :
11631177 case "/weboneca.txt" :
1178+ // Root certificate (PEM BASE64-encoded)
11641179 const string CRT_HEADER = "-----BEGIN CERTIFICATE-----\n " ;
11651180 const string CRT_FOOTER = "\n -----END CERTIFICATE-----" ;
11661181
@@ -1198,7 +1213,7 @@ private void SendInternalPage(string InternalPageId, string Arguments)
11981213 case "/auto.pac" :
11991214 case "/wpad.dat" :
12001215 case "/wpad.da" :
1201- //Proxy Auto-Config
1216+ // Proxy Auto-Config
12021217 Log . WriteLine ( "<Return PAC/WPAD script." ) ;
12031218 string LocalHostAdress = GetServerName ( ) ;
12041219 if ( LocalHostAdress . StartsWith ( "[" ) ) LocalHostAdress = ConfigFile . DefaultHostName + ":" + ConfigFile . Port ; //on IPv6, fallback to DefaultHostName:Port
@@ -1223,7 +1238,7 @@ private void SendInternalPage(string InternalPageId, string Arguments)
12231238 }
12241239 return ;
12251240 case "/robots.txt" :
1226- //attempt to include in google index; kick the bot off
1241+ // Attempt to include in Google index; kick the bot off
12271242 Log . WriteLine ( "<Return robot kicker." ) ;
12281243 if ( SendInternalContent ( "robots.txt" , "" ) ) return ;
12291244
@@ -1246,11 +1261,14 @@ private void SendInternalPage(string InternalPageId, string Arguments)
12461261 }
12471262 return ;
12481263 default :
1249- if ( InternalPageId . ToLowerInvariant ( ) == "/rovp.htm" && ! Program . ToBoolean ( ConfigFile . WebVideoOptions [ "Enable" ] ?? "yes" ) )
1264+ // Custom content (CSS or ROVP)
1265+ if ( InternalPageId . ToLowerInvariant ( ) == "/rovp.htm" &&
1266+ ( ! ConfigFile . WebVideoOptions . ContainsKey ( "Enable" ) || ! Program . ToBoolean ( ConfigFile . WebVideoOptions [ "Enable" ] ?? "yes" ) ) )
12501267 {
12511268 SendRedirect ( "/norovp.htm" , "ROVP is disabled on this server." ) ;
12521269 return ;
12531270 }
1271+
12541272 if ( CheckInternalContentModification ( InternalPageId , ClientRequest . Headers [ "If-Modified-Since" ] ) )
12551273 {
12561274 // send 304 Not Modified code
@@ -1298,6 +1316,13 @@ public bool SendInternalContent(string ContentId, string Arguments, int StatusCo
12981316 {
12991317 if ( ! ContentId . StartsWith ( "!" ) ) ContentId = "/" + ContentId ;
13001318 string ContentFilePath = ConfigFile . ContentDirectory + ContentId ;
1319+
1320+ ContentFilePath = ContentFilePath . Replace ( "//" , "/" ) . Replace ( @"\\" , @"\" ) ;
1321+ if ( Environment . OSVersion . Platform == PlatformID . Win32NT )
1322+ ContentFilePath = ContentFilePath . Replace ( "/" , @"\" ) ;
1323+ if ( Environment . OSVersion . Platform == PlatformID . Unix )
1324+ ContentFilePath = ContentFilePath . Replace ( @"\" , "/" ) ;
1325+
13011326 if ( File . Exists ( ContentFilePath ) )
13021327 {
13031328 string Extension = ContentId . Substring ( ContentId . LastIndexOf ( '.' ) + 1 ) . ToLowerInvariant ( ) ;
@@ -1362,6 +1387,12 @@ public bool CheckInternalContentModification(string ContentId, string IfModified
13621387 if ( ! ContentId . StartsWith ( "!" ) ) ContentId = "/" + ContentId ;
13631388 string ContentFilePath = ConfigFile . ContentDirectory + ContentId ;
13641389
1390+ ContentFilePath = ContentFilePath . Replace ( "//" , "/" ) . Replace ( @"\\" , @"\" ) ;
1391+ if ( Environment . OSVersion . Platform == PlatformID . Win32NT )
1392+ ContentFilePath = ContentFilePath . Replace ( "/" , @"\" ) ;
1393+ if ( Environment . OSVersion . Platform == PlatformID . Unix )
1394+ ContentFilePath = ContentFilePath . Replace ( @"\" , "/" ) ;
1395+
13651396 if ( File . Exists ( ContentFilePath ) )
13661397 {
13671398 var IMS = ToDateTimeOffset ( IfModifiedSince ) ;
@@ -1680,16 +1711,46 @@ private string ProcessBody(string Body)
16801711 //fix the body if it will be deliveried through Alternate mode
16811712 if ( ClientRequest . Kind == HttpUtil . RequestKind . AlternateProxy || ClientRequest . Kind == HttpUtil . RequestKind . DirtyAlternateProxy )
16821713 {
1683- Body = Body . Replace ( "http://" , "http://" + GetServerName ( ) + "/http://" ) ;
1684- Body = Body . Replace ( "href=\" ./" , "href=\" http://" + GetServerName ( ) + "/http://" + RequestURL . Host + "/" ) ;
1685- Body = Body . Replace ( "src=\" ./" , "src=\" http://" + GetServerName ( ) + "/http://" + RequestURL . Host + "/" ) ;
1686- Body = Body . Replace ( "action=\" ./" , "action=\" http://" + GetServerName ( ) + "/http://" + RequestURL . Host + "/" ) ;
1687- Body = Body . Replace ( "href=\" //" , "href=\" http://" + GetServerName ( ) + "/http://" ) ;
1688- Body = Body . Replace ( "src=\" //" , "src=\" http://" + GetServerName ( ) + "/http://" ) ;
1689- Body = Body . Replace ( "action=\" //" , "action=\" http://" + GetServerName ( ) + "/http://" ) ;
1690- Body = Body . Replace ( "href=\" /" , "href=\" http://" + GetServerName ( ) + "/http://" + RequestURL . Host + "/" ) ;
1691- Body = Body . Replace ( "src=\" /" , "src=\" http://" + GetServerName ( ) + "/http://" + RequestURL . Host + "/" ) ;
1692- Body = Body . Replace ( "action=\" /" , "action=\" http://" + GetServerName ( ) + "/http://" + RequestURL . Host + "/" ) ;
1714+ string LocalPathDirectory = "/" ;
1715+ for ( int i = 0 ; i < RequestURL . Segments . Length - 1 ; i ++ )
1716+ {
1717+ LocalPathDirectory += RequestURL . Segments [ i ] ;
1718+ }
1719+
1720+ Body = Body . Replace ( ".replace(/\" /g" , ".replace(/\" WEBONEGOOGLEFIX1/g" ) ;
1721+ Body = Body . Replace ( ".replace(/'/g" , ".replace(/'WEBONEGOOGLEFIX2/g" ) ;
1722+
1723+ Body = Body . Replace ( "\" http://" , "\" @@@/http://" ) ;
1724+ Body = Body . Replace ( "\" https://" , "\" @@@/http://" ) ;
1725+ Body = Body . Replace ( "\" ftp://" , "\" @@@/ftp://" ) ;
1726+
1727+ Body = Body . Replace ( "\" //" , "\" @@@/http://" ) ;
1728+ Body = Body . Replace ( "\" /" , "\" /http://" + RequestURL . Host + "/" ) ;
1729+ Body = Body . Replace ( "\" ./" , "\" /http://" + RequestURL . Host + LocalPathDirectory ) ;
1730+ Body = Body . Replace ( "\" @@@/http://" , "\" /http://" ) ;
1731+ Body = Body . Replace ( "\" @@@/ftp://" , "\" /ftp://" ) ;
1732+
1733+ Body = Body . Replace ( "'http://" , "'@@@/http://" ) ;
1734+ Body = Body . Replace ( "'https://" , "'@@@/http://" ) ;
1735+ Body = Body . Replace ( "'ftp://" , "'@@@/ftp://" ) ;
1736+
1737+ Body = Body . Replace ( "'//" , "'@@@/http://" ) ;
1738+ Body = Body . Replace ( "'/" , "'/http://" + RequestURL . Host + "/" ) ;
1739+ Body = Body . Replace ( "'./" , "'/http://" + RequestURL . Host + LocalPathDirectory ) ;
1740+ Body = Body . Replace ( "'@@@/http://" , "'/http://" ) ;
1741+ Body = Body . Replace ( "'@@@/ftp://" , "'/ftp://" ) ;
1742+
1743+ Body = Body . Replace ( ":url(http://" , ":url(/http://" + RequestURL . Host + "/" ) ;
1744+ Body = Body . Replace ( ":url(https://" , ":url(/http://" + RequestURL . Host + "/" ) ;
1745+ Body = Body . Replace ( ":url(//" , ":url(@@@/http://" ) ;
1746+ Body = Body . Replace ( ":url(/" , ":url(/http://" + RequestURL . Host + "/" ) ;
1747+ Body = Body . Replace ( ":url(./" , ":url(/http://" + RequestURL . Host + LocalPathDirectory ) ;
1748+ Body = Body . Replace ( ":url(@@@/http://" , ":url(/http://" ) ;
1749+
1750+ Body = Body . Replace ( ".replace(/\" WEBONEGOOGLEFIX1/g" , ".replace(/\" /g" ) ;
1751+ Body = Body . Replace ( ".replace(/'WEBONEGOOGLEFIX2/g" , ".replace(/'/g" ) ;
1752+
1753+ // Note: "@@@" is workaround to differ strings.
16931754 }
16941755
16951756 return Body ;
@@ -2060,12 +2121,17 @@ private bool LookInWebArchive()
20602121 }
20612122 catch ( Exception ArchiveException )
20622123 {
2063- string ErrorPageId = "Err-WArchiveException.htm" ;
2064- string ErrorPageArguments = "?ErrorMessage=" + ArchiveException . Message . Replace ( "\n " , "<br>" ) + "&URL=" + RequestURL . AbsoluteUri . ToString ( ) ;
2065- if ( SendInternalContent ( ErrorPageId , ErrorPageArguments ) ) return true ;
2124+ try
2125+ {
2126+ string ErrorPageId = "Err-WArchiveException.htm" ;
2127+ string ErrorPageArguments = "?ErrorMessage=" + ArchiveException . Message . Replace ( "\n " , "<br>" ) + "&URL=" + RequestURL . AbsoluteUri . ToString ( ) ;
2128+ if ( SendInternalContent ( ErrorPageId , ErrorPageArguments ) ) return true ;
20662129
2067- SendInfoPage ( "WebOne: Web Archive error." , "Cannot load this page" , string . Format ( "<b>The requested server or page is not found and a Web Archive error occured.</b><br>{0}" , ArchiveException . Message . Replace ( "\n " , "<br>" ) ) ) ;
2068- return true ; //error page is ready
2130+ SendInfoPage ( "WebOne: Web Archive error." , "Cannot load this page" , string . Format ( "<b>The requested server or page is not found and a Web Archive error occured.</b><br>{0}" , ArchiveException . Message . Replace ( "\n " , "<br>" ) ) ) ;
2131+ return true ; //error page is ready
2132+ }
2133+ catch ( InvalidOperationException )
2134+ { return true ; } //catch case of "HTTP response headers are already sent."
20692135 }
20702136 }
20712137 else return false ; //nothing ready
0 commit comments