internal string GetUrlFromRoute(string route, UmbracoContext umbracoContext, int id, Uri current, UrlProviderMode mode)
        {
            if (string.IsNullOrWhiteSpace(route))
            {
                LogHelper.Debug <DefaultUrlProvider>(
                    "Couldn't find any page with nodeId={0}. This is most likely caused by the page not being published.",
                    () => id);
                return(null);
            }

            if (route.StartsWith("err/"))
            {
                LogHelper.Debug <DefaultUrlProvider>(
                    "Page with nodeId={0} has a colliding url with page with nodeId={1}.",
                    () => id, () => route.Substring(4));
                return("#err-" + route.Substring(4));
            }

            var domainHelper = new DomainHelper(umbracoContext.Application.Services.DomainService);

            // extract domainUri and path
            // route is /<path> or <domainRootId>/<path>
            var pos       = route.IndexOf('/');
            var path      = pos == 0 ? route : route.Substring(pos);
            var domainUri = pos == 0
                ? null
                : domainHelper.DomainForNode(int.Parse(route.Substring(0, pos)), current);

            // assemble the url from domainUri (maybe null) and path
            return(AssembleUrl(domainUri, path, current, mode).ToString());
        }
        /// <summary>
        /// Looks for wildcard domains in the path and updates <c>Culture</c> accordingly.
        /// </summary>
        internal void HandleWildcardDomains()
        {
            const string tracePrefix = "HandleWildcardDomains: ";

            if (_pcr.HasPublishedContent == false)
            {
                return;
            }

            var nodePath = _pcr.PublishedContent.Path;

            ProfilingLogger.Logger.Debug <PublishedContentRequestEngine>("{0}Path=\"{1}\"", () => tracePrefix, () => nodePath);
            var rootNodeId = _pcr.HasDomain ? _pcr.UmbracoDomain.RootContentId : (int?)null;
            var domain     = DomainHelper.FindWildcardDomainInPath(Services.DomainService.GetAll(true), nodePath, rootNodeId);

            if (domain != null && domain.LanguageIsoCode.IsNullOrWhiteSpace() == false)
            {
                _pcr.Culture = new CultureInfo(domain.LanguageIsoCode);
                ProfilingLogger.Logger.Debug <PublishedContentRequestEngine>("{0}Got domain on node {1}, set culture to \"{2}\".", () => tracePrefix,
                                                                             () => domain.RootContentId, () => _pcr.Culture.Name);
            }
            else
            {
                ProfilingLogger.Logger.Debug <PublishedContentRequestEngine>("{0}No match.", () => tracePrefix);
            }
        }
        /// <summary>
        /// Looks for wildcard domains in the path and updates <c>Culture</c> accordingly.
        /// </summary>
        internal void HandleWildcardDomains(PublishedRequest request)
        {
            const string tracePrefix = "HandleWildcardDomains: ";

            if (request.HasPublishedContent == false)
            {
                return;
            }

            var nodePath = request.PublishedContent.Path;

            _logger.Debug <PublishedRouter>("{TracePrefix}Path={NodePath}", tracePrefix, nodePath);
            var rootNodeId = request.HasDomain ? request.Domain.ContentId : (int?)null;
            var domain     = DomainHelper.FindWildcardDomainInPath(request.UmbracoContext.PublishedSnapshot.Domains.GetAll(true), nodePath, rootNodeId);

            // always has a contentId and a culture
            if (domain != null)
            {
                request.Culture = domain.Culture;
                _logger.Debug <PublishedRouter>("{TracePrefix}Got domain on node {DomainContentId}, set culture to {CultureName}", tracePrefix, domain.ContentId, request.Culture.Name);
            }
            else
            {
                _logger.Debug <PublishedRouter>("{TracePrefix}No match.", tracePrefix);
            }
        }
        /// <summary>
        /// Gets the other urls of a published content.
        /// </summary>
        /// <param name="umbracoContext">The Umbraco context.</param>
        /// <param name="id">The published content id.</param>
        /// <param name="current">The current absolute url.</param>
        /// <returns>The other urls for the published content.</returns>
        /// <remarks>
        /// <para>Other urls are those that <c>GetUrl</c> would not return in the current context, but would be valid
        /// urls for the node in other contexts (different domain for current request, umbracoUrlAlias...).</para>
        /// </remarks>
        public virtual IEnumerable <string> GetOtherUrls(UmbracoContext umbracoContext, int id, Uri current)
        {
            // will not use cache if previewing
            var route = umbracoContext.ContentCache.GetRouteById(id);

            if (string.IsNullOrWhiteSpace(route))
            {
                LogHelper.Debug <DefaultUrlProvider>(
                    "Couldn't find any page with nodeId={0}. This is most likely caused by the page not being published.",
                    () => id);
                return(null);
            }

            if (route.StartsWith("err/"))
            {
                return(null);
            }

            var domainHelper = new DomainHelper(umbracoContext.Application.Services.DomainService);

            // extract domainUri and path
            // route is /<path> or <domainRootId>/<path>
            var pos        = route.IndexOf('/');
            var path       = pos == 0 ? route : route.Substring(pos);
            var domainUris = pos == 0 ? null : domainHelper.DomainsForNode(int.Parse(route.Substring(0, pos)), current);

            // assemble the alternate urls from domainUris (maybe empty) and path
            return(AssembleUrls(domainUris, path).Select(uri => uri.ToString()));
        }
Exemple #5
0
        /// <summary>
        /// Looks for wildcard domains in the path and updates <c>Culture</c> accordingly.
        /// </summary>
        internal void HandleWildcardDomains()
        {
            const string tracePrefix = "HandleWildcardDomains: ";

            if (!_pcr.HasPublishedContent)
            {
                return;
            }

            var nodePath = _pcr.PublishedContent.Path;

            LogHelper.Debug <PublishedContentRequestEngine>("{0}Path=\"{1}\"", () => tracePrefix, () => nodePath);
            var rootNodeId = _pcr.HasDomain ? _pcr.Domain.RootNodeId : (int?)null;
            var domain     = DomainHelper.FindWildcardDomainInPath(DomainHelper.GetAllDomains(true), nodePath, rootNodeId);

            if (domain != null)
            {
                _pcr.Culture = new CultureInfo(domain.Language.CultureAlias);
                LogHelper.Debug <PublishedContentRequestEngine>("{0}Got domain on node {1}, set culture to \"{2}\".", () => tracePrefix,
                                                                () => domain.RootNodeId, () => _pcr.Culture.Name);
            }
            else
            {
                LogHelper.Debug <PublishedContentRequestEngine>("{0}No match.", () => tracePrefix);
            }
        }
        /// <summary>
        /// Gets the nice url of a published content.
        /// </summary>
        /// <param name="umbracoContext">The Umbraco context.</param>
        /// <param name="id">The published content id.</param>
        /// <param name="current">The current absolute url.</param>
        /// <param name="mode">The url mode.</param>
        /// <returns>The url for the published content.</returns>
        /// <remarks>
        /// <para>The url is absolute or relative depending on <c>mode</c> and on <c>current</c>.</para>
        /// <para>If the provider is unable to provide a url, it should return <c>null</c>.</para>
        /// </remarks>
        public virtual string GetUrl(UmbracoContext umbracoContext, int id, Uri current, UrlProviderMode mode)
        {
            if (!current.IsAbsoluteUri)
            {
                throw new ArgumentException("Current url must be absolute.", "current");
            }

            // will not use cache if previewing
            var route = umbracoContext.ContentCache.GetRouteById(id);

            if (string.IsNullOrWhiteSpace(route))
            {
                LogHelper.Debug <DefaultUrlProvider>(
                    "Couldn't find any page with nodeId={0}. This is most likely caused by the page not being published.",
                    () => id);
                return(null);
            }

            var domainHelper = new DomainHelper(umbracoContext.Application.Services.DomainService);

            // extract domainUri and path
            // route is /<path> or <domainRootId>/<path>
            var pos       = route.IndexOf('/');
            var path      = pos == 0 ? route : route.Substring(pos);
            var domainUri = pos == 0
                ? null
                : domainHelper.DomainForNode(int.Parse(route.Substring(0, pos)), current);

            // assemble the url from domainUri (maybe null) and path
            return(AssembleUrl(domainUri, path, current, mode).ToString());
        }
Exemple #7
0
        /// <summary>
        /// Looks for wildcard domains in the path and updates <c>Culture</c> accordingly.
        /// </summary>
        private void HandleWildcardDomains()
        {
            const string tracePrefix = "HandleWildcardDomains: ";

            if (!_publishedContentRequest.HasNode)
            {
                return;
            }

            var nodePath = _publishedContentRequest.PublishedContent.Path;

            LogHelper.Debug <PublishedContentRequest>("{0}Path=\"{1}\"", () => tracePrefix, () => nodePath);
            var rootNodeId = _publishedContentRequest.HasDomain ? _publishedContentRequest.Domain.RootNodeId : (int?)null;
            var domain     = DomainHelper.LookForWildcardDomain(Domain.GetDomains(), nodePath, rootNodeId);

            if (domain != null)
            {
                _publishedContentRequest.Culture = new CultureInfo(domain.Language.CultureAlias);
                LogHelper.Debug <PublishedContentRequest>("{0}Got domain on node {1}, set culture to \"{2}\".", () => tracePrefix,
                                                          () => domain.RootNodeId, () => _publishedContentRequest.Culture.Name);
            }
            else
            {
                LogHelper.Debug <PublishedContentRequest>("{0}No match.", () => tracePrefix);
            }
        }
        /// <summary>
        /// Tries to find and assign an Umbraco document to a <c>PublishedRequest</c>.
        /// </summary>
        /// <param name="frequest">The <c>PublishedRequest</c>.</param>
        /// <returns>A value indicating whether an Umbraco document was found and assigned.</returns>
        /// <remarks>If successful, also assigns the template.</remarks>
        public override bool TryFindContent(PublishedRequest frequest)
        {
            IPublishedContent node = null;
            var path = frequest.Uri.GetAbsolutePathDecoded();

            if (frequest.HasDomain)
            {
                path = DomainHelper.PathRelativeToDomain(frequest.Domain.Uri, path);
            }

            // no template if "/"
            if (path == "/")
            {
                Logger.Debug <ContentFinderByUrlAndTemplate>("No template in path '/'");
                return(false);
            }

            // look for template in last position
            var pos           = path.LastIndexOf('/');
            var templateAlias = path.Substring(pos + 1);

            path = pos == 0 ? "/" : path.Substring(0, pos);

            var template = _fileService.GetTemplate(templateAlias);

            if (template == null)
            {
                Logger.Debug <ContentFinderByUrlAndTemplate>("Not a valid template: '{TemplateAlias}'", templateAlias);
                return(false);
            }

            Logger.Debug <ContentFinderByUrlAndTemplate>("Valid template: '{TemplateAlias}'", templateAlias);

            // look for node corresponding to the rest of the route
            var route = frequest.HasDomain ? (frequest.Domain.ContentId + path) : path;

            node = FindContent(frequest, route); // also assigns to published request

            if (node == null)
            {
                Logger.Debug <ContentFinderByUrlAndTemplate>("Not a valid route to node: '{Route}'", route);
                return(false);
            }

            // IsAllowedTemplate deals both with DisableAlternativeTemplates and ValidateAlternativeTemplates settings
            if (!node.IsAllowedTemplate(template.Id))
            {
                Logger.Warn <ContentFinderByUrlAndTemplate>("Alternative template '{TemplateAlias}' is not allowed on node {NodeId}.", template.Alias, node.Id);
                frequest.PublishedContent = null; // clear
                return(false);
            }

            // got it
            frequest.TemplateModel = template;
            return(true);
        }
Exemple #9
0
        Uri DomainUriAtNode(int nodeId, Uri current)
        {
            // be safe
            if (nodeId <= 0)
            {
                return(null);
            }

            // apply filter on domains defined on that node
            var domainAndUri = DomainHelper.DomainMatch(Domain.GetDomainsById(nodeId), current, true);

            return(domainAndUri == null ? null : domainAndUri.Uri);
        }
Exemple #10
0
 /// <summary>
 /// Initializes a new instance of the <see cref="DomainAndUri"/> class.
 /// </summary>
 /// <param name="domain">The original domain.</param>
 /// <param name="currentUri">The context current Uri.</param>
 public DomainAndUri(Domain domain, Uri currentUri)
     : base(domain)
 {
     try
     {
         Uri = DomainHelper.ParseUriFromDomainName(Name, currentUri);
     }
     catch (UriFormatException)
     {
         throw new ArgumentException($"Failed to parse invalid domain: node id={domain.ContentId}, hostname=\"{Name.ToCSharpString()}\"."
                                     + " Hostname should be a valid uri.", nameof(domain));
     }
 }
Exemple #11
0
        /// <summary>
        /// Tries to find and assign an Umbraco document to a <c>PublishedContentRequest</c>.
        /// </summary>
        /// <param name="docRequest">The <c>PublishedContentRequest</c>.</param>
        /// <returns>A value indicating whether an Umbraco document was found and assigned.</returns>
        /// <remarks>If successful, also assigns the template.</remarks>
        public override bool TryFindContent(PublishedContentRequest docRequest)
        {
            const string tracePrefix = "ContentFinderByNiceUrlAndTemplate: ";

            IPublishedContent node = null;
            string            path = docRequest.Uri.GetAbsolutePathDecoded();

            if (docRequest.HasDomain)
            {
                path = DomainHelper.PathRelativeToDomain(docRequest.DomainUri, path);
            }

            if (path != "/") // no template if "/"
            {
                var pos           = path.LastIndexOf('/');
                var templateAlias = path.Substring(pos + 1);
                path = pos == 0 ? "/" : path.Substring(0, pos);

                var template = ApplicationContext.Current.Services.FileService.GetTemplate(templateAlias);
                if (template != null)
                {
                    LogHelper.Debug <ContentFinderByNiceUrlAndTemplate>("Valid template: \"{0}\"", () => templateAlias);

                    var route = docRequest.HasDomain ? (docRequest.Domain.RootNodeId.ToString() + path) : path;
                    node = FindContent(docRequest, route);

                    if (node.IsAllowedTemplate(template.Id))
                    {
                        docRequest.TemplateModel = template;
                    }
                    else
                    {
                        LogHelper.Warn <ContentFinderByNiceUrlAndTemplate>("Configuration settings prevent template \"{0}\" from showing for node \"{1}\"", () => templateAlias, () => node.Id);
                        docRequest.PublishedContent = null;
                        node = null;
                    }
                }
                else
                {
                    LogHelper.Debug <ContentFinderByNiceUrlAndTemplate>("Not a valid template: \"{0}\"", () => templateAlias);
                }
            }
            else
            {
                LogHelper.Debug <ContentFinderByNiceUrlAndTemplate>("No template in path \"/\"");
            }

            return(node != null);
        }
Exemple #12
0
        /// <summary>
        /// Tries to find and assign an Umbraco document to a <c>PublishedContentRequest</c>.
        /// </summary>
        /// <param name="frequest">The <c>PublishedContentRequest</c>.</param>
        /// <returns>A value indicating whether an Umbraco document was found and assigned.</returns>
        public virtual bool TryFindContent(PublishedRequest frequest)
        {
            string route;

            if (frequest.HasDomain)
            {
                route = frequest.Domain.ContentId + DomainHelper.PathRelativeToDomain(frequest.Domain.Uri, frequest.Uri.GetAbsolutePathDecoded());
            }
            else
            {
                route = frequest.Uri.GetAbsolutePathDecoded();
            }

            var node = FindContent(frequest, route);

            return(node != null);
        }
Exemple #13
0
        /// <summary>
        /// Tries to find and assign an Umbraco document to a <c>PublishedContentRequest</c>.
        /// </summary>
        /// <param name="docRequest">The <c>PublishedContentRequest</c>.</param>
        /// <returns>A value indicating whether an Umbraco document was found and assigned.</returns>
        public virtual bool TrySetDocument(PublishedContentRequest docRequest)
        {
            string route;

            if (docRequest.HasDomain)
            {
                route = docRequest.Domain.RootNodeId.ToString() + DomainHelper.PathRelativeToDomain(docRequest.DomainUri, docRequest.Uri.GetAbsolutePathDecoded());
            }
            else
            {
                route = docRequest.Uri.GetAbsolutePathDecoded();
            }

            var node = LookupDocumentNode(docRequest, route);

            return(node != null);
        }
        /// <summary>
        /// Tries to find and assign an Umbraco document to a <c>PublishedContentRequest</c>.
        /// </summary>
        /// <param name="contentRequest">The <c>PublishedContentRequest</c>.</param>
        /// <returns>A value indicating whether an Umbraco document was found and assigned.</returns>
        /// <remarks>Optionally, can also assign the template or anything else on the document request, although that is not required.</remarks>
        public bool TryFindContent(PublishedContentRequest contentRequest)
        {
            var route = contentRequest.HasDomain
                ? contentRequest.UmbracoDomain.RootContentId + DomainHelper.PathRelativeToDomain(contentRequest.DomainUri, contentRequest.Uri.GetAbsolutePathDecoded())
                : contentRequest.Uri.GetAbsolutePathDecoded();

            var service     = contentRequest.RoutingContext.UmbracoContext.Application.Services.RedirectUrlService;
            var redirectUrl = service.GetMostRecentRedirectUrl(route);

            if (redirectUrl == null)
            {
                LogHelper.Debug <ContentFinderByRedirectUrl>("No match for route: \"{0}\".", () => route);
                return(false);
            }

            var content = contentRequest.RoutingContext.UmbracoContext.ContentCache.GetById(redirectUrl.ContentId);
            var url     = content == null ? "#" : content.Url;

            if (url.StartsWith("#"))
            {
                LogHelper.Debug <ContentFinderByRedirectUrl>("Route \"{0}\" matches content {1} which has no url.",
                                                             () => route, () => redirectUrl.ContentId);
                return(false);
            }

            // Apending any querystring from the incoming request to the redirect url.
            url = string.IsNullOrEmpty(contentRequest.Uri.Query) ? url : url + contentRequest.Uri.Query;

            LogHelper.Debug <ContentFinderByRedirectUrl>("Route \"{0}\" matches content {1} with url \"{2}\", redirecting.",
                                                         () => route, () => content.Id, () => url);

            // From: http://stackoverflow.com/a/22468386/5018
            // See http://issues.umbraco.org/issue/U4-8361#comment=67-30532
            // Setting automatic 301 redirects to not be cached because browsers cache these very aggressively which then leads
            // to problems if you rename a page back to it's original name or create a new page with the original name
            contentRequest.Cacheability    = HttpCacheability.NoCache;
            contentRequest.CacheExtensions = new List <string> {
                "no-store, must-revalidate"
            };
            contentRequest.Headers = new Dictionary <string, string> {
                { "Pragma", "no-cache" }, { "Expires", "0" }
            };

            contentRequest.SetRedirectPermanent(url);
            return(true);
        }
Exemple #15
0
        /// <summary>
        /// Finds the site root (if any) matching the http request, and updates the PublishedContentRequest accordingly.
        /// </summary>
        /// <returns>A value indicating whether a domain was found.</returns>
        internal bool FindDomain()
        {
            const string tracePrefix = "FindDomain: ";

            // note - we are not handling schemes nor ports here.

            LogHelper.Debug <PublishedContentRequestEngine>("{0}Uri=\"{1}\"", () => tracePrefix, () => _pcr.Uri);

            // try to find a domain matching the current request
            var domainAndUri = DomainHelper.DomainForUri(DomainHelper.GetAllDomains(false), _pcr.Uri);

            // handle domain
            if (domainAndUri != null)
            {
                // matching an existing domain
                LogHelper.Debug <PublishedContentRequestEngine>("{0}Matches domain=\"{1}\", rootId={2}, culture=\"{3}\"",
                                                                () => tracePrefix,
                                                                () => domainAndUri.Domain.Name,
                                                                () => domainAndUri.Domain.RootNodeId,
                                                                () => domainAndUri.Domain.Language.CultureAlias);

                _pcr.Domain    = domainAndUri.Domain;
                _pcr.DomainUri = domainAndUri.Uri;
                _pcr.Culture   = new CultureInfo(domainAndUri.Domain.Language.CultureAlias);

                // canonical? not implemented at the moment
                // if (...)
                // {
                //  _pcr.RedirectUrl = "...";
                //  return true;
                // }
            }
            else
            {
                // not matching any existing domain
                LogHelper.Debug <PublishedContentRequestEngine>("{0}Matches no domain", () => tracePrefix);

                var defaultLanguage = Language.GetAllAsList().FirstOrDefault();
                _pcr.Culture = defaultLanguage == null ? CultureInfo.CurrentUICulture : new CultureInfo(defaultLanguage.CultureAlias);
            }

            LogHelper.Debug <PublishedContentRequestEngine>("{0}Culture=\"{1}\"", () => tracePrefix, () => _pcr.Culture.Name);

            return(_pcr.Domain != null);
        }
        /// <summary>
        /// Tries to find and assign an Umbraco document to a <c>PublishedContentRequest</c>.
        /// </summary>
        /// <param name="docRequest">The <c>PublishedContentRequest</c>.</param>
        /// <returns>A value indicating whether an Umbraco document was found and assigned.</returns>
        /// <remarks>If successful, also assigns the template.</remarks>
        public override bool TrySetDocument(PublishedContentRequest docRequest)
        {
            IPublishedContent node = null;
            string            path = docRequest.Uri.GetAbsolutePathDecoded();

            if (docRequest.HasDomain)
            {
                path = DomainHelper.PathRelativeToDomain(docRequest.DomainUri, path);
            }

            if (path != "/")             // no template if "/"
            {
                var pos           = path.LastIndexOf('/');
                var templateAlias = path.Substring(pos + 1);
                path = pos == 0 ? "/" : path.Substring(0, pos);

                //TODO: We need to check if the altTemplate is for MVC or not, though I'm not exactly sure how the best
                // way to do that would be since the template is just an alias and if we are not having a flag on the
                // doc type for rendering engine and basing it only on template name, then how would we handle this?

                var template = Template.GetByAlias(templateAlias);
                if (template != null)
                {
                    LogHelper.Debug <LookupByNiceUrlAndTemplate>("Valid template: \"{0}\"", () => templateAlias);

                    var route = docRequest.HasDomain ? (docRequest.Domain.RootNodeId.ToString() + path) : path;
                    node = LookupDocumentNode(docRequest, route);

                    if (node != null)
                    {
                        docRequest.Template = template;
                    }
                }
                else
                {
                    LogHelper.Debug <LookupByNiceUrlAndTemplate>("Not a valid template: \"{0}\"", () => templateAlias);
                }
            }
            else
            {
                LogHelper.Debug <LookupByNiceUrlAndTemplate>("No template in path \"/\"");
            }

            return(node != null);
        }
        /// <summary>
        /// Finds the site root (if any) matching the http request, and updates the PublishedContentRequest accordingly.
        /// </summary>
        /// <returns>A value indicating whether a domain was found.</returns>
        internal bool FindDomain()
        {
            const string tracePrefix = "FindDomain: ";

            // note - we are not handling schemes nor ports here.

            ProfilingLogger.Logger.Debug <PublishedContentRequestEngine>("{0}Uri=\"{1}\"", () => tracePrefix, () => _pcr.Uri);

            // try to find a domain matching the current request
            var domainAndUri = DomainHelper.DomainForUri(Services.DomainService.GetAll(false), _pcr.Uri);

            // handle domain
            if (domainAndUri != null && domainAndUri.UmbracoDomain.LanguageIsoCode.IsNullOrWhiteSpace() == false)
            {
                // matching an existing domain
                ProfilingLogger.Logger.Debug <PublishedContentRequestEngine>("{0}Matches domain=\"{1}\", rootId={2}, culture=\"{3}\"",
                                                                             () => tracePrefix,
                                                                             () => domainAndUri.UmbracoDomain.DomainName,
                                                                             () => domainAndUri.UmbracoDomain.RootContentId,
                                                                             () => domainAndUri.UmbracoDomain.LanguageIsoCode);

                _pcr.UmbracoDomain = domainAndUri.UmbracoDomain;
                _pcr.DomainUri     = domainAndUri.Uri;
                _pcr.Culture       = new CultureInfo(domainAndUri.UmbracoDomain.LanguageIsoCode);

                // canonical? not implemented at the moment
                // if (...)
                // {
                //  _pcr.RedirectUrl = "...";
                //  return true;
                // }
            }
            else
            {
                // not matching any existing domain
                ProfilingLogger.Logger.Debug <PublishedContentRequestEngine>("{0}Matches no domain", () => tracePrefix);

                var defaultLanguage = Services.LocalizationService.GetAllLanguages().FirstOrDefault();
                _pcr.Culture = defaultLanguage == null ? CultureInfo.CurrentUICulture : new CultureInfo(defaultLanguage.IsoCode);
            }

            ProfilingLogger.Logger.Debug <PublishedContentRequestEngine>("{0}Culture=\"{1}\"", () => tracePrefix, () => _pcr.Culture.Name);

            return(_pcr.UmbracoDomain != null);
        }
Exemple #18
0
        /// <summary>
        /// Gets the other urls of a published content.
        /// </summary>
        /// <param name="umbracoContext">The Umbraco context.</param>
        /// <param name="id">The published content id.</param>
        /// <param name="current">The current absolute url.</param>
        /// <returns>The other urls for the published content.</returns>
        /// <remarks>
        /// <para>Other urls are those that <c>GetUrl</c> would not return in the current context, but would be valid
        /// urls for the node in other contexts (different domain for current request, umbracoUrlAlias...).</para>
        /// </remarks>
        public IEnumerable <string> GetOtherUrls(UmbracoContext umbracoContext, int id, Uri current)
        {
            if (!FindByUrlAliasEnabled)
            {
                return(Enumerable.Empty <string>()); // we have nothing to say
            }
            var    node           = umbracoContext.ContentCache.GetById(id);
            string umbracoUrlName = null;

            if (node.HasProperty(Constants.Conventions.Content.UrlAlias))
            {
                umbracoUrlName = node.GetPropertyValue <string>(Constants.Conventions.Content.UrlAlias);
            }
            if (string.IsNullOrWhiteSpace(umbracoUrlName))
            {
                return(Enumerable.Empty <string>());
            }

            var domainHelper = new DomainHelper(umbracoContext.Application.Services.DomainService);

            var n          = node;
            var domainUris = domainHelper.DomainsForNode(n.Id, current, false);

            while (domainUris == null && n != null) // n is null at root
            {
                // move to parent node
                n          = n.Parent;
                domainUris = n == null ? null : domainHelper.DomainsForNode(n.Id, current, false);
            }

            var path = "/" + umbracoUrlName;

            if (domainUris == null)
            {
                var uri = new Uri(path, UriKind.Relative);
                return(new[] { UriUtility.UriFromUmbraco(uri).ToString() });
            }

            return(domainUris
                   .Select(domainUri => new Uri(CombinePaths(domainUri.Uri.GetLeftPart(UriPartial.Path), path)))
                   .Select(uri => UriUtility.UriFromUmbraco(uri).ToString()));
        }
        /// <summary>
        /// Tries to find and assign an Umbraco document to a <c>PublishedContentRequest</c>.
        /// </summary>
        /// <param name="docRequest">The <c>PublishedContentRequest</c>.</param>
        /// <returns>A value indicating whether an Umbraco document was found and assigned.</returns>
        /// <remarks>If successful, also assigns the template.</remarks>
        public override bool TryFindContent(PublishedContentRequest docRequest)
        {
            IPublishedContent node = null;
            string            path = docRequest.Uri.GetAbsolutePathDecoded();

            if (docRequest.HasDomain)
            {
                path = DomainHelper.PathRelativeToDomain(docRequest.DomainUri, path);
            }

            if (path != "/") // no template if "/"
            {
                var pos           = path.LastIndexOf('/');
                var templateAlias = path.Substring(pos + 1);
                path = pos == 0 ? "/" : path.Substring(0, pos);

                var template = ApplicationContext.Current.Services.FileService.GetTemplate(templateAlias);
                if (template != null)
                {
                    LogHelper.Debug <ContentFinderByNiceUrlAndTemplate>("Valid template: \"{0}\"", () => templateAlias);

                    var route = docRequest.HasDomain ? (docRequest.Domain.RootNodeId.ToString() + path) : path;
                    node = FindContent(docRequest, route);

                    if (UmbracoConfig.For.UmbracoSettings().WebRouting.DisableAlternativeTemplates == false && node != null)
                    {
                        docRequest.TemplateModel = template;
                    }
                }
                else
                {
                    LogHelper.Debug <ContentFinderByNiceUrlAndTemplate>("Not a valid template: \"{0}\"", () => templateAlias);
                }
            }
            else
            {
                LogHelper.Debug <ContentFinderByNiceUrlAndTemplate>("No template in path \"/\"");
            }

            return(node != null);
        }
Exemple #20
0
        IEnumerable <Uri> DomainUrisAtNode(int nodeId, Uri current)
        {
            // be safe
            if (nodeId <= 0)
            {
                return new Uri[] { }
            }
            ;

            var domainAndUris = DomainHelper.DomainMatches(Domain.GetDomainsById(nodeId), current);

            return(domainAndUris.Select(d => d.Uri));
        }

        void ApplyHideTopLevelNodeFromPath(Core.Models.IPublishedContent node, List <string> pathParts)
        {
            // in theory if hideTopLevelNodeFromPath is true, then there should be only once
            // top-level node, or else domains should be assigned. but for backward compatibility
            // we add this check - we look for the document matching "/" and if it's not us, then
            // we do not hide the top level path
            // it has to be taken care of in IPublishedContentStore.GetDocumentByRoute too so if
            // "/foo" fails (looking for "/*/foo") we try also "/foo".
            // this does not make much sense anyway esp. if both "/foo/" and "/bar/foo" exist, but
            // that's the way it works pre-4.10 and we try to be backward compat for the time being
            if (node.Parent == null)
            {
                var rootNode = _publishedContentStore.GetDocumentByRoute(_umbracoContext, "/", true);

                if (rootNode.Id == node.Id)                 // remove only if we're the default node
                {
                    pathParts.RemoveAt(pathParts.Count - 1);
                }
            }
            else
            {
                pathParts.RemoveAt(pathParts.Count - 1);
            }
        }

        #endregion
    }
Exemple #21
0
        /// <summary>
        /// Tries to find an Umbraco document for a <c>PublishedContentRequest</c> and a route.
        /// </summary>
        /// <param name="docreq">The document request.</param>
        /// <param name="route">The route.</param>
        /// <returns>The document node, or null.</returns>
        protected IPublishedContent LookupDocumentNode(PublishedContentRequest docreq, string route)
        {
            LogHelper.Debug <LookupByNiceUrl>("Test route \"{0}\"", () => route);

            // first ask the cache for a node
            // return '0' if in preview mode
            var nodeId = !docreq.RoutingContext.UmbracoContext.InPreviewMode
                                                        ? docreq.RoutingContext.UmbracoContext.RoutesCache.GetNodeId(route)
                                : 0;

            // if a node was found, get it by id and ensure it exists
            // else clear the cache
            IPublishedContent node = null;

            if (nodeId > 0)
            {
                node = docreq.RoutingContext.PublishedContentStore.GetDocumentById(
                    docreq.RoutingContext.UmbracoContext,
                    nodeId);

                if (node != null)
                {
                    docreq.PublishedContent = node;
                    LogHelper.Debug <LookupByNiceUrl>("Cache hit, id={0}", () => nodeId);
                }
                else
                {
                    docreq.RoutingContext.UmbracoContext.RoutesCache.ClearNode(nodeId);
                }
            }

            // if we still have no node, get it by route
            if (node == null)
            {
                LogHelper.Debug <LookupByNiceUrl>("Cache miss, query");
                node = docreq.RoutingContext.PublishedContentStore.GetDocumentByRoute(
                    docreq.RoutingContext.UmbracoContext,
                    route);

                if (node != null)
                {
                    docreq.PublishedContent = node;
                    LogHelper.Debug <LookupByNiceUrl>("Query matches, id={0}", () => docreq.DocumentId);

                    var iscanon = true;
                    if (docreq.HasDomain)
                    {
                        iscanon = !DomainHelper.ExistsDomainInPath(docreq.Domain, node.Path);
                        if (!iscanon)
                        {
                            LogHelper.Debug <LookupByNiceUrl>("Non canonical url");
                        }
                    }

                    // do not store if previewing or if non-canonical
                    if (!docreq.RoutingContext.UmbracoContext.InPreviewMode && iscanon)
                    {
                        docreq.RoutingContext.UmbracoContext.RoutesCache.Store(docreq.DocumentId, route);
                    }
                }
                else
                {
                    LogHelper.Debug <LookupByNiceUrl>("Query does not match");
                }
            }

            return(node);
        }
        /// <summary>
        /// Tries to find and assign an Umbraco document to a <c>PublishedRequest</c>.
        /// </summary>
        /// <param name="frequest">The <c>PublishedRequest</c>.</param>
        /// <returns>A value indicating whether an Umbraco document was found and assigned.</returns>
        public bool TryFindContent(PublishedRequest frequest)
        {
            _logger.Debug <ContentFinderByConfigured404>("Looking for a page to handle 404.");

            // try to find a culture as best as we can
            var errorCulture = CultureInfo.CurrentUICulture;

            if (frequest.HasDomain)
            {
                errorCulture = frequest.Domain.Culture;
            }
            else
            {
                var route = frequest.Uri.GetAbsolutePathDecoded();
                var pos   = route.LastIndexOf('/');
                IPublishedContent node = null;
                while (pos > 1)
                {
                    route = route.Substring(0, pos);
                    node  = frequest.UmbracoContext.ContentCache.GetByRoute(route, culture: frequest?.Culture?.Name);
                    if (node != null)
                    {
                        break;
                    }
                    pos = route.LastIndexOf('/');
                }
                if (node != null)
                {
                    var d = DomainHelper.FindWildcardDomainInPath(frequest.UmbracoContext.PublishedSnapshot.Domains.GetAll(true), node.Path, null);
                    if (d != null)
                    {
                        errorCulture = d.Culture;
                    }
                }
            }

            var error404 = NotFoundHandlerHelper.GetCurrentNotFoundPageId(
                _contentConfigSection.Error404Collection.ToArray(),
                _entityService,
                new PublishedContentQuery(frequest.UmbracoContext.PublishedSnapshot, frequest.UmbracoContext.VariationContextAccessor),
                errorCulture);

            IPublishedContent content = null;

            if (error404.HasValue)
            {
                _logger.Debug <ContentFinderByConfigured404>("Got id={ErrorNodeId}.", error404.Value);

                content = frequest.UmbracoContext.ContentCache.GetById(error404.Value);

                _logger.Debug <ContentFinderByConfigured404>(content == null
                    ? "Could not find content with that id."
                    : "Found corresponding content.");
            }
            else
            {
                _logger.Debug <ContentFinderByConfigured404>("Got nothing.");
            }

            frequest.PublishedContent = content;
            frequest.Is404            = true;
            return(content != null);
        }
        /// <summary>
        /// Finds the site root (if any) matching the http request, and updates the PublishedContentRequest accordingly.
        /// </summary>
        /// <returns>A value indicating whether a domain was found.</returns>
        internal bool FindDomain(PublishedRequest request)
        {
            const string tracePrefix = "FindDomain: ";

            // note - we are not handling schemes nor ports here.

            _logger.Debug <PublishedRouter>("{TracePrefix}Uri={RequestUri}", tracePrefix, request.Uri);

            var domainsCache = request.UmbracoContext.PublishedSnapshot.Domains;
            var domains      = domainsCache.GetAll(includeWildcards: false).ToList();

            // determines whether a domain corresponds to a published document, since some
            // domains may exist but on a document that has been unpublished - as a whole - or
            // that is not published for the domain's culture - in which case the domain does
            // not apply
            bool IsPublishedContentDomain(Domain domain)
            {
                // just get it from content cache - optimize there, not here
                var domainDocument = request.UmbracoContext.PublishedSnapshot.Content.GetById(domain.ContentId);

                // not published - at all
                if (domainDocument == null)
                {
                    return(false);
                }

                // invariant - always published
                if (!domainDocument.ContentType.VariesByCulture())
                {
                    return(true);
                }

                // variant, ensure that the culture corresponding to the domain's language is published
                return(domainDocument.Cultures.ContainsKey(domain.Culture.Name));
            }

            domains = domains.Where(IsPublishedContentDomain).ToList();

            var defaultCulture = domainsCache.DefaultCulture;

            // try to find a domain matching the current request
            var domainAndUri = DomainHelper.SelectDomain(domains, request.Uri, defaultCulture: defaultCulture);

            // handle domain - always has a contentId and a culture
            if (domainAndUri != null)
            {
                // matching an existing domain
                _logger.Debug <PublishedRouter>("{TracePrefix}Matches domain={Domain}, rootId={RootContentId}, culture={Culture}", tracePrefix, domainAndUri.Name, domainAndUri.ContentId, domainAndUri.Culture);

                request.Domain  = domainAndUri;
                request.Culture = domainAndUri.Culture;

                // canonical? not implemented at the moment
                // if (...)
                // {
                //  _pcr.RedirectUrl = "...";
                //  return true;
                // }
            }
            else
            {
                // not matching any existing domain
                _logger.Debug <PublishedRouter>("{TracePrefix}Matches no domain", tracePrefix);

                request.Culture = defaultCulture == null ? CultureInfo.CurrentUICulture : new CultureInfo(defaultCulture);
            }

            _logger.Debug <PublishedRouter>("{TracePrefix}Culture={CultureName}", tracePrefix, request.Culture.Name);

            return(request.Domain != null);
        }
        /// <summary>
        /// Tries to find and assign an Umbraco document to a <c>PublishedContentRequest</c>.
        /// </summary>
        /// <param name="pcr">The <c>PublishedContentRequest</c>.</param>
        /// <returns>A value indicating whether an Umbraco document was found and assigned.</returns>
        public bool TryFindContent(PublishedContentRequest pcr)
        {
            LogHelper.Debug <ContentFinderByLegacy404>("Looking for a page to handle 404.");

            // try to find a culture as best as we can
            var errorCulture = CultureInfo.CurrentUICulture;

            if (pcr.HasDomain)
            {
                errorCulture = CultureInfo.GetCultureInfo(pcr.UmbracoDomain.LanguageIsoCode);
            }
            else
            {
                var route = pcr.Uri.GetAbsolutePathDecoded();
                var pos   = route.LastIndexOf('/');
                IPublishedContent node = null;
                while (pos > 1)
                {
                    route = route.Substring(0, pos);
                    node  = pcr.RoutingContext.UmbracoContext.ContentCache.GetByRoute(route);
                    if (node != null)
                    {
                        break;
                    }
                    pos = route.LastIndexOf('/');
                }
                if (node != null)
                {
                    var d = DomainHelper.FindWildcardDomainInPath(pcr.RoutingContext.UmbracoContext.Application.Services.DomainService.GetAll(true), node.Path, null);
                    if (d != null && string.IsNullOrWhiteSpace(d.LanguageIsoCode) == false)
                    {
                        errorCulture = CultureInfo.GetCultureInfo(d.LanguageIsoCode);
                    }
                }
            }

            // TODO - replace the whole logic
            var error404 = NotFoundHandlerHelper.GetCurrentNotFoundPageId(
                //TODO: The IContentSection should be ctor injected into this class in v8!
                UmbracoConfig.For.UmbracoSettings().Content.Error404Collection.ToArray(),
                pcr.RoutingContext.UmbracoContext.Application.Services.EntityService,
                new PublishedContentQuery(pcr.RoutingContext.UmbracoContext.ContentCache, pcr.RoutingContext.UmbracoContext.MediaCache),
                errorCulture);

            IPublishedContent content = null;

            if (error404.HasValue)
            {
                LogHelper.Debug <ContentFinderByLegacy404>("Got id={0}.", () => error404.Value);

                content = pcr.RoutingContext.UmbracoContext.ContentCache.GetById(error404.Value);

                LogHelper.Debug <ContentFinderByLegacy404>(content == null
                                ? "Could not find content with that id."
                                : "Found corresponding content.");
            }
            else
            {
                LogHelper.Debug <ContentFinderByLegacy404>("Got nothing.");
            }

            pcr.PublishedContent = content;
            pcr.SetIs404();
            return(content != null);
        }