using System;
|
using System.Collections.Generic;
|
using System.Configuration;
|
using System.IO;
|
using System.Linq;
|
using System.Text;
|
using System.Web;
|
using System.Web.Hosting;
|
|
namespace PalGain.Core
|
{
|
/// <summary>
|
/// Represents a common helper
|
/// </summary>
|
public partial class WebHelper : IWebHelper
|
{
|
#region Fields
|
|
private readonly HttpContextBase _httpContext;
|
|
#endregion
|
|
#region Utilities
|
|
protected virtual Boolean IsRequestAvailable(HttpContextBase httpContext)
|
{
|
if (httpContext == null)
|
return false;
|
|
try
|
{
|
if (httpContext.Request == null)
|
return false;
|
}
|
catch (HttpException)
|
{
|
return false;
|
}
|
|
return true;
|
}
|
protected virtual bool TryWriteWebConfig()
|
{
|
try
|
{
|
// In medium trust, "UnloadAppDomain" is not supported. Touch web.config
|
// to force an AppDomain restart.
|
File.SetLastWriteTimeUtc(MapPath("~/web.config"), DateTime.UtcNow);
|
return true;
|
}
|
catch
|
{
|
return false;
|
}
|
}
|
|
protected virtual bool TryWriteGlobalAsax()
|
{
|
try
|
{
|
//When a new plugin is dropped in the Plugins folder and is installed into nopCommerce,
|
//even if the plugin has registered routes for its controllers,
|
//these routes will not be working as the MVC framework couldn't
|
//find the new controller types and couldn't instantiate the requested controller.
|
//That's why you get these nasty errors
|
//i.e "Controller does not implement IController".
|
//The issue is described here: http://www.nopcommerce.com/boards/t/10969/nop-20-plugin.aspx?p=4#51318
|
//The solution is to touch global.asax file
|
File.SetLastWriteTimeUtc(MapPath("~/global.asax"), DateTime.UtcNow);
|
return true;
|
}
|
catch
|
{
|
return false;
|
}
|
}
|
|
#endregion
|
|
#region Methods
|
|
/// <summary>
|
/// Ctor
|
/// </summary>
|
/// <param name="httpContext">HTTP context</param>
|
public WebHelper(HttpContextBase httpContext)
|
{
|
this._httpContext = httpContext;
|
}
|
|
/// <summary>
|
/// Get URL referrer
|
/// </summary>
|
/// <returns>URL referrer</returns>
|
public virtual string GetUrlReferrer()
|
{
|
string referrerUrl = string.Empty;
|
|
//URL referrer is null in some case (for example, in IE 8)
|
if (IsRequestAvailable(_httpContext) && _httpContext.Request.UrlReferrer != null)
|
referrerUrl = _httpContext.Request.UrlReferrer.PathAndQuery;
|
|
return referrerUrl;
|
}
|
|
/// <summary>
|
/// Get context IP address
|
/// </summary>
|
/// <returns>URL referrer</returns>
|
public virtual string GetCurrentIpAddress()
|
{
|
if (!IsRequestAvailable(_httpContext))
|
return string.Empty;
|
|
var result = "";
|
if (_httpContext.Request.Headers != null)
|
{
|
//The X-Forwarded-For (XFF) HTTP header field is a de facto standard
|
//for identifying the originating IP address of a client
|
//connecting to a web server through an HTTP proxy or load balancer.
|
var forwardedHttpHeader = "X-FORWARDED-FOR";
|
if (!String.IsNullOrEmpty(ConfigurationManager.AppSettings["ForwardedHTTPheader"]))
|
{
|
//but in some cases server use other HTTP header
|
//in these cases an administrator can specify a custom Forwarded HTTP header
|
//e.g. CF-Connecting-IP, X-FORWARDED-PROTO, etc
|
forwardedHttpHeader = ConfigurationManager.AppSettings["ForwardedHTTPheader"];
|
}
|
|
//it's used for identifying the originating IP address of a client connecting to a web server
|
//through an HTTP proxy or load balancer.
|
string xff = _httpContext.Request.Headers.AllKeys
|
.Where(x => forwardedHttpHeader.Equals(x, StringComparison.InvariantCultureIgnoreCase))
|
.Select(k => _httpContext.Request.Headers[k])
|
.FirstOrDefault();
|
|
//if you want to exclude private IP addresses, then see http://stackoverflow.com/questions/2577496/how-can-i-get-the-clients-ip-address-in-asp-net-mvc
|
if (!String.IsNullOrEmpty(xff))
|
{
|
string lastIp = xff.Split(new [] { ',' }).FirstOrDefault();
|
result = lastIp;
|
}
|
}
|
|
if (String.IsNullOrEmpty(result) && _httpContext.Request.UserHostAddress != null)
|
{
|
result = _httpContext.Request.UserHostAddress;
|
}
|
|
//some validation
|
if (result == "::1")
|
result = "127.0.0.1";
|
//remove port
|
if (!String.IsNullOrEmpty(result))
|
{
|
int index = result.IndexOf(":", StringComparison.InvariantCultureIgnoreCase);
|
if (index > 0)
|
result = result.Substring(0, index);
|
}
|
return result;
|
|
}
|
|
/// <summary>
|
/// Gets this page name
|
/// </summary>
|
/// <param name="includeQueryString">Value indicating whether to include query strings</param>
|
/// <returns>Page name</returns>
|
public virtual string GetThisPageUrl(bool includeQueryString)
|
{
|
bool useSsl = IsCurrentConnectionSecured();
|
return GetThisPageUrl(includeQueryString, useSsl);
|
}
|
|
/// <summary>
|
/// Gets a value indicating whether current connection is secured
|
/// </summary>
|
/// <returns>true - secured, false - not secured</returns>
|
public virtual bool IsCurrentConnectionSecured()
|
{
|
bool useSsl = false;
|
if (IsRequestAvailable(_httpContext))
|
{
|
useSsl = _httpContext.Request.IsSecureConnection;
|
//when your hosting uses a load balancer on their server then the Request.IsSecureConnection is never got set to true, use the statement below
|
//just uncomment it
|
//useSSL = _httpContext.Request.ServerVariables["HTTP_CLUSTER_HTTPS"] == "on" ? true : false;
|
}
|
|
return useSsl;
|
}
|
|
/// <summary>
|
/// Gets server variable by name
|
/// </summary>
|
/// <param name="name">Name</param>
|
/// <returns>Server variable</returns>
|
public virtual string ServerVariables(string name)
|
{
|
string result = string.Empty;
|
|
try
|
{
|
if (!IsRequestAvailable(_httpContext))
|
return result;
|
|
//put this method is try-catch
|
//as described here http://www.nopcommerce.com/boards/t/21356/multi-store-roadmap-lets-discuss-update-done.aspx?p=6#90196
|
if (_httpContext.Request.ServerVariables[name] != null)
|
{
|
result = _httpContext.Request.ServerVariables[name];
|
}
|
}
|
catch
|
{
|
result = string.Empty;
|
}
|
return result;
|
}
|
|
/// <summary>
|
/// Returns true if the requested resource is one of the typical resources that needn't be processed by the cms engine.
|
/// </summary>
|
/// <param name="request">HTTP Request</param>
|
/// <returns>True if the request targets a static resource file.</returns>
|
/// <remarks>
|
/// These are the file extensions considered to be static resources:
|
/// .css
|
/// .gif
|
/// .png
|
/// .jpg
|
/// .jpeg
|
/// .js
|
/// .axd
|
/// .ashx
|
/// </remarks>
|
public virtual bool IsStaticResource(HttpRequest request)
|
{
|
if (request == null)
|
throw new ArgumentNullException("request");
|
|
string path = request.Path;
|
string extension = VirtualPathUtility.GetExtension(path);
|
|
if (extension == null) return false;
|
|
switch (extension.ToLower())
|
{
|
case ".axd":
|
case ".ashx":
|
case ".bmp":
|
case ".css":
|
case ".gif":
|
case ".htm":
|
case ".html":
|
case ".ico":
|
case ".jpeg":
|
case ".jpg":
|
case ".js":
|
case ".png":
|
case ".rar":
|
case ".zip":
|
return true;
|
}
|
|
return false;
|
}
|
|
/// <summary>
|
/// Maps a virtual path to a physical disk path.
|
/// </summary>
|
/// <param name="path">The path to map. E.g. "~/bin"</param>
|
/// <returns>The physical path. E.g. "c:\inetpub\wwwroot\bin"</returns>
|
public virtual string MapPath(string path)
|
{
|
if (HostingEnvironment.IsHosted)
|
{
|
//hosted
|
return HostingEnvironment.MapPath(path);
|
}
|
|
//not hosted. For example, run in unit tests
|
string baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
path = path.Replace("~/", "").TrimStart('/').Replace('/', '\\');
|
return Path.Combine(baseDirectory, path);
|
}
|
|
/// <summary>
|
/// Modifies query string
|
/// </summary>
|
/// <param name="url">Url to modify</param>
|
/// <param name="queryStringModification">Query string modification</param>
|
/// <param name="anchor">Anchor</param>
|
/// <returns>New url</returns>
|
public virtual string ModifyQueryString(string url, string queryStringModification, string anchor)
|
{
|
if (url == null)
|
url = string.Empty;
|
url = url.ToLowerInvariant();
|
|
if (queryStringModification == null)
|
queryStringModification = string.Empty;
|
queryStringModification = queryStringModification.ToLowerInvariant();
|
|
if (anchor == null)
|
anchor = string.Empty;
|
anchor = anchor.ToLowerInvariant();
|
|
|
string str = string.Empty;
|
string str2 = string.Empty;
|
if (url.Contains("#"))
|
{
|
str2 = url.Substring(url.IndexOf("#") + 1);
|
url = url.Substring(0, url.IndexOf("#"));
|
}
|
if (url.Contains("?"))
|
{
|
str = url.Substring(url.IndexOf("?") + 1);
|
url = url.Substring(0, url.IndexOf("?"));
|
}
|
if (!string.IsNullOrEmpty(queryStringModification))
|
{
|
if (!string.IsNullOrEmpty(str))
|
{
|
var dictionary = new Dictionary<string, string>();
|
foreach (string str3 in str.Split(new [] { '&' }))
|
{
|
if (!string.IsNullOrEmpty(str3))
|
{
|
string[] strArray = str3.Split(new [] { '=' });
|
if (strArray.Length == 2)
|
{
|
if (!dictionary.ContainsKey(strArray[0]))
|
{
|
//do not add value if it already exists
|
//two the same query parameters? theoretically it's not possible.
|
//but MVC has some ugly implementation for checkboxes and we can have two values
|
//find more info here: http://www.mindstorminteractive.com/topics/jquery-fix-asp-net-mvc-checkbox-truefalse-value/
|
//we do this validation just to ensure that the first one is not overridden
|
dictionary[strArray[0]] = strArray[1];
|
}
|
}
|
else
|
{
|
dictionary[str3] = null;
|
}
|
}
|
}
|
foreach (string str4 in queryStringModification.Split(new [] { '&' }))
|
{
|
if (!string.IsNullOrEmpty(str4))
|
{
|
string[] strArray2 = str4.Split(new [] { '=' });
|
if (strArray2.Length == 2)
|
{
|
dictionary[strArray2[0]] = strArray2[1];
|
}
|
else
|
{
|
dictionary[str4] = null;
|
}
|
}
|
}
|
var builder = new StringBuilder();
|
foreach (string str5 in dictionary.Keys)
|
{
|
if (builder.Length > 0)
|
{
|
builder.Append("&");
|
}
|
builder.Append(str5);
|
if (dictionary[str5] != null)
|
{
|
builder.Append("=");
|
builder.Append(dictionary[str5]);
|
}
|
}
|
str = builder.ToString();
|
}
|
else
|
{
|
str = queryStringModification;
|
}
|
}
|
if (!string.IsNullOrEmpty(anchor))
|
{
|
str2 = anchor;
|
}
|
return (url + (string.IsNullOrEmpty(str) ? "" : ("?" + str)) + (string.IsNullOrEmpty(str2) ? "" : ("#" + str2))).ToLowerInvariant();
|
}
|
|
/// <summary>
|
/// Remove query string from url
|
/// </summary>
|
/// <param name="url">Url to modify</param>
|
/// <param name="queryString">Query string to remove</param>
|
/// <returns>New url</returns>
|
public virtual string RemoveQueryString(string url, string queryString)
|
{
|
if (url == null)
|
url = string.Empty;
|
url = url.ToLowerInvariant();
|
|
if (queryString == null)
|
queryString = string.Empty;
|
queryString = queryString.ToLowerInvariant();
|
|
|
string str = string.Empty;
|
if (url.Contains("?"))
|
{
|
str = url.Substring(url.IndexOf("?") + 1);
|
url = url.Substring(0, url.IndexOf("?"));
|
}
|
if (!string.IsNullOrEmpty(queryString))
|
{
|
if (!string.IsNullOrEmpty(str))
|
{
|
var dictionary = new Dictionary<string, string>();
|
foreach (string str3 in str.Split(new [] { '&' }))
|
{
|
if (!string.IsNullOrEmpty(str3))
|
{
|
string[] strArray = str3.Split(new [] { '=' });
|
if (strArray.Length == 2)
|
{
|
dictionary[strArray[0]] = strArray[1];
|
}
|
else
|
{
|
dictionary[str3] = null;
|
}
|
}
|
}
|
dictionary.Remove(queryString);
|
|
var builder = new StringBuilder();
|
foreach (string str5 in dictionary.Keys)
|
{
|
if (builder.Length > 0)
|
{
|
builder.Append("&");
|
}
|
builder.Append(str5);
|
if (dictionary[str5] != null)
|
{
|
builder.Append("=");
|
builder.Append(dictionary[str5]);
|
}
|
}
|
str = builder.ToString();
|
}
|
}
|
return (url + (string.IsNullOrEmpty(str) ? "" : ("?" + str)));
|
}
|
|
/// <summary>
|
/// Gets query string value by name
|
/// </summary>
|
/// <typeparam name="T"></typeparam>
|
/// <param name="name">Parameter name</param>
|
/// <returns>Query string value</returns>
|
public virtual T QueryString<T>(string name)
|
{
|
string queryParam = null;
|
if (IsRequestAvailable(_httpContext) && _httpContext.Request.QueryString[name] != null)
|
queryParam = _httpContext.Request.QueryString[name];
|
|
if (!String.IsNullOrEmpty(queryParam))
|
return CommonHelper.To<T>(queryParam);
|
|
return default(T);
|
}
|
|
/// <summary>
|
/// Restart application domain
|
/// </summary>
|
/// <param name="makeRedirect">A value indicating whether we should made redirection after restart</param>
|
/// <param name="redirectUrl">Redirect URL; empty string if you want to redirect to the current page URL</param>
|
public virtual void RestartAppDomain(bool makeRedirect = false, string redirectUrl = "")
|
{
|
if (CommonHelper.GetTrustLevel() > AspNetHostingPermissionLevel.Medium)
|
{
|
//full trust
|
HttpRuntime.UnloadAppDomain();
|
|
TryWriteGlobalAsax();
|
}
|
else
|
{
|
//medium trust
|
bool success = TryWriteWebConfig();
|
if (!success)
|
{
|
throw new NopException("nopCommerce needs to be restarted due to a configuration change, but was unable to do so." + Environment.NewLine +
|
"To prevent this issue in the future, a change to the web server configuration is required:" + Environment.NewLine +
|
"- run the application in a full trust environment, or" + Environment.NewLine +
|
"- give the application write access to the 'web.config' file.");
|
}
|
|
success = TryWriteGlobalAsax();
|
if (!success)
|
{
|
throw new NopException("nopCommerce needs to be restarted due to a configuration change, but was unable to do so." + Environment.NewLine +
|
"To prevent this issue in the future, a change to the web server configuration is required:" + Environment.NewLine +
|
"- run the application in a full trust environment, or" + Environment.NewLine +
|
"- give the application write access to the 'Global.asax' file.");
|
}
|
}
|
|
// If setting up extensions/modules requires an AppDomain restart, it's very unlikely the
|
// current request can be processed correctly. So, we redirect to the same URL, so that the
|
// new request will come to the newly started AppDomain.
|
if (_httpContext != null && makeRedirect)
|
{
|
if (String.IsNullOrEmpty(redirectUrl))
|
redirectUrl = GetThisPageUrl(true);
|
_httpContext.Response.Redirect(redirectUrl, true /*endResponse*/);
|
}
|
}
|
|
/// <summary>
|
/// Gets a value that indicates whether the client is being redirected to a new location
|
/// </summary>
|
public virtual bool IsRequestBeingRedirected
|
{
|
get
|
{
|
var response = _httpContext.Response;
|
return response.IsRequestBeingRedirected;
|
}
|
}
|
|
/// <summary>
|
/// Gets or sets a value that indicates whether the client is being redirected to a new location using POST
|
/// </summary>
|
public virtual bool IsPostBeingDone
|
{
|
get
|
{
|
if (_httpContext.Items["nop.IsPOSTBeingDone"] == null)
|
return false;
|
return Convert.ToBoolean(_httpContext.Items["nop.IsPOSTBeingDone"]);
|
}
|
set
|
{
|
_httpContext.Items["nop.IsPOSTBeingDone"] = value;
|
}
|
}
|
|
#endregion
|
|
|
public string GetThisPageUrl(bool includeQueryString, bool useSsl)
|
{
|
throw new NotImplementedException();
|
}
|
|
public string GetStoreHost(bool useSsl)
|
{
|
throw new NotImplementedException();
|
}
|
|
public string GetStoreLocation()
|
{
|
throw new NotImplementedException();
|
}
|
|
public string GetStoreLocation(bool useSsl)
|
{
|
throw new NotImplementedException();
|
}
|
}
|
}
|