2014-05-30 21:09:13 +12:00
|
|
|
|
#region License Information (GPL v3)
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
ShareX - A program that allows you to take screenshots and share any file type
|
2017-01-11 21:39:40 +13:00
|
|
|
|
Copyright (c) 2007-2017 ShareX Team
|
2014-05-30 21:09:13 +12:00
|
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
|
modify it under the terms of the GNU General Public License
|
|
|
|
|
as published by the Free Software Foundation; either version 2
|
|
|
|
|
of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
|
|
|
|
|
Optionally you can also view the license at <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#endregion License Information (GPL v3)
|
|
|
|
|
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
2014-06-28 12:22:56 +12:00
|
|
|
|
using System.Diagnostics;
|
2014-06-10 08:00:59 +12:00
|
|
|
|
using System.Globalization;
|
2014-05-30 21:09:13 +12:00
|
|
|
|
using System.Linq;
|
2014-06-10 08:00:59 +12:00
|
|
|
|
using System.Text;
|
2014-05-30 21:09:13 +12:00
|
|
|
|
using System.Text.RegularExpressions;
|
2014-06-28 12:22:56 +12:00
|
|
|
|
using System.Web;
|
2014-05-30 21:09:13 +12:00
|
|
|
|
|
2014-12-11 09:25:20 +13:00
|
|
|
|
namespace ShareX.HelpersLib
|
2014-05-30 21:09:13 +12:00
|
|
|
|
{
|
|
|
|
|
public static class URLHelpers
|
|
|
|
|
{
|
2014-06-28 12:22:56 +12:00
|
|
|
|
public static void OpenURL(string url)
|
|
|
|
|
{
|
|
|
|
|
if (!string.IsNullOrEmpty(url))
|
|
|
|
|
{
|
|
|
|
|
TaskEx.Run(() =>
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
2015-01-12 22:14:59 +13:00
|
|
|
|
if (!string.IsNullOrEmpty(HelpersOptions.BrowserPath))
|
|
|
|
|
{
|
|
|
|
|
Process.Start(HelpersOptions.BrowserPath, url);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Process.Start(url);
|
|
|
|
|
}
|
2015-08-08 22:11:19 +12:00
|
|
|
|
|
|
|
|
|
DebugHelper.WriteLine("URL opened: " + url);
|
2014-06-28 12:22:56 +12:00
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
DebugHelper.WriteException(e, string.Format("OpenURL({0}) failed", url));
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-10 08:00:59 +12:00
|
|
|
|
private static string Encode(string text, string unreservedCharacters)
|
|
|
|
|
{
|
|
|
|
|
StringBuilder result = new StringBuilder();
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrEmpty(text))
|
|
|
|
|
{
|
|
|
|
|
foreach (char c in text)
|
|
|
|
|
{
|
|
|
|
|
if (unreservedCharacters.Contains(c))
|
|
|
|
|
{
|
|
|
|
|
result.Append(c);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
byte[] bytes = Encoding.UTF8.GetBytes(c.ToString());
|
|
|
|
|
|
|
|
|
|
foreach (byte b in bytes)
|
|
|
|
|
{
|
|
|
|
|
result.AppendFormat(CultureInfo.InvariantCulture, "%{0:X2}", b);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result.ToString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static string URLEncode(string text)
|
|
|
|
|
{
|
|
|
|
|
return Encode(text, Helpers.URLCharacters);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static string URLPathEncode(string text)
|
|
|
|
|
{
|
|
|
|
|
return Encode(text, Helpers.URLPathCharacters);
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-28 12:22:56 +12:00
|
|
|
|
public static string HtmlEncode(string text)
|
|
|
|
|
{
|
|
|
|
|
char[] chars = HttpUtility.HtmlEncode(text).ToCharArray();
|
|
|
|
|
StringBuilder result = new StringBuilder(chars.Length + (int)(chars.Length * 0.1));
|
|
|
|
|
|
|
|
|
|
foreach (char c in chars)
|
|
|
|
|
{
|
|
|
|
|
int value = Convert.ToInt32(c);
|
|
|
|
|
|
|
|
|
|
if (value > 127)
|
|
|
|
|
{
|
|
|
|
|
result.AppendFormat("&#{0};", value);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
result.Append(c);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result.ToString();
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-31 18:20:20 +12:00
|
|
|
|
public static string URLDecode(string url, int count = 1)
|
|
|
|
|
{
|
|
|
|
|
string temp = null;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < count && url != temp; i++)
|
|
|
|
|
{
|
|
|
|
|
temp = url;
|
|
|
|
|
url = HttpUtility.UrlDecode(url);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return url;
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-10 08:00:59 +12:00
|
|
|
|
public static string CombineURL(string url1, string url2)
|
|
|
|
|
{
|
|
|
|
|
bool url1Empty = string.IsNullOrEmpty(url1);
|
|
|
|
|
bool url2Empty = string.IsNullOrEmpty(url2);
|
|
|
|
|
|
|
|
|
|
if (url1Empty && url2Empty)
|
|
|
|
|
{
|
2016-05-25 06:15:45 +12:00
|
|
|
|
return "";
|
2014-06-10 08:00:59 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (url1Empty)
|
|
|
|
|
{
|
|
|
|
|
return url2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (url2Empty)
|
|
|
|
|
{
|
|
|
|
|
return url1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (url1.EndsWith("/"))
|
|
|
|
|
{
|
|
|
|
|
url1 = url1.Substring(0, url1.Length - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (url2.StartsWith("/"))
|
|
|
|
|
{
|
|
|
|
|
url2 = url2.Remove(0, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return url1 + "/" + url2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static string CombineURL(params string[] urls)
|
|
|
|
|
{
|
|
|
|
|
return urls.Aggregate(CombineURL);
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-25 02:01:35 +12:00
|
|
|
|
public static bool IsValidURL(string url, bool useRegex = true)
|
2014-06-10 08:00:59 +12:00
|
|
|
|
{
|
2017-04-25 02:01:35 +12:00
|
|
|
|
if (string.IsNullOrEmpty(url)) return false;
|
2014-06-10 08:00:59 +12:00
|
|
|
|
|
2017-04-25 02:01:35 +12:00
|
|
|
|
url = url.Trim();
|
2014-06-10 08:00:59 +12:00
|
|
|
|
|
2017-04-25 02:01:35 +12:00
|
|
|
|
if (useRegex)
|
|
|
|
|
{
|
|
|
|
|
// https://gist.github.com/729294
|
|
|
|
|
string pattern =
|
|
|
|
|
"^" +
|
|
|
|
|
// protocol identifier
|
|
|
|
|
"(?:(?:https?|ftp)://)" +
|
|
|
|
|
// user:pass authentication
|
|
|
|
|
"(?:\\S+(?::\\S*)?@)?" +
|
|
|
|
|
"(?:" +
|
|
|
|
|
// IP address exclusion
|
|
|
|
|
// private & local networks
|
|
|
|
|
"(?!(?:10|127)(?:\\.\\d{1,3}){3})" +
|
|
|
|
|
"(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})" +
|
|
|
|
|
"(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" +
|
|
|
|
|
// IP address dotted notation octets
|
|
|
|
|
// excludes loopback network 0.0.0.0
|
|
|
|
|
// excludes reserved space >= 224.0.0.0
|
|
|
|
|
// excludes network & broacast addresses
|
|
|
|
|
// (first & last IP address of each class)
|
|
|
|
|
"(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" +
|
|
|
|
|
"(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" +
|
|
|
|
|
"(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" +
|
|
|
|
|
"|" +
|
|
|
|
|
// host name
|
|
|
|
|
"(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)" +
|
|
|
|
|
// domain name
|
|
|
|
|
"(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*" +
|
|
|
|
|
// TLD identifier
|
|
|
|
|
"(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))" +
|
|
|
|
|
// TLD may end with dot
|
|
|
|
|
"\\.?" +
|
|
|
|
|
")" +
|
|
|
|
|
// port number
|
|
|
|
|
"(?::\\d{2,5})?" +
|
|
|
|
|
// resource path
|
|
|
|
|
"(?:[/?#]\\S*)?" +
|
|
|
|
|
"$";
|
|
|
|
|
|
|
|
|
|
return Regex.IsMatch(url, pattern, RegexOptions.IgnoreCase);
|
|
|
|
|
}
|
2014-06-10 08:00:59 +12:00
|
|
|
|
|
2017-05-02 22:45:57 +12:00
|
|
|
|
return !url.StartsWith("file://") && Uri.IsWellFormedUriString(url, UriKind.Absolute);
|
2014-06-10 08:00:59 +12:00
|
|
|
|
}
|
|
|
|
|
|
2014-05-30 21:09:13 +12:00
|
|
|
|
public static string AddSlash(string url, SlashType slashType)
|
|
|
|
|
{
|
|
|
|
|
return AddSlash(url, slashType, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static string AddSlash(string url, SlashType slashType, int count)
|
|
|
|
|
{
|
|
|
|
|
if (slashType == SlashType.Prefix)
|
|
|
|
|
{
|
|
|
|
|
if (url.StartsWith("/"))
|
|
|
|
|
{
|
|
|
|
|
url = url.Remove(0, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < count; i++)
|
|
|
|
|
{
|
|
|
|
|
url = "/" + url;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (url.EndsWith("/"))
|
|
|
|
|
{
|
|
|
|
|
url = url.Substring(0, url.Length - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < count; i++)
|
|
|
|
|
{
|
|
|
|
|
url += "/";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return url;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-31 18:20:20 +12:00
|
|
|
|
public static string GetFileName(string path)
|
2014-05-30 21:09:13 +12:00
|
|
|
|
{
|
2015-08-28 21:34:54 +12:00
|
|
|
|
if (path.Contains('/'))
|
2014-05-30 21:09:13 +12:00
|
|
|
|
{
|
2015-08-28 21:34:54 +12:00
|
|
|
|
path = path.Substring(path.LastIndexOf('/') + 1);
|
2014-05-30 21:09:13 +12:00
|
|
|
|
}
|
|
|
|
|
|
2015-08-28 21:34:54 +12:00
|
|
|
|
if (path.Contains('?'))
|
2014-05-30 21:09:13 +12:00
|
|
|
|
{
|
2015-08-28 21:34:54 +12:00
|
|
|
|
path = path.Remove(path.IndexOf('?'));
|
2014-05-30 21:09:13 +12:00
|
|
|
|
}
|
|
|
|
|
|
2015-08-29 18:11:37 +12:00
|
|
|
|
if (path.Contains('#'))
|
|
|
|
|
{
|
|
|
|
|
path = path.Remove(path.IndexOf('#'));
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-30 21:09:13 +12:00
|
|
|
|
return path;
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-20 20:23:46 +12:00
|
|
|
|
public static bool IsFileURL(string url)
|
|
|
|
|
{
|
|
|
|
|
int index = url.LastIndexOf('/');
|
|
|
|
|
|
|
|
|
|
if (index < 0)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string path = url.Substring(index + 1);
|
|
|
|
|
|
|
|
|
|
return !string.IsNullOrEmpty(path) && path.Contains(".");
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-30 21:09:13 +12:00
|
|
|
|
public static string GetDirectoryPath(string path)
|
|
|
|
|
{
|
|
|
|
|
if (path.Contains("/"))
|
|
|
|
|
{
|
|
|
|
|
path = path.Substring(0, path.LastIndexOf('/'));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return path;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static List<string> GetPaths(string path)
|
|
|
|
|
{
|
2017-05-02 22:45:57 +12:00
|
|
|
|
List<string> paths = new List<string>();
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < path.Length; i++)
|
2014-05-30 21:09:13 +12:00
|
|
|
|
{
|
2017-05-02 22:45:57 +12:00
|
|
|
|
if (path[i] == '/')
|
|
|
|
|
{
|
|
|
|
|
string currentPath = path.Remove(i);
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrEmpty(currentPath))
|
|
|
|
|
{
|
|
|
|
|
paths.Add(currentPath);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (i == path.Length - 1)
|
2014-05-30 21:09:13 +12:00
|
|
|
|
{
|
2017-05-02 22:45:57 +12:00
|
|
|
|
paths.Add(path);
|
2014-05-30 21:09:13 +12:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-02 22:45:57 +12:00
|
|
|
|
return paths;
|
2014-05-30 21:09:13 +12:00
|
|
|
|
}
|
|
|
|
|
|
2016-04-08 02:50:41 +12:00
|
|
|
|
private static readonly string[] URLPrefixes = new string[] { "http://", "https://", "ftp://", "ftps://", "file://", "//" };
|
2014-05-30 21:09:13 +12:00
|
|
|
|
|
2015-06-29 07:30:55 +12:00
|
|
|
|
public static bool HasPrefix(string url)
|
|
|
|
|
{
|
|
|
|
|
return URLPrefixes.Any(x => url.StartsWith(x, StringComparison.InvariantCultureIgnoreCase));
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-08 02:50:41 +12:00
|
|
|
|
public static string FixPrefix(string url, string prefix = "http://")
|
2014-08-07 03:55:48 +12:00
|
|
|
|
{
|
2016-04-08 02:50:41 +12:00
|
|
|
|
if (!string.IsNullOrEmpty(url) && !HasPrefix(url))
|
2014-08-07 03:55:48 +12:00
|
|
|
|
{
|
2016-04-08 02:50:41 +12:00
|
|
|
|
return prefix + url;
|
2014-08-07 03:55:48 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return url;
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-08 02:50:41 +12:00
|
|
|
|
public static string ForcePrefix(string url, string prefix = "https://")
|
2015-06-10 06:26:11 +12:00
|
|
|
|
{
|
2016-04-08 02:50:41 +12:00
|
|
|
|
if (!string.IsNullOrEmpty(url))
|
2015-06-10 06:26:11 +12:00
|
|
|
|
{
|
2016-04-08 02:50:41 +12:00
|
|
|
|
url = prefix + RemovePrefixes(url);
|
2015-06-10 06:26:11 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return url;
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-30 21:09:13 +12:00
|
|
|
|
public static string RemovePrefixes(string url)
|
|
|
|
|
{
|
|
|
|
|
foreach (string prefix in URLPrefixes)
|
|
|
|
|
{
|
|
|
|
|
if (url.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
url = url.Remove(0, prefix.Length);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return url;
|
|
|
|
|
}
|
2016-03-06 05:23:53 +13:00
|
|
|
|
|
2017-09-24 20:30:03 +13:00
|
|
|
|
public static string GetHostName(string url)
|
2016-03-06 05:23:53 +13:00
|
|
|
|
{
|
2017-09-24 20:30:03 +13:00
|
|
|
|
if (!string.IsNullOrEmpty(url) && Uri.TryCreate(url, UriKind.Absolute, out Uri uri))
|
2016-03-06 05:23:53 +13:00
|
|
|
|
{
|
|
|
|
|
string host = uri.Host;
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrEmpty(host))
|
|
|
|
|
{
|
|
|
|
|
if (host.StartsWith("www.", StringComparison.InvariantCultureIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
host = host.Substring(4);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return host;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return url;
|
|
|
|
|
}
|
2017-03-20 12:53:32 +13:00
|
|
|
|
|
2017-09-24 20:14:27 +13:00
|
|
|
|
public static string CreateQuery(Dictionary<string, string> args, bool customEncoding = false)
|
2017-03-20 12:53:32 +13:00
|
|
|
|
{
|
2017-09-24 20:14:27 +13:00
|
|
|
|
if (args != null && args.Count > 0)
|
2017-03-20 12:53:32 +13:00
|
|
|
|
{
|
2017-09-24 20:14:27 +13:00
|
|
|
|
return string.Join("&", args.Select(x => x.Key + "=" + (customEncoding ? URLEncode(x.Value) : HttpUtility.UrlEncode(x.Value))).ToArray());
|
2017-03-20 12:53:32 +13:00
|
|
|
|
}
|
|
|
|
|
|
2017-09-24 20:14:27 +13:00
|
|
|
|
return "";
|
2017-03-20 12:53:32 +13:00
|
|
|
|
}
|
|
|
|
|
|
2017-09-24 20:14:27 +13:00
|
|
|
|
public static string CreateQuery(string url, Dictionary<string, string> args, bool customEncoding = false)
|
2017-03-20 12:53:32 +13:00
|
|
|
|
{
|
2017-09-24 20:14:27 +13:00
|
|
|
|
string query = CreateQuery(args, customEncoding);
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrEmpty(query))
|
2017-03-20 12:53:32 +13:00
|
|
|
|
{
|
2017-09-24 20:14:27 +13:00
|
|
|
|
return url + "?" + query;
|
2017-03-20 12:53:32 +13:00
|
|
|
|
}
|
|
|
|
|
|
2017-09-24 20:14:27 +13:00
|
|
|
|
return url;
|
2017-03-20 12:53:32 +13:00
|
|
|
|
}
|
2017-08-07 04:18:30 +12:00
|
|
|
|
|
|
|
|
|
public static string RemoveQuery(string url)
|
|
|
|
|
{
|
|
|
|
|
if (!string.IsNullOrEmpty(url))
|
|
|
|
|
{
|
|
|
|
|
int index = url.IndexOf("?");
|
|
|
|
|
|
|
|
|
|
if (index > -1)
|
|
|
|
|
{
|
|
|
|
|
return url.Remove(index);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return url;
|
|
|
|
|
}
|
2014-05-30 21:09:13 +12:00
|
|
|
|
}
|
|
|
|
|
}
|