Skip to content

Commit cf50855

Browse files
committed
smarter URL validation
1 parent c80480d commit cf50855

5 files changed

Lines changed: 108 additions & 60 deletions

File tree

FlashpointSecurePlayer/FlashpointSecurePlayerGUI.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,7 @@ private void ActivateMode(TemplateElement templateElement, ErrorDelegate errorDe
525525
Uri webBrowserURL = null;
526526

527527
try {
528-
webBrowserURL = new Uri(AddURLProtocol(URL));
528+
webBrowserURL = new Uri(ValidateURL(URL), UriKind.Absolute);
529529
} catch (Exception ex) {
530530
LogExceptionToLauncher(ex);
531531
errorDelegate(String.Format(Properties.Resources.AddressNotUnderstood, URL));
@@ -1346,7 +1346,7 @@ await ImportActiveX(delegate (string text) {
13461346

13471347
if (templateElement.Mode.Name == ModeElement.NAME.SOFTWARE) {
13481348
try {
1349-
Uri requestUri = await DownloadAsync(AddURLProtocol(URL)).ConfigureAwait(true);
1349+
Uri requestUri = await DownloadAsync(ValidateURL(URL)).ConfigureAwait(true);
13501350

13511351
StringBuilder htdocsFilePath = new StringBuilder(HTDOCS);
13521352

FlashpointSecurePlayer/Properties/AssemblyInfo.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
// You can specify all the values or you can default the Build and Revision Numbers
3434
// by using the '*' as shown below:
3535
// [assembly: AssemblyVersion("1.0.*")]
36-
[assembly: AssemblyVersion("2.1.4.0")]
37-
[assembly: AssemblyFileVersion("2.1.4.0")]
36+
[assembly: AssemblyVersion("2.1.5.0")]
37+
[assembly: AssemblyFileVersion("2.1.5.0")]
3838
[assembly: NeutralResourcesLanguage("en")]
3939

FlashpointSecurePlayer/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Flashpoint Secure Player 2.1.4
1+
# Flashpoint Secure Player 2.1.5
22
This player attempts to solve common compatibility or portability issues posed by browser plugins on Windows for the purpose of playback in BlueMaxima's Flashpoint.
33

44
It is compatible with Windows 7, Windows 8, Windows 8.1 and Windows 10, and requires .NET Framework 4.5. If you are on Windows 8.1 or Windows 10, or if you are on Windows 7/8 and have updates enabled, you already have .NET Framework 4.5. Otherwise, you may [download .NET Framework 4.5.](http://www.microsoft.com/en-us/download/details.aspx?id=30653)

FlashpointSecurePlayer/Shared.cs

Lines changed: 72 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,29 @@ public static extern uint GetLongPathName(
186186
uint cchBuffer
187187
);
188188

189+
public const uint INTERNET_MAX_PATH_LENGTH = 2048;
190+
public const uint INTERNET_MAX_SCHEME_LENGTH = 32;
191+
static readonly uint INTERNET_MAX_URL_LENGTH = INTERNET_MAX_SCHEME_LENGTH + (uint)"://".Length + INTERNET_MAX_PATH_LENGTH;
192+
193+
[Flags]
194+
public enum URL_APPLYFlags : uint {
195+
URL_APPLY_DEFAULT = 0x00000001,
196+
URL_APPLY_GUESSSCHEME = 0x00000002,
197+
URL_APPLY_GUESSFILE = 0x00000004,
198+
URL_APPLY_FORCEAPPLY = 0x00000008
199+
}
200+
201+
[DllImport("SHLWAPI.DLL", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)]
202+
public static extern int UrlApplyScheme(
203+
[MarshalAs(UnmanagedType.LPTStr)]
204+
string pszIn,
205+
206+
[MarshalAs(UnmanagedType.LPTStr)]
207+
StringBuilder pszOut,
208+
209+
ref uint pcchOut,
210+
URL_APPLYFlags dwFlags);
211+
189212
public enum OS : uint {
190213
OS_WINDOWS = 0,
191214
OS_NT = 1,
@@ -1958,6 +1981,55 @@ public string this[string shortPath] {
19581981
public static PathNamesLong Long { get; } = new PathNamesLong();
19591982
}
19601983

1984+
private const string URI_SCHEME_HTTP = "http";
1985+
private const string URI_SCHEME_HTTPS = "https";
1986+
private const string URI_SCHEME_FTP = "ftp";
1987+
1988+
public static string ValidateURL(string url) {
1989+
// first try a guessed scheme
1990+
// (for example, guess HTTP for www subdomain, FTP for ftp subdomain...)
1991+
StringBuilder validatedURL = new StringBuilder((int)INTERNET_MAX_URL_LENGTH);
1992+
uint validatedURLCapacity = (uint)validatedURL.Capacity;
1993+
1994+
int err = UrlApplyScheme(url, validatedURL, ref validatedURLCapacity, URL_APPLYFlags.URL_APPLY_GUESSSCHEME);
1995+
1996+
if (err == S_OK
1997+
&& validatedURLCapacity < validatedURL.Capacity) {
1998+
url = validatedURL.ToString();
1999+
} else {
2000+
// second try the default scheme
2001+
// we only do this to see if it returns S_FALSE
2002+
// if so, we know there is already a scheme and don't add our own
2003+
// we do not use the validated URL given by UrlApplyScheme here
2004+
validatedURL.Clear();
2005+
validatedURLCapacity = (uint)validatedURL.Capacity;
2006+
2007+
err = UrlApplyScheme(url, validatedURL, ref validatedURLCapacity, URL_APPLYFlags.URL_APPLY_DEFAULT);
2008+
2009+
// workaround: we always want to use HTTP, regardless of the default
2010+
// (in case the default is HTTPS)
2011+
if (err != S_FALSE) {
2012+
// skip leading slashes for protocol-less URLs
2013+
if (url.StartsWith("//", StringComparison.Ordinal)) {
2014+
url = url.Substring(2);
2015+
}
2016+
2017+
url = URI_SCHEME_HTTP + "://" + url;
2018+
}
2019+
}
2020+
return url;
2021+
}
2022+
2023+
public static bool TestInternetURI(Uri uri) {
2024+
if (uri.IsFile) {
2025+
return false;
2026+
}
2027+
2028+
// the URI Scheme is always lowercase
2029+
string scheme = uri.Scheme;
2030+
return scheme == URI_SCHEME_HTTP || scheme == URI_SCHEME_HTTPS || scheme == URI_SCHEME_FTP;
2031+
}
2032+
19612033
public static string GetWindowsVersionName(bool edition, bool servicePack, bool architecture) {
19622034
OperatingSystem operatingSystem = Environment.OSVersion;
19632035
string versionName = "Windows ";
@@ -2573,50 +2645,6 @@ public static Process StartProcessCreateBreakawayFromJob(ProcessStartInfo proces
25732645
}
25742646
}
25752647

2576-
private static int GetURLProtocolLength(string url) {
2577-
Uri uri;
2578-
2579-
try {
2580-
uri = new Uri(url);
2581-
} catch {
2582-
return 0;
2583-
}
2584-
2585-
if (String.IsNullOrEmpty(uri.Scheme)) {
2586-
return 0;
2587-
}
2588-
return (uri.Scheme + "://").Length;
2589-
}
2590-
2591-
public static bool HasURLProtocol(string url) {
2592-
return GetURLProtocolLength(url) > 0;
2593-
}
2594-
2595-
public static string AddURLProtocol(string url) {
2596-
if (GetURLProtocolLength(url) == 0) {
2597-
return "http://" + url;
2598-
}
2599-
return url;
2600-
}
2601-
2602-
public static string RemoveURLProtocol(string url) {
2603-
return url.Substring(GetURLProtocolLength(url));
2604-
}
2605-
2606-
public static bool TestInternetURI(Uri uri) {
2607-
if (uri.IsFile) {
2608-
return false;
2609-
}
2610-
2611-
const string SCHEME_HTTP = "http";
2612-
const string SCHEME_HTTPS = "https";
2613-
const string SCHEME_FTP = "ftp";
2614-
2615-
// the URI Scheme is always lowercase
2616-
string scheme = uri.Scheme;
2617-
return scheme == SCHEME_HTTP || scheme == SCHEME_HTTPS || scheme == SCHEME_FTP;
2618-
}
2619-
26202648
public static BINARY_TYPE GetLibraryBinaryType(string libFileName) {
26212649
IntPtr moduleHandle = IntPtr.Zero;
26222650

FlashpointSecurePlayer/WebBrowserMode.cs

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
using System;
1+
using SHDocVw;
2+
3+
using System;
24
using System.Collections.Generic;
35
using System.ComponentModel;
46
using System.Data;
57
using System.Drawing;
68
using System.IO;
79
using System.Linq;
10+
using System.Media;
811
using System.Runtime.InteropServices;
912
using System.Security.Permissions;
1013
using System.Text;
@@ -13,8 +16,6 @@
1316
using static FlashpointSecurePlayer.Shared;
1417
using static FlashpointSecurePlayer.Shared.Exceptions;
1518

16-
using SHDocVw;
17-
1819
namespace FlashpointSecurePlayer {
1920
public partial class WebBrowserMode : Form {
2021
private readonly HookProc lowLevelMouseProc;
@@ -380,6 +381,22 @@ public WebBrowserMode(Uri webBrowserURL, bool useFlashActiveXControl = false) {
380381
statusBarStatusStrip.Renderer = new EndEllipsisTextRenderer();
381382
}
382383

384+
private bool addressToolStripSpringTextBoxEntered = false;
385+
386+
public void AddressInvalid() {
387+
// focus the address again, if the user clicked the go button
388+
SystemSounds.Beep.Play();
389+
390+
addressToolStripSpringTextBox.Focus();
391+
addressToolStripSpringTextBox.SelectionStart = addressToolStripSpringTextBox.TextLength;
392+
addressToolStripSpringTextBoxEntered = false;
393+
}
394+
395+
public void AddressValid() {
396+
// unfocus the address before navigation
397+
ActiveControl = null;
398+
}
399+
383400
public void BrowserBack() {
384401
if (closableWebBrowser == null) {
385402
return;
@@ -434,17 +451,20 @@ public void BrowserGo(string url) {
434451
}
435452

436453
if (String.IsNullOrEmpty(url)) {
454+
AddressInvalid();
437455
return;
438456
}
439457

440458
Uri webBrowserURL;
441459

442460
try {
443-
webBrowserURL = new Uri(AddURLProtocol(url));
461+
webBrowserURL = new Uri(ValidateURL(url), UriKind.Absolute);
444462
} catch {
463+
AddressInvalid();
445464
return;
446465
}
447466

467+
AddressValid();
448468
closableWebBrowser.Navigate(webBrowserURL);
449469
}
450470

@@ -889,15 +909,15 @@ private void printButton_Click(object sender, EventArgs e) {
889909
BrowserPrint();
890910
}
891911

892-
private bool addressToolStripSpringTextBoxEntered = false;
893-
894912
private void addressToolStripSpringTextBox_Click(object sender, EventArgs e) {
895-
if (addressToolStripSpringTextBoxEntered) {
896-
addressToolStripSpringTextBoxEntered = false;
913+
if (!addressToolStripSpringTextBoxEntered) {
914+
return;
915+
}
897916

898-
if (String.IsNullOrEmpty(addressToolStripSpringTextBox.SelectedText)) {
899-
addressToolStripSpringTextBox.SelectAll();
900-
}
917+
addressToolStripSpringTextBoxEntered = false;
918+
919+
if (String.IsNullOrEmpty(addressToolStripSpringTextBox.SelectedText)) {
920+
addressToolStripSpringTextBox.SelectAll();
901921
}
902922
}
903923

0 commit comments

Comments
 (0)