using System;
using System.Collections.Generic;
using System.IO;
using System.Web;
using System.Text;
namespace ScrewTurn.Wiki {
///
/// Implements useful URL-handling tools.
///
public static class UrlTools {
///
/// Properly routes the current virtual request to a physical ASP.NET page.
///
public static void RouteCurrentRequest() {
// Extract the physical page name, e.g. MainPage, Edit or Category
string pageName = Path.GetFileNameWithoutExtension(HttpContext.Current.Request.PhysicalPath);
// Exctract the extension, e.g. .ashx or .aspx
string ext = Path.GetExtension(HttpContext.Current.Request.PhysicalPath).ToLowerInvariant();
// Remove trailing dot, .ashx -> ashx
if(ext.Length > 0) ext = ext.Substring(1);
// IIS7+Integrated Pipeline handles all requests through the ASP.NET engine
// All non-interesting files are not processed, such as GIF, CSS, etc.
if(ext != "ashx" && ext != "aspx") return;
// Extract the current namespace, if any
string nspace = GetCurrentNamespace() + "";
if(!string.IsNullOrEmpty(nspace)) pageName = pageName.Substring(nspace.Length + 1); // Trim Namespace. from pageName
string queryString = ""; // Empty or begins with ampersand, not question mark
try {
// This might throw exceptions if 3rd-party modules interfer with the request pipeline
queryString = HttpContext.Current.Request.Url.Query.Replace("?", "&");
}
catch { }
if(ext.Equals("ashx")) {
// Content page requested, process it via Default.aspx
if(!queryString.Contains("NS=")) {
HttpContext.Current.RewritePath("~/Default.aspx?Page=" + Tools.UrlEncode(pageName) + "&NS=" + Tools.UrlEncode(nspace) + queryString);
}
else {
HttpContext.Current.RewritePath("~/Default.aspx?Page=" + Tools.UrlEncode(pageName) + queryString);
}
}
else if(ext.Equals("aspx")) {
// System page requested, redirect to the root of the application
// For example: http://www.server.com/Namespace.Edit.aspx?Page=MainPage -> http://www.server.com/Edit.aspx?Page=MainPage&NS=Namespace
if(!string.IsNullOrEmpty(nspace)) {
if(!queryString.Contains("NS=")) {
HttpContext.Current.RewritePath("~/" + Tools.UrlEncode(pageName) + "." + ext + "?NS=" + Tools.UrlEncode(nspace) + queryString);
}
else {
if(queryString.Length > 1) queryString = "?" + queryString.Substring(1);
HttpContext.Current.RewritePath("~/" + Tools.UrlEncode(pageName) + "." + ext + queryString);
}
}
}
// else nothing to do
}
///
/// Extracts the current namespace from the URL, such as /App/Namespace.Edit.aspx.
///
/// The current namespace, or an empty string. null if the URL format is not specified.
public static string GetCurrentNamespace() {
string filename = Path.GetFileNameWithoutExtension(HttpContext.Current.Request.Path); // e.g. MainPage or Edit or Namespace.MainPage or Namespace.Edit
// Use dot to split the filename
string[] fields = filename.Split('.');
if(fields.Length != 1 && fields.Length != 2) return null; // Unrecognized format
if(fields.Length == 1) return ""; // Just page name
else return fields[0]; // Namespace.Page
}
///
/// Redirects the current response to the specified URL, properly appending the current namespace if any.
///
/// The target URL.
public static void Redirect(string target) {
Redirect(target, true);
}
///
/// Redirects the current response to the specified URL, appending the current namespace if requested.
///
/// The target URL.
/// A value indicating whether to add the namespace.
public static void Redirect(string target, bool addNamespace) {
string nspace = HttpContext.Current.Request["NS"];
if(nspace == null || nspace.Length == 0 || !addNamespace) HttpContext.Current.Response.Redirect(target);
else HttpContext.Current.Response.Redirect(target + (target.Contains("?") ? "&" : "?") + "NS=" + Tools.UrlEncode(nspace));
}
///
/// Builds a URL properly prepending the namespace to the URL.
///
/// The chunks used to build the URL.
/// The complete URL.
public static string BuildUrl(params string[] chunks) {
if(chunks == null) throw new ArgumentNullException("chunks");
if(chunks.Length == 0) return ""; // Shortcut
StringBuilder temp = new StringBuilder(chunks.Length * 10);
foreach(string chunk in chunks) {
temp.Append(chunk);
}
string tempString = temp.ToString();
if(tempString.StartsWith("++")) return tempString.Substring(2);
string nspace = HttpContext.Current.Request["NS"];
if(string.IsNullOrEmpty(nspace)) nspace = null;
if(nspace == null) nspace = GetCurrentNamespace();
if(string.IsNullOrEmpty(nspace)) nspace = null;
else nspace = Pages.FindNamespace(nspace).Name;
if(nspace != null) {
string tempStringLower = tempString.ToLowerInvariant();
if((tempStringLower.Contains(".ashx") || tempStringLower.Contains(".aspx")) && !tempString.StartsWith(Tools.UrlEncode(nspace) + ".")) temp.Insert(0, nspace + ".");
}
return temp.ToString();
}
///
/// Builds a URL properly appendind the NS parameter if appropriate.
///
/// The destination .
/// The chunks to append.
public static void BuildUrl(StringBuilder destination, params string[] chunks) {
if(destination == null) throw new ArgumentNullException("destination");
destination.Append(BuildUrl(chunks));
}
///
/// Redirects to the default page of the current namespace.
///
public static void RedirectHome() {
Redirect(BuildUrl(Settings.DefaultPage, Settings.PageExtension));
}
}
}