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
{
///
/// Represents a common helper
///
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
///
/// Ctor
///
/// HTTP context
public WebHelper(HttpContextBase httpContext)
{
this._httpContext = httpContext;
}
///
/// Get URL referrer
///
/// URL referrer
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;
}
///
/// Get context IP address
///
/// URL referrer
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;
}
///
/// Gets this page name
///
/// Value indicating whether to include query strings
/// Page name
public virtual string GetThisPageUrl(bool includeQueryString)
{
bool useSsl = IsCurrentConnectionSecured();
return GetThisPageUrl(includeQueryString, useSsl);
}
///
/// Gets a value indicating whether current connection is secured
///
/// true - secured, false - not secured
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;
}
///
/// Gets server variable by name
///
/// Name
/// Server variable
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;
}
///
/// Returns true if the requested resource is one of the typical resources that needn't be processed by the cms engine.
///
/// HTTP Request
/// True if the request targets a static resource file.
///
/// These are the file extensions considered to be static resources:
/// .css
/// .gif
/// .png
/// .jpg
/// .jpeg
/// .js
/// .axd
/// .ashx
///
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;
}
///
/// Maps a virtual path to a physical disk path.
///
/// The path to map. E.g. "~/bin"
/// The physical path. E.g. "c:\inetpub\wwwroot\bin"
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);
}
///
/// Modifies query string
///
/// Url to modify
/// Query string modification
/// Anchor
/// New url
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();
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();
}
///
/// Remove query string from url
///
/// Url to modify
/// Query string to remove
/// New url
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();
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)));
}
///
/// Gets query string value by name
///
///
/// Parameter name
/// Query string value
public virtual T QueryString(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(queryParam);
return default(T);
}
///
/// Restart application domain
///
/// A value indicating whether we should made redirection after restart
/// Redirect URL; empty string if you want to redirect to the current page URL
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*/);
}
}
///
/// Gets a value that indicates whether the client is being redirected to a new location
///
public virtual bool IsRequestBeingRedirected
{
get
{
var response = _httpContext.Response;
return response.IsRequestBeingRedirected;
}
}
///
/// Gets or sets a value that indicates whether the client is being redirected to a new location using POST
///
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();
}
}
}