Provides the working environment for code within Sage.
Inheritance: IXmlConvertible
Esempio n. 1
0
        /// <summary>
        /// Returns a copy of this instance, setting its category and locale to the specified values.
        /// </summary>
        /// <param name="category">The category to set on the resulting instance.</param>
        /// <param name="locale">The locale to set on the resulting instance.</param>
        /// <returns>A <see cref="SageContext"/> copy of this instance, with its category and locale set to the
        /// specified <paramref name="category"/> and <paramref name="locale"/>.</returns>
        internal SageContext Copy(string category, string locale)
        {
            SageContext result = new SageContext(this);
            result.Category = category;
            result.Locale = locale;

            return result;
        }
Esempio n. 2
0
        internal static XmlNode ProcessSageBaseHrefElement(SageContext context, XmlNode node)
        {
            Contract.Requires<ArgumentNullException>(node != null);
            if (node.SelectSingleElement("ancestor::sage:literal", XmlNamespaces.Manager) != null)
                return node;

            XmlElement result = node.OwnerDocument.CreateElement("base", XmlNamespaces.XHtmlNamespace);
            result.SetAttribute("href", context.BaseHref);

            return result;
        }
Esempio n. 3
0
        internal static XmlNode ProcessSageUrlElement(SageContext context, XmlNode node)
        {
            Contract.Requires<ArgumentNullException>(node != null);
            if (node.SelectSingleElement("ancestor::sage:literal", XmlNamespaces.Manager) != null)
                return node;

            string linkHref = context.Url.GetUrl((XmlElement) node);

            if (!string.IsNullOrEmpty(linkHref))
            {
                if (node.NodeType == XmlNodeType.Element)
                    return node.OwnerDocument.CreateTextNode(linkHref);
            }

            return node;
        }
Esempio n. 4
0
        internal static string GetLinkFunction(SageContext context, params string[] arguments)
        {
            var linkArguments = new LinkArguments(arguments, true, "encode", "absolute");
            var qualify = linkArguments.Switches["absolute"];

            var result = context.Url.GetUrl(linkArguments.LinkName, linkArguments.QueryString, linkArguments.HashString, qualify);
            if (linkArguments.Switches["encode"] && !string.IsNullOrEmpty(result))
                result = HttpUtility.UrlEncode(result);

            return result;
        }
Esempio n. 5
0
        internal static string GetSelfFunction(SageContext context, params string[] arguments)
        {
            var linkArguments = new LinkArguments(arguments, false, "encode", "absolute");
            var currentUrl = linkArguments.Switches["absolute"]
                ? context.Url.RawUrl
                : context.Url.RawPathAndQuery;

            var paramQuery = new QueryString(parameterSeparators);
            if (currentUrl.Contains("?"))
            {
                var questionIndex = currentUrl.IndexOf("?", StringComparison.Ordinal);
                paramQuery.Parse(currentUrl.Substring(questionIndex + 1));
                currentUrl = currentUrl.Substring(0, questionIndex);
            }

            paramQuery.Merge(linkArguments.QueryString);
            var result = string.Concat(currentUrl, paramQuery.ToString("?"), string.IsNullOrEmpty(linkArguments.HashString)
                ? string.Empty
                : string.Concat("#", linkArguments.HashString));

            if (linkArguments.Switches["encode"] && !string.IsNullOrEmpty(result))
                result = HttpUtility.UrlEncode(result);

            return result;
        }
Esempio n. 6
0
 /// <summary>
 /// Starts this instance.
 /// </summary>
 /// <param name="context">The context.</param>
 protected static void Start(SageContext context)
 {
     Project.IsStarted = true;
 }
Esempio n. 7
0
        /// <summary>
        /// Handles the Error event of the Application control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected virtual void Application_Error(object sender, EventArgs e)
        {
            Exception exception = this.Server.GetLastError();
            if (exception == null)
                return;

            if (exception is ThreadAbortException)
                return;

            log.Fatal(exception.Message, exception);

            StringBuilder html = new StringBuilder();
            TextWriter writer = new StringWriter(html);
            SageContext context = new SageContext(this.Context);

            SageException sageException = SageHelpException.Create(exception);
            if (((SageHelpException) sageException).Problem.Type == ProblemType.Unknown)
                sageException = exception is SageHelpException
                ? (SageHelpException) exception
                : new SageException(exception);

            if (this.IsRequestAvailable)
            {
                sageException.Render(writer, context);
            }
            else
            {
                sageException.RenderWithoutContext(writer);
            }

            writer.Close();
            writer.Dispose();

            this.Response.ContentType = "text/html";
            this.Response.Write(html.ToString());
            this.Response.Cache.SetCacheability(HttpCacheability.NoCache);
            this.Response.Cache.SetNoStore();
            this.Response.End();
        }
Esempio n. 8
0
        internal static string IIf(SageContext context, params string[] arguments)
        {
            if (arguments.Length < 3)
                return string.Empty;

            string condition = context.textEvaluator.Process(arguments[0]);
            string result1 = arguments[1];
            string result2 = arguments[2];

            return !string.IsNullOrWhiteSpace(condition) ? result1 : result2;
        }
Esempio n. 9
0
        internal static string IsNull(SageContext context, params string[] arguments)
        {
            if (arguments.Length < 2)
                return string.Empty;

            string result1 = arguments[0];
            string result2 = arguments[1];

            return !string.IsNullOrWhiteSpace(result1) ? result1 : result2;
        }
Esempio n. 10
0
        internal static string GetSessionParam(SageContext context, params string[] arguments)
        {
            if (arguments.Length == 0)
                return string.Empty;

            return context.Session[arguments[0]] as string;
        }
Esempio n. 11
0
        internal static string GetVariable(SageContext context, params string[] arguments)
        {
            if (arguments.Length < 1)
                return string.Empty;

            string name = arguments[0];
            string locale = arguments.Length < 2 ? null : arguments[1];

            return context.GetProjectVariable(name, locale);
        }
Esempio n. 12
0
        internal static string GetRequestParam(SageContext context, params string[] arguments)
        {
            if (arguments.Length == 0)
                return string.Empty;

            return context.Request[arguments[0]];
        }
Esempio n. 13
0
 /// <summary>
 /// Initializes a new instance of the <see cref="SageContext"/> class, using an existing context instance.
 /// </summary>
 /// <param name="context">An existing <see cref="SageContext"/> to use to initialize this instance.</param>
 /// <param name="pathMapper">The function to use for resolving relative paths.</param>
 /// <param name="config">The project configuration to use with this context instance.</param>
 public SageContext(SageContext context, ProjectConfiguration config = null, Func<string, string> pathMapper = null)
     : this(context, context.Category, config)
 {
     if (pathMapper != null)
         this.pathMapper = pathMapper;
 }
Esempio n. 14
0
        private static string GetContextProperty(SageContext context, string propName, string propKey)
        {
            const BindingFlags BindingFlags =
                BindingFlags.IgnoreCase |
                BindingFlags.Public |
                BindingFlags.Instance |
                BindingFlags.Static;

            PropertyInfo property = context.GetType().GetProperty(propName, BindingFlags);
            if (property == null)
            {
                log.ErrorFormat(
                    "Property name '{0}' is invalid. Please make sure the name matches a property of SageContext",
                    propName);

                return null;
            }

            object value = property.GetValue(context, null);
            if (value != null)
            {
                if (!string.IsNullOrEmpty(propKey))
                {
                    if (value is NameValueCollection)
                        return ((NameValueCollection) value)[propKey];

                    object subProperty = value.GetType().GetProperty(propKey, BindingFlags);
                    if (subProperty != null)
                    {
                        return subProperty.ToString();
                    }

                    log.ErrorFormat(
                        "The context property '{0}' is not a NameValue collection and it doesn't have a property named '{1}'.",
                        propName, propKey);

                    return null;
                }

                return value.ToString();
            }

            return null;
        }
Esempio n. 15
0
        /// <summary>
        /// Initializes the application using the specified project configuration instance.
        /// </summary>
        /// <param name="context">The context in which this method is being executed.</param>
        internal static void Initialize(SageContext context)
        {
            ViewEngines.Engines.Clear();
            ViewEngines.Engines.Add(new XsltViewEngine());
            ViewEngines.Engines.Add(new WebFormViewEngine());

            Project.InitializeConfiguration(context);

            //// The routes need to be re-registered after the assemblies get updated
            Project.AssembliesUpdated += (sender, args) => Project.RegisterRoutes();
            Project.RegisterRoutes();

            var controller = Project.Configuration.Routing.DefaultController;
            var action = Project.Configuration.Routing.DefaultAction;
            var routeName = string.Format("{0}.{1}", controller, action);

            log.DebugFormat("Manually registering route '*' to {0}", routeName);
            RouteTable.Routes.MapRouteLowercase(
                routeName,
                "{*path}",
                new Dictionary<string, object> { { "controller", controller.Replace("Controller", string.Empty) }, { "action", action } });

            projectIsReady = true;
        }
Esempio n. 16
0
        internal static XmlNode ProcessBaseHrefNode(SageContext context, XmlNode node)
        {
            if (node.SelectSingleElement("ancestor::sage:literal", XmlNamespaces.Manager) != null)
                return node;

            XmlElement result = node.OwnerDocument.CreateElement("base", XmlNamespaces.XHtmlNamespace);
            result.SetAttribute("href", context.BaseHref);
            return result;
        }
Esempio n. 17
0
        internal static SageContext InitializeConfiguration(SageContext context)
        {
            string projectConfigPathBinDir = Path.Combine(Project.AssemblyCodeBaseDirectory, ProjectConfiguration.ProjectConfigName);
            string projectConfigPathProjDir = Path.Combine(Project.AssemblyCodeBaseDirectory, "..\\" + ProjectConfiguration.ProjectConfigName);

            string projectConfigPath = projectConfigPathBinDir;
            if (File.Exists(projectConfigPathProjDir))
            {
                projectConfigPath = projectConfigPathProjDir;
            }

            var projectConfig = ProjectConfiguration.Create();

            if (!File.Exists(projectConfigPath))
            {
                log.Warn("Project configuration file not found; configuration initialized with default values");
                return new SageContext(context);
            }

            installOrder = new List<string>();
            extensions = new OrderedDictionary<string, ExtensionInfo>();

            if (File.Exists(projectConfigPath))
                projectConfig.Parse(projectConfigPath);

            if (projectConfig.Locales.Count == 0)
            {
                var defaultLocale = new LocaleInfo();
                projectConfig.Locales.Add(defaultLocale.Name, defaultLocale);
            }

            var result = projectConfig.ValidationResult;
            if (!result.Success)
            {
                initializationError = result.Exception;
                initializationProblemInfo = new ProblemInfo(ProblemType.ProjectSchemaValidationError, result.SourceFile);
            }
            else
            {
                configuration = projectConfig;

                // this will ensure the new context uses the just
                // created configuration immediately
                context = new SageContext(context);

                var extensionManager = new ExtensionManager();
                try
                {
                    extensionManager.Initialize(context);
                }
                catch (ProjectInitializationException ex)
                {
                    initializationError = ex;
                    initializationProblemInfo = new ProblemInfo(ex.Reason, ex.SourceFile);
                    if (ex.Reason == ProblemType.MissingExtensionDependency)
                    {
                        initializationProblemInfo.InfoBlocks
                            .Add("Dependencies", ex.Dependencies.ToDictionary(name => name));
                    }
                }

                if (initializationError == null)
                {
                    var missingDependencies = projectConfig.Dependencies
                        .Where(name => extensionManager.Count(ex => ex.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)) == 0)
                        .ToList();

                    var extraDependencies = extensionManager
                        .Where(extension => projectConfig.Dependencies.Count(name => name.Equals(extension.Name, StringComparison.InvariantCultureIgnoreCase)) == 0)
                        .ToList();

                    if (missingDependencies.Count != 0)
                    {
                        string errorMessage =
                            string.Format("Project is missing one or more dependencies ({0}) - installation cancelled.",
                            string.Join(", ", missingDependencies));

                        initializationError = new ProjectInitializationException(errorMessage);
                        initializationProblemInfo = new ProblemInfo(ProblemType.MissingDependency);
                        initializationProblemInfo.InfoBlocks
                            .Add("Dependencies", missingDependencies.ToDictionary(name => name));
                    }

                    if (extraDependencies.Count != 0)
                    {
                        log.WarnFormat("There are additional, unreferenced extensions in the extensions directory: {0}", string.Join(",", extraDependencies));
                    }

                    foreach (var name in projectConfig.Dependencies)
                    {
                        var extension = extensionManager.First(ex => ex.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase));
                        installOrder.Add(extension.Config.Id);
                        Project.RelevantAssemblies.AddRange(extension.Assemblies);

                        projectConfig.RegisterExtension(extension.Config);
                        extensions.Add(extension.Config.Id, extension);
                    }

                    // fire this event at the end rather than once for each extension
                    var totalAssemblies = extensionManager.Sum(info => info.Assemblies.Count);
                    if (totalAssemblies != 0)
                    {
                        if (Project.AssembliesUpdated != null)
                        {
                            log.DebugFormat("{0} extension assemblies loaded, triggering AssembliesUpdated event", totalAssemblies);
                            Project.AssembliesUpdated(null, EventArgs.Empty);
                        }
                    }

                    installOrder.Add(projectConfig.Id);
                    projectConfig.RegisterRoutes();
                    context.LmCache.Put(ConfigWatchName, DateTime.Now, projectConfig.Files);
                }
            }

            return context;
        }
Esempio n. 18
0
        internal static XmlNode ProcessContextIfNode(SageContext context, XmlNode node)
        {
            if (node.SelectSingleElement("ancestor::sage:literal", XmlNamespaces.Manager) != null)
                return node;

            XmlElement element = (XmlElement) node;
            XmlDocumentFragment result = node.OwnerDocument.CreateDocumentFragment();

            string expression = element.GetAttribute("expression");
            string propName = element.GetAttribute("property");
            string key = element.GetAttribute("key");
            string equals = element.GetAttribute("equals");
            string notEquals = element.GetAttribute("not-equals");
            bool nodeValid = false;

            if (!string.IsNullOrWhiteSpace(expression))
            {
                var text = context.textEvaluator.Process(expression);
                nodeValid = !string.IsNullOrWhiteSpace(text);
            }
            else
            {
                string propValue = SageContext.GetContextProperty(context, propName, key);
                if (notEquals != string.Empty)
                    nodeValid = !propValue.Equals(notEquals, StringComparison.InvariantCultureIgnoreCase);
                else if (equals != string.Empty)
                    nodeValid = propValue.Equals(equals, StringComparison.InvariantCultureIgnoreCase);
            }

            if (!nodeValid)
                return null;

            foreach (XmlNode child in node.SelectNodes("node()"))
                result.AppendChild(context.ProcessNode(child));

            return result;
        }
Esempio n. 19
0
        /// <summary>
        /// Handles the BeginRequest event of the Application control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected virtual void Application_BeginRequest(object sender, EventArgs e)
        {
            if (Thread.CurrentThread.Name == null)
            {
                Thread.CurrentThread.Name = Project.GenerateThreadId();
                log.InfoFormat("Thread name set to {0}", Thread.CurrentThread.Name);
            }

            if (initializationError != null)
            {
                StringBuilder html = new StringBuilder();
                using (TextWriter writer = new StringWriter(html))
                {
                    SageHelpException helpException = new SageHelpException(initializationProblemInfo, initializationError);
                    helpException.Render(writer, new SageContext(this.Context));
                }

                this.Response.Write(html.ToString());
                this.Response.Cache.SetCacheability(HttpCacheability.NoCache);
                this.Response.Cache.SetNoStore();
                this.Response.End();
            }

            var context = new SageContext(this.Context);
            if (context.LmCache.Get(ConfigWatchName) == null)
                Project.InitializeConfiguration(context);

            if (!Project.IsStarted)
            {
                lock (lck)
                {
                    if (!Project.IsStarted)
                    {
                        Project.Start(context);
                    }
                }
            }

            if (this.Context != null)
                log.InfoFormat("Request {0} started.", HttpContext.Current.Request.Url);
            else
                log.InfoFormat("Request started (no context)");
        }
Esempio n. 20
0
 /// <summary>
 /// Initializes a new instance of the <see cref="SageContext"/> class, using an existing context instance.
 /// </summary>
 /// <param name="context">An existing <see cref="SageContext"/> to use to initialize this instance.</param>
 /// <param name="categoryName">The name of the category to set on the new context.</param>
 /// <param name="config">The project configuration to use with this context instance.</param>
 public SageContext(SageContext context, string categoryName, ProjectConfiguration config = null)
     : this(context.HttpContext, config)
 {
     this.Category = categoryName;
     pathMapper = context.MapPath;
 }
Esempio n. 21
0
        /// <summary>
        /// Initializes a new instance of the <see cref="LastModifiedCache"/> class, using the specified
        /// <paramref name="context"/>.
        /// </summary>
        /// <param name="context">The current context under which this code is being executed.</param>
        internal LastModifiedCache(SageContext context)
        {
            Contract.Requires<ArgumentNullException>(context != null);

            this.context = context;
        }
Esempio n. 22
0
        internal static XmlNode ProcessContextSwitchNode(SageContext context, XmlNode switchNode)
        {
            if (switchNode.SelectSingleElement("ancestor::sage:literal", XmlNamespaces.Manager) != null)
                return switchNode;

            XmlElement switchElem = (XmlElement) switchNode;

            string propName = switchElem.GetAttribute("property");
            string key = switchElem.GetAttribute("key");

            if (string.IsNullOrEmpty(propName))
            {
                log.ErrorFormat("The switch node in document '{0}' is missing the required property attribute",
                    switchNode.OwnerDocument.BaseURI);

                return switchNode;
            }

            string propValue = SageContext.GetContextProperty(context, propName, key);

            int caseNum = 0;
            bool caseFound = false;
            XmlDocumentFragment result = switchNode.OwnerDocument.CreateDocumentFragment();

            foreach (XmlElement caseNode in switchNode.SelectNodes("context:case", XmlNamespaces.Manager))
            {
                string testValue = caseNode.GetAttribute("test");
                if (string.IsNullOrEmpty(testValue))
                {
                    log.WarnFormat(
                        "The case node with index {0} of switch node '{1}' in document '{2}' didn't specify a test condition.",
                            caseNum, propName, switchNode.OwnerDocument.BaseURI);

                    continue;
                }

                if (testValue.Equals(propValue, StringComparison.InvariantCultureIgnoreCase))
                {
                    foreach (XmlNode node in caseNode.SelectNodes("node()"))
                        result.AppendChild(context.ProcessNode(node));

                    caseFound = true;
                    break;
                }

                caseNum += 1;
            }

            if (!caseFound)
            {
                XmlNode defaultNode = switchNode.SelectSingleNode("context:default", XmlNamespaces.Manager);
                if (defaultNode != null)
                {
                    foreach (XmlNode node in defaultNode.SelectNodes("node()"))
                        result.AppendChild(context.ProcessNode(node));
                }
            }

            return result;
        }
Esempio n. 23
0
        internal static string GetProjectLinkFunction(SageContext context, params string[] arguments)
        {
            var linkArguments = new LinkArguments(arguments, false, "encode", "absolute", "pretty");
            var result = linkArguments.Switches["absolute"]
                ? context.Url.ApplicationRoot
                : context.Request.ApplicationPath;

            if (linkArguments.Switches["encode"] && !string.IsNullOrEmpty(result))
                result = HttpUtility.UrlEncode(result);

            return result + (result.EndsWith("/") ? string.Empty : "/");
        }
Esempio n. 24
0
        /// <summary>
        /// Renders the exception to the specified <paramref name="writer"/>
        /// </summary>
        /// <param name="writer">The writer to render the exception to.</param>
        /// <param name="context">The context under which this code is executing.</param>
        public virtual void Render(TextWriter writer, SageContext context)
        {
            Contract.Requires<ArgumentNullException>(context != null);
            Contract.Requires<ArgumentNullException>(writer != null);

            XmlDocument document = new XmlDocument();
            XmlElement documentElement = document.AppendElement(this.ConvertToXml(this.Exception, document));
            Exception inner = this.Exception.InnerException;

            while (inner != null)
            {
                documentElement.AppendChild(this.ConvertToXml(inner, document));
                inner = inner.InnerException;
            }

            documentElement.AppendChild(context.ToXml(document));
            documentElement.SetAttribute("date", DateTime.Now.ToString("dd-MM-yyyy"));
            documentElement.SetAttribute("time", DateTime.Now.ToString("hh:mm:ss"));

            XsltTransform processor = XsltTransform.Create(context, this.StylesheetPath);
            XmlWriter xmlwr = XmlWriter.Create(writer, processor.OutputSettings);

            processor.Transform(documentElement, xmlwr, context, this.GetTransformArguments(context));
        }
Esempio n. 25
0
        internal static XmlNode ProcessHrefAttribute(SageContext context, XmlNode node)
        {
            Contract.Requires<ArgumentNullException>(node != null);
            if (node.SelectSingleElement("ancestor::sage:literal", XmlNamespaces.Manager) != null)
                return node;

            node.InnerText = context.ProcessText(node.InnerText);
            return node;
        }
Esempio n. 26
0
 /// <summary>
 /// Gets the XSLT arguments to use with the transform.
 /// </summary>
 /// <param name="context">The current context.</param>
 /// <returns>The XSLT arguments to use with this transform</returns>
 protected virtual Dictionary<string, object> GetTransformArguments(SageContext context)
 {
     Dictionary<string, object> arguments = new Dictionary<string, object>();
     arguments.Add("developer", context.IsDeveloperRequest ? 1 : 0);
     return arguments;
 }
Esempio n. 27
0
        internal static XmlNode ProcessSageLinkElement(SageContext context, XmlNode node)
        {
            Contract.Requires<ArgumentNullException>(node != null);
            if (node.SelectSingleElement("ancestor::sage:literal", XmlNamespaces.Manager) != null)
                return node;

            XmlElement linkElem = (XmlElement) node;
            string linkName = context.ProcessText(linkElem.GetAttribute("ref"));
            bool rawString = linkElem.GetAttribute("raw").EqualsAnyOf("1", "yes", "true");

            if (!string.IsNullOrEmpty(linkName) && rawString)
            {
                if (context.Url.Links.ContainsKey(linkName))
                {
                    linkElem.InnerText = context.Url.Links[linkName].Value;
                }

                return linkElem;
            }

            string linkHref = context.Url.GetUrl(linkElem);
            if (!string.IsNullOrEmpty(linkHref))
            {
                linkElem.SetAttribute("href", linkHref);
            }

            foreach (XmlNode child in node.ChildNodes)
            {
                XmlNode processed = NodeEvaluator.GetNodeHandler(child)(context, child);
                if (processed != null)
                    node.ReplaceChild(processed, child);
                else
                    node.RemoveChild(child);
            }

            return linkElem;
        }
Esempio n. 28
0
        internal static Dictionary<string, string> GetVirtualDirectories(SageContext context)
        {
            Dictionary<string, string> virtualDirectories = new Dictionary<string, string>();

            try
            {
                string serverRootPath = context.MapPath("/").ToLower().TrimEnd('\\');
                using (DirectoryEntry iis = new DirectoryEntry("IIS://Localhost/w3svc"))
                {
                    IEnumerable<DirectoryEntry> websites = iis.Children.Cast<DirectoryEntry>()
                        .Where(c => c.SchemaClassName == "IIsWebServer");

                    foreach (DirectoryEntry website in websites)
                    {
                        using (website)
                        {
                            DirectoryEntry root = website.Children.Find("Root", "IIsWebVirtualDir");
                            string sitePath = root.Properties["path"].Value.ToString().ToLower().TrimEnd('\\');

                            if (sitePath == serverRootPath)
                            {
                                virtualDirectories = Project.GetVirtualDirectories(root, string.Empty);
                                break;
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                log.ErrorFormat("Could not retrieve virtual directories in the current application's web server: {0}", ex.Message);
            }

            return virtualDirectories;
        }
Esempio n. 29
0
 /// <summary>
 /// Initializes a new instance of the <see cref="UrlGenerator"/> class, using the specified <paramref name="context"/>.
 /// </summary>
 /// <param name="context">The current <see cref="SageContext"/>.</param>
 public UrlGenerator(SageContext context)
 {
     this.context = context;
 }
Esempio n. 30
0
        internal static string ResolvePathVariable(SageContext context, string variable)
        {
            switch (variable.ToLower())
            {
                case "apppath":
                    return context.ApplicationPath;

                case "locale":
                    return context.Locale;

                case "basehref":
                    return context.BaseHref;

                case "category":
                    return context.Category;

                case "assetpath":
                    return context.Path.GetRelativeWebPath(context.Path.AssetPath);

                case "sharedassetpath":
                    return context.Path.GetRelativeWebPath(context.Path.SharedAssetPath);

                case "modulepath":
                    return context.Path.GetRelativeWebPath(context.Path.ModulePath);
            }

            return variable;
        }