diff --git a/src/BVNetwork.404Handler.csproj b/src/BVNetwork.404Handler.csproj index 30e211d..4df356f 100644 --- a/src/BVNetwork.404Handler.csproj +++ b/src/BVNetwork.404Handler.csproj @@ -1,384 +1,387 @@ - - - - - Local - 9.0.30729 - 2.0 - {DFBF0553-7E44-44BF-A59F-F94F9493FC17} - Debug - AnyCPU - - - - - BVNetwork.EPi404 - - - JScript - Grid - IE50 - false - Library - BVNetwork.NotFound - OnBuildSuccess - - - - - - - 4.0 - v4.5 - false - - - - - - - - - bin\Debug\ - false - 285212672 - false - - - DEBUG;TRACE - - - true - 4096 - false - - - false - false - false - false - 4 - full - prompt - false - - - bin\Release\ - false - 285212672 - false - - - TRACE - - - false - 4096 - false - - - true - false - false - false - 4 - none - prompt - false - - - - - - - - - - - - - ASPXCodeBehind - - - ASPXCodeBehind - - - - - - - - - - - - - - - - - - - - - ASPXCodeBehind - - - ASPXCodeBehind - - - ASPXCodeBehind - - - ASPXCodeBehind - - - ASPXCodeBehind - - - - ASPXCodeBehind - - - Bvn\FileNotFound\Configuration\Bvn404HandlerConfiguration.csd.cs - - - Code - - - Code - - - Code - - - - - - - - - - - - ASPXCodeBehind - - - Code - - - Code - - - Code - - - Code - - - Code - - - ASPXCodeBehind - - - Designer - - - - - - - - - packages\Castle.Core.3.2.0\lib\net45\Castle.Core.dll - True - - - packages\Castle.Windsor.3.2.0\lib\net45\Castle.Windsor.dll - True - - - packages\EPiServer.CMS.Core.9.0.0\lib\net45\EPiServer.dll - True - - - packages\EPiServer.Framework.9.0.0\lib\net45\EPiServer.ApplicationModules.dll - True - - - packages\EPiServer.CMS.UI.Core.9.0.0\lib\net45\EPiServer.Cms.Shell.UI.dll - True - - - packages\EPiServer.CMS.Core.9.0.0\lib\net45\EPiServer.Configuration.dll - True - - - packages\EPiServer.Framework.9.0.0\lib\net45\EPiServer.Data.dll - True - - - packages\EPiServer.Framework.9.0.0\lib\net45\EPiServer.Data.Cache.dll - True - - - packages\EPiServer.CMS.Core.9.0.0\lib\net45\EPiServer.Enterprise.dll - True - - - packages\EPiServer.Framework.9.0.0\lib\net45\EPiServer.Events.dll - True - - - packages\EPiServer.Framework.9.0.0\lib\net45\EPiServer.Framework.dll - True - - - packages\EPiServer.CMS.Core.9.0.0\lib\net45\EPiServer.ImageLibrary.dll - True - - - packages\EPiServer.Framework.9.0.0\lib\net45\EPiServer.Licensing.dll - True - - - packages\EPiServer.CMS.Core.9.0.0\lib\net45\EPiServer.LinkAnalyzer.dll - True - - - packages\EPiServer.Framework.9.0.0\lib\net45\EPiServer.Shell.dll - True - - - packages\EPiServer.CMS.UI.Core.9.0.0\lib\net45\EPiServer.Shell.UI.dll - True - - - packages\EPiServer.CMS.UI.Core.9.0.0\lib\net45\EPiServer.UI.dll - True - - - packages\EPiServer.CMS.Core.9.0.0\lib\net45\EPiServer.Web.WebControls.dll - True - - - packages\EPiServer.CMS.Core.9.0.0\lib\net45\EPiServer.XForms.dll - True - - - packages\DotNetZip.1.9.1.8\lib\net20\Ionic.Zip.dll - True - - - - packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll - True - - - packages\Newtonsoft.Json.5.0.8\lib\net45\Newtonsoft.Json.dll - True - - - packages\structuremap-signed.3.1.6.186\lib\net40\StructureMap.Net4.dll - True - - - packages\structuremap.web-signed.3.1.6.186\lib\net40\StructureMap.Web.dll - True - - - - - - - packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.Helpers.dll - True - - - packages\Microsoft.AspNet.Mvc.4.0.20710.0\lib\net40\System.Web.Mvc.dll - True - - - packages\Microsoft.AspNet.Razor.2.0.20710.0\lib\net40\System.Web.Razor.dll - True - - - packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.dll - True - - - packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.Deployment.dll - True - - - packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.Razor.dll - True - - - - - - - - 10.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - - - - - - - - - - - - - - - - - - + + + + + Local + 9.0.30729 + 2.0 + {DFBF0553-7E44-44BF-A59F-F94F9493FC17} + Debug + AnyCPU + + + + + BVNetwork.EPi404 + + + JScript + Grid + IE50 + false + Library + BVNetwork.NotFound + OnBuildSuccess + + + + + + + 4.0 + v4.5 + false + + + + + + + + + bin\Debug\ + false + 285212672 + false + + + DEBUG;TRACE + + + true + 4096 + false + + + false + false + false + false + 4 + full + prompt + false + + + bin\Release\ + false + 285212672 + false + + + TRACE + + + false + 4096 + false + + + true + false + false + false + 4 + none + prompt + false + + + + + + + + + + + + + + ASPXCodeBehind + + + ASPXCodeBehind + + + + + + + + + + + + + + + + + + + + ASPXCodeBehind + + + ASPXCodeBehind + + + ASPXCodeBehind + + + ASPXCodeBehind + + + ASPXCodeBehind + + + ASPXCodeBehind + + + + ASPXCodeBehind + + + Bvn\FileNotFound\Configuration\Bvn404HandlerConfiguration.csd.cs + + + Code + + + Code + + + Code + + + + + + + + + + + + ASPXCodeBehind + + + Code + + + Code + + + Code + + + Code + + + Code + + + ASPXCodeBehind + + + Designer + + + + + + + + + packages\Castle.Core.3.2.0\lib\net45\Castle.Core.dll + True + + + packages\Castle.Windsor.3.2.0\lib\net45\Castle.Windsor.dll + True + + + packages\EPiServer.CMS.Core.9.0.0\lib\net45\EPiServer.dll + True + + + packages\EPiServer.Framework.9.0.0\lib\net45\EPiServer.ApplicationModules.dll + True + + + packages\EPiServer.CMS.UI.Core.9.0.0\lib\net45\EPiServer.Cms.Shell.UI.dll + True + + + packages\EPiServer.CMS.Core.9.0.0\lib\net45\EPiServer.Configuration.dll + True + + + packages\EPiServer.Framework.9.0.0\lib\net45\EPiServer.Data.dll + True + + + packages\EPiServer.Framework.9.0.0\lib\net45\EPiServer.Data.Cache.dll + True + + + packages\EPiServer.CMS.Core.9.0.0\lib\net45\EPiServer.Enterprise.dll + True + + + packages\EPiServer.Framework.9.0.0\lib\net45\EPiServer.Events.dll + True + + + packages\EPiServer.Framework.9.0.0\lib\net45\EPiServer.Framework.dll + True + + + packages\EPiServer.CMS.Core.9.0.0\lib\net45\EPiServer.ImageLibrary.dll + True + + + packages\EPiServer.Framework.9.0.0\lib\net45\EPiServer.Licensing.dll + True + + + packages\EPiServer.CMS.Core.9.0.0\lib\net45\EPiServer.LinkAnalyzer.dll + True + + + packages\EPiServer.Framework.9.0.0\lib\net45\EPiServer.Shell.dll + True + + + packages\EPiServer.CMS.UI.Core.9.0.0\lib\net45\EPiServer.Shell.UI.dll + True + + + packages\EPiServer.CMS.UI.Core.9.0.0\lib\net45\EPiServer.UI.dll + True + + + packages\EPiServer.CMS.Core.9.0.0\lib\net45\EPiServer.Web.WebControls.dll + True + + + packages\EPiServer.CMS.Core.9.0.0\lib\net45\EPiServer.XForms.dll + True + + + packages\DotNetZip.1.9.1.8\lib\net20\Ionic.Zip.dll + True + + + + packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll + True + + + packages\Newtonsoft.Json.5.0.8\lib\net45\Newtonsoft.Json.dll + True + + + packages\structuremap-signed.3.1.6.186\lib\net40\StructureMap.Net4.dll + True + + + packages\structuremap.web-signed.3.1.6.186\lib\net40\StructureMap.Web.dll + True + + + + + + + packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.Helpers.dll + True + + + packages\Microsoft.AspNet.Mvc.4.0.20710.0\lib\net40\System.Web.Mvc.dll + True + + + packages\Microsoft.AspNet.Razor.2.0.20710.0\lib\net40\System.Web.Razor.dll + True + + + packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.dll + True + + + packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.Deployment.dll + True + + + packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.Razor.dll + True + + + + + + + + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + + + + + + + + + + + + + + + + + - - - - $(MSBuildProjectDirectory)\..\ - $(SolutionDir)\.nuget\NuGet.exe - $(SolutionDir)\tmp - $(SolutionDir)\$(ProjectName).nuspec - $(SolutionDir)\$(ProjectName).csproj - - - - - - - - - - - - - - - + ]]> + + + + $(MSBuildProjectDirectory)\..\ + $(SolutionDir)\.nuget\NuGet.exe + $(SolutionDir)\tmp + $(SolutionDir)\$(ProjectName).nuspec + $(SolutionDir)\$(ProjectName).csproj + + + + + + + + + + + + + + + "$(NuGetExe)" pack "$(NuspecFile)" -OutputDirectory "$(OutDir.TrimEnd('\\'))" -Properties Configuration=$(Configuration) - - - - - - + + + + + + \ No newline at end of file diff --git a/src/Controllers/NotFoundRedirectController.cs b/src/Controllers/NotFoundRedirectController.cs index 0a069ed..b1c9780 100644 --- a/src/Controllers/NotFoundRedirectController.cs +++ b/src/Controllers/NotFoundRedirectController.cs @@ -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; @@ -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 redirects = dsHandler.GetCustomRedirects(true); + + XmlDocument document = new RedirectsXmlParser().Export(redirects); + + return new XmlActionResult(document); + } + [AcceptVerbs(HttpVerbs.Post)] public FileUploadJsonResult ImportDeleted(HttpPostedFileBase txtFile) { diff --git a/src/Core/CustomRedirects/RedirectsXmlParser.cs b/src/Core/CustomRedirects/RedirectsXmlParser.cs index 553a0a0..cbdc892 100644 --- a/src/Core/CustomRedirects/RedirectsXmlParser.cs +++ b/src/Core/CustomRedirects/RedirectsXmlParser.cs @@ -1,78 +1,127 @@ -using System.IO; -using System.Xml; -using EPiServer.Logging; - -namespace BVNetwork.NotFound.Core.CustomRedirects -{ - /// - /// Class for reading and writing to the custom redirects file - /// - public class RedirectsXmlParser - { - private static readonly ILogger Logger = LogManager.GetLogger(); - private XmlDocument _customRedirectsXmlFile = null; - - /// - /// Reads the custom redirects information from the specified xml file - /// - /// The virtual path to the xml file containing redirect settings - 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 = ""; - Logger.Error("404 Handler: The Custom Redirects file '{0}' does not exist.", xmlContent); - } - } - - /// - /// Parses the xml file and reads all redirects. - /// - /// A collection of CustomRedirect objects - 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 +{ + /// + /// Class for reading and writing to the custom redirects file + /// + 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"; + + /// + /// Reads the custom redirects information from the specified xml file + /// + /// The virtual path to the xml file containing redirect settings + 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 = ""; + Logger.Error("404 Handler: The Custom Redirects file '{0}' does not exist.", xmlContent); + } + } + + public RedirectsXmlParser() + { + } + + /// + /// Parses the xml file and reads all redirects. + /// + /// A collection of CustomRedirect objects + 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 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; + } + } +} diff --git a/src/Core/CustomRedirects/XmlActionResult.cs b/src/Core/CustomRedirects/XmlActionResult.cs new file mode 100644 index 0000000..0eb71f3 --- /dev/null +++ b/src/Core/CustomRedirects/XmlActionResult.cs @@ -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); + } + } +} diff --git a/src/Views/NotFoundRedirect/Administer.ascx b/src/Views/NotFoundRedirect/Administer.ascx index 6dcdfd9..c80ae79 100644 --- a/src/Views/NotFoundRedirect/Administer.ascx +++ b/src/Views/NotFoundRedirect/Administer.ascx @@ -1,175 +1,196 @@ -<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %> -<%@ Import Namespace="System.Web.Mvc.Html" %> -<%@ Import Namespace="EPiServer.Shell" %> -<%@ Import Namespace="EPiServer.Shell.Web.Mvc.Html" %> +<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %> +<%@ Import Namespace="System.Web.Mvc.Html" %> +<%@ Import Namespace="EPiServer.Shell" %> +<%@ Import Namespace="EPiServer.Shell.Web.Mvc.Html" %> - -
-
-
- + + +
+
+
+ <%=ViewData["information"] ?? Html.Translate("/gadget/redirects/Administerinfo") %> - -
-
-
-
    -
  • ntab"> - <%= Html.ViewLink( + +
+
+
+
    +
  • ntab"> + <%= Html.ViewLink( "Back to redirects", // html helper "", // title "Index", // Action name "", // css class "", new {}) %> -
  • -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - -
-
<%= Html.Translate("/gadget/redirects/deleteignoreinfo") %> -
-
- <% Html.BeginGadgetForm("DeleteAllIgnored"); %> - - <% Html.EndForm(); %> -
-
-
<%= Html.Translate("/gadget/redirects/deleteallSuggestions") %> -
-
- <% Html.BeginGadgetForm("DeleteAllSuggestions"); %> - - <% Html.EndForm(); %> -
-
-
<%= Html.Translate("/gadget/redirects/deleteallredirects") %> -
-
- <% Html.BeginGadgetForm("DeleteAllRedirects"); %> - - <% Html.EndForm(); %> -
-
- <% Html.BeginGadgetForm("DeleteSuggestions"); %> -
<%= Html.Translate("/gadget/redirects/suggesteionsdeleteinfo1") %> - - <%= Html.Translate("/gadget/redirects/suggesteionsdeleteinfo2") %> - - <%= Html.Translate("/gadget/redirects/suggesteionsdeleteinfo3") %> -
- -
- - -
- <% Html.EndForm(); %> -
-
-
- <%= Html.Translate("/gadget/redirects/importinfo") %> - - - -
-
- - -
- -
-
-
-
- <%= Html.Translate("/gadget/redirects/importDeleted") %> - - - -
-
- - -
- -
-
- -
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ <%= Html.Translate("/gadget/redirects/deleteignoreinfo") %> +
+
+ <% Html.BeginGadgetForm("DeleteAllIgnored"); %> + + <% Html.EndForm(); %> +
+
+
+ <%= Html.Translate("/gadget/redirects/deleteallSuggestions") %> +
+
+ <% Html.BeginGadgetForm("DeleteAllSuggestions"); %> + + <% Html.EndForm(); %> +
+
+
+ <%= Html.Translate("/gadget/redirects/deleteallredirects") %> +
+
+ <% Html.BeginGadgetForm("DeleteAllRedirects"); %> + + <% Html.EndForm(); %> +
+
+ <% Html.BeginGadgetForm("DeleteSuggestions"); %> +
+ <%= Html.Translate("/gadget/redirects/suggesteionsdeleteinfo1") %> + + <%= Html.Translate("/gadget/redirects/suggesteionsdeleteinfo2") %> + + <%= Html.Translate("/gadget/redirects/suggesteionsdeleteinfo3") %> +
+ +
+ + +
+ <% Html.EndForm(); %> +
+
+
+ <%= Html.Translate("/gadget/redirects/importinfo") %> + + + +
+
+ + +
+ +
+
+
+
+ <%= Html.Translate("/gadget/redirects/importDeleted") %> + + + +
+
+ + +
+ +
+
+
+ <%= Html.Translate("/gadget/redirects/exportredirects") %> +
+
+ <% Html.BeginForm("ExportAllRedirects", "NotFoundRedirect", new {@class = "epi-gadgetform", target="_blank"}); %> + + <% Html.EndForm(); %> +
+
+ + diff --git a/src/lang/RedirectsGadget.xml b/src/lang/RedirectsGadget.xml index 49c99d5..b5321a4 100644 --- a/src/lang/RedirectsGadget.xml +++ b/src/lang/RedirectsGadget.xml @@ -50,8 +50,9 @@ Permanently delete all ignored suggestions Permanently delete all suggestions Permanently delete all custom redirects - Clean up redirect suggestions or ignored urls, or import redirect from an XML file. + Clean up redirect suggestions or ignored urls, or import/export redirects from/to an XML file. There are currently <b>{0}</b> urls that return a Deleted response. This tells crawlers to remove these urls from their index. + Export redirects to an XML-file