Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
755 changes: 379 additions & 376 deletions src/BVNetwork.404Handler.csproj

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions src/Controllers/NotFoundRedirectController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Security;
using System.Web;
using System.Web.Mvc;
using System.Xml;
using BVNetwork.NotFound.Core.CustomRedirects;
using BVNetwork.NotFound.Core.Data;
using BVNetwork.NotFound.Models;
Expand Down Expand Up @@ -274,6 +275,18 @@ public FileUploadJsonResult ImportRedirects(HttpPostedFileBase xmlfile)
return new FileUploadJsonResult { Data = new { message = message } };
}

public XmlActionResult ExportAllRedirects()
{
CheckAccess();
DataStoreHandler dsHandler = new DataStoreHandler();

List<CustomRedirect> redirects = dsHandler.GetCustomRedirects(true);

XmlDocument document = new RedirectsXmlParser().Export(redirects);

return new XmlActionResult(document);
}

[AcceptVerbs(HttpVerbs.Post)]
public FileUploadJsonResult ImportDeleted(HttpPostedFileBase txtFile)
{
Expand Down
205 changes: 127 additions & 78 deletions src/Core/CustomRedirects/RedirectsXmlParser.cs
Original file line number Diff line number Diff line change
@@ -1,78 +1,127 @@
using System.IO;
using System.Xml;
using EPiServer.Logging;

namespace BVNetwork.NotFound.Core.CustomRedirects
{
/// <summary>
/// Class for reading and writing to the custom redirects file
/// </summary>
public class RedirectsXmlParser
{
private static readonly ILogger Logger = LogManager.GetLogger();
private XmlDocument _customRedirectsXmlFile = null;

/// <summary>
/// Reads the custom redirects information from the specified xml file
/// </summary>
/// <param name="virtualFile">The virtual path to the xml file containing redirect settings</param>
public RedirectsXmlParser(Stream xmlContent)
{
_customRedirectsXmlFile = new XmlDocument();
if (xmlContent != null)
{
_customRedirectsXmlFile.Load(xmlContent);
}
else
{
// Not on disk, not in a vpp, construct an empty one
_customRedirectsXmlFile = new XmlDocument();
_customRedirectsXmlFile.InnerXml = "<redirects><urls></urls></redirects>";
Logger.Error("404 Handler: The Custom Redirects file '{0}' does not exist.", xmlContent);
}
}

/// <summary>
/// Parses the xml file and reads all redirects.
/// </summary>
/// <returns>A collection of CustomRedirect objects</returns>
public CustomRedirectCollection Load()
{
const string URLPATH = "/redirects/urls/url";
const string NEWURL = "new";
const string OLDURL = "old";
const string SKIPWILDCARD = "onWildCardMatchSkipAppend";

CustomRedirectCollection redirects = new CustomRedirectCollection();

// Parse all url nodes
XmlNodeList nodes = _customRedirectsXmlFile.SelectNodes(URLPATH);
foreach (XmlNode node in nodes)
{
// Each url new url can have several old values
// we need to create a redirect object for each pair
XmlNode newNode = node.SelectSingleNode(NEWURL);

XmlNodeList oldNodes = node.SelectNodes(OLDURL);
foreach (XmlNode oldNode in oldNodes)
{
bool skipWildCardAppend = false;
XmlAttribute skipWildCardAttr = oldNode.Attributes[SKIPWILDCARD];
if (skipWildCardAttr != null)
{
// If value parsing fails, it will be false by default. We do
// not really care to check if it fails, as we cannot do anything
// about it (throwing an exception is not a good idea here)
bool.TryParse(skipWildCardAttr.Value, out skipWildCardAppend);
}

// Create new custom redirect nodes
CustomRedirect redirect = new CustomRedirect(oldNode.InnerText, newNode.InnerText, skipWildCardAppend);
redirects.Add(redirect);
}
}

return redirects;
}
}
}
using System.Collections.Generic;
using System.IO;
using System.Xml;
using EPiServer.Logging;

namespace BVNetwork.NotFound.Core.CustomRedirects
{
/// <summary>
/// Class for reading and writing to the custom redirects file
/// </summary>
public class RedirectsXmlParser
{
private static readonly ILogger Logger = LogManager.GetLogger();
private XmlDocument _customRedirectsXmlFile = null;

const string NEWURL = "new";
const string OLDURL = "old";
const string SKIPWILDCARD = "onWildCardMatchSkipAppend";

/// <summary>
/// Reads the custom redirects information from the specified xml file
/// </summary>
/// <param name="virtualFile">The virtual path to the xml file containing redirect settings</param>
public RedirectsXmlParser(Stream xmlContent)
{
_customRedirectsXmlFile = new XmlDocument();
if (xmlContent != null)
{
_customRedirectsXmlFile.Load(xmlContent);
}
else
{
// Not on disk, not in a vpp, construct an empty one
_customRedirectsXmlFile = new XmlDocument();
_customRedirectsXmlFile.InnerXml = "<redirects><urls></urls></redirects>";
Logger.Error("404 Handler: The Custom Redirects file '{0}' does not exist.", xmlContent);
}
}

public RedirectsXmlParser()
{
}

/// <summary>
/// Parses the xml file and reads all redirects.
/// </summary>
/// <returns>A collection of CustomRedirect objects</returns>
public CustomRedirectCollection Load()
{
const string URLPATH = "/redirects/urls/url";

CustomRedirectCollection redirects = new CustomRedirectCollection();

// Parse all url nodes
XmlNodeList nodes = _customRedirectsXmlFile.SelectNodes(URLPATH);
foreach (XmlNode node in nodes)
{
// Each url new url can have several old values
// we need to create a redirect object for each pair
XmlNode newNode = node.SelectSingleNode(NEWURL);

XmlNodeList oldNodes = node.SelectNodes(OLDURL);
foreach (XmlNode oldNode in oldNodes)
{
bool skipWildCardAppend = false;
XmlAttribute skipWildCardAttr = oldNode.Attributes[SKIPWILDCARD];
if (skipWildCardAttr != null)
{
// If value parsing fails, it will be false by default. We do
// not really care to check if it fails, as we cannot do anything
// about it (throwing an exception is not a good idea here)
bool.TryParse(skipWildCardAttr.Value, out skipWildCardAppend);
}

// Create new custom redirect nodes
CustomRedirect redirect = new CustomRedirect(oldNode.InnerText, newNode.InnerText, skipWildCardAppend);
redirects.Add(redirect);
}
}

return redirects;
}

public XmlDocument Export(List<CustomRedirect> redirects)
{
XmlDocument document = new XmlDocument();
XmlDeclaration xmlDeclaration = document.CreateXmlDeclaration("1.0", "UTF-8", null);
XmlElement root = document.DocumentElement;
document.InsertBefore(xmlDeclaration, root);

XmlElement redirectsElement = document.CreateElement(string.Empty, "redirects", string.Empty);
document.AppendChild(redirectsElement);

XmlElement urlsElement = document.CreateElement(string.Empty, "urls", string.Empty);
redirectsElement.AppendChild(urlsElement);

foreach (var redirect in redirects)
{
if (string.IsNullOrWhiteSpace(redirect.OldUrl) || string.IsNullOrWhiteSpace(redirect.NewUrl))
{
continue;
}

XmlElement urlElement = document.CreateElement(string.Empty, "url", string.Empty);

XmlElement oldElement = document.CreateElement(string.Empty, OLDURL, string.Empty);
oldElement.AppendChild(document.CreateTextNode(redirect.OldUrl.Trim()));
if (redirect.WildCardSkipAppend)
{
XmlAttribute wildCardAttribute = document.CreateAttribute(string.Empty, SKIPWILDCARD, string.Empty);
wildCardAttribute.Value = "true";
oldElement.Attributes.Append(wildCardAttribute);
}

XmlElement newElement = document.CreateElement(string.Empty, NEWURL, string.Empty);
newElement.AppendChild(document.CreateTextNode(redirect.NewUrl.Trim()));

urlElement.AppendChild(oldElement);
urlElement.AppendChild(newElement);

urlsElement.AppendChild(urlElement);
}

return document;
}
}
}
39 changes: 39 additions & 0 deletions src/Core/CustomRedirects/XmlActionResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;
using System.Text;
using System.Web.Mvc;
using System.Xml;

namespace BVNetwork.NotFound.Core.CustomRedirects
{
public sealed class XmlActionResult : ActionResult
{
private readonly XmlDocument _document;

public Formatting Formatting { get; set; }
public string MimeType { get; set; }

public XmlActionResult(XmlDocument document)
{
if (document == null)
{
throw new ArgumentNullException(nameof(document));
}

_document = document;

MimeType = "text/xml";
Formatting = Formatting.Indented;
}

public override void ExecuteResult(ControllerContext context)
{
context.HttpContext.Response.Clear();
context.HttpContext.Response.Buffer = true;
context.HttpContext.Response.ContentType = MimeType;
context.HttpContext.Response.AddHeader("content-disposition", "attachment; filename=customRedirects.xml");

using (var writer = new XmlTextWriter(context.HttpContext.Response.OutputStream, Encoding.UTF8) { Formatting = Formatting })
_document.WriteTo(writer);
}
}
}
Loading