Пример #1
0
 //--- Constructors ---
 protected AttachmentBL()
 {
     _dekiContext = DekiContext.Current;
     _session     = DbUtils.CurrentSession;
     _resources   = _dekiContext.Resources;
     _resourceBL  = ResourceBL.Instance;
 }
Пример #2
0
        protected virtual void ShutdownInstance(string wikiid, DekiInstance instance)
        {
            lock (instance) {
                _log.DebugFormat("shutting down instance '{0}'", wikiid);
                var         context            = DreamContext.Current;
                var         currentDekiContext = context.GetState <DekiContext>();
                DekiContext tempDekiContext    = null;
                try {
                    if (currentDekiContext == null || currentDekiContext.Instance.Id != wikiid)
                    {
                        _log.DebugFormat("creating temp deki context for shutdown of instance '{0}'", wikiid);

                        // Note (arnec): the host header is only used for logging in the Epilogue which will never be invoked
                        // by this temporary dekicontext
                        var hostheader = wikiid + "-notused";
                        tempDekiContext = new DekiContext(_dekiService, instance, hostheader, context.StartTime, DekiWikiService.ResourceManager);
                        context.SetState(tempDekiContext);
                    }
                    instance.EndShutdown();
                } finally {
                    if (tempDekiContext != null)
                    {
                        tempDekiContext.Dispose();
                    }
                    context.SetState(currentDekiContext);
                }
            }
        }
Пример #3
0
 public TagBL()
 {
     _dekiContext = DekiContext.Current;
     _session     = DbUtils.CurrentSession;
     _user        = _dekiContext.User;
     _eventSink   = _dekiContext.Instance.EventSink;
     _culture     = DreamContext.Current.Culture;
 }
Пример #4
0
        private static XDoc BuildHtmlSiteMap(PageBE current, XDoc doc, Dictionary <ulong, PageBE> allowedPagesById, Dictionary <ulong, PageBE> filteredPagesById, int depth, bool reverse)
        {
            doc.Start("li");
            string        uri         = Utils.AsPublicUiUri(current.Title);
            List <string> classValues = new List <string>();

            if (filteredPagesById.ContainsKey(current.ID))
            {
                classValues.Add("statusRestricted");
            }
            if (current.ID == DekiContext.Current.Instance.HomePageId)
            {
                classValues.Add("statusHome");
            }

            doc.Start("a").Attr("rel", "internal").Attr("href", uri).Attr("title", current.Title.AsPrefixedUserFriendlyPath()).Attr("pageid", current.ID);
            if (classValues.Count > 0)
            {
                doc.Attr("class", string.Join(" ", classValues.ToArray()));
            }
            doc.Value(current.Title.AsUserFriendlyName()).End();

            if (depth > 0 && !ArrayUtil.IsNullOrEmpty(current.ChildPages))
            {
                PageBE[] visibleChildren = Array.FindAll(current.ChildPages, delegate(PageBE child) {
                    return(allowedPagesById.ContainsKey(child.ID));
                });
                DreamContext context = DreamContext.CurrentOrNull;
                if (context != null)
                {
                    DekiContext deki    = DekiContext.CurrentOrNull;
                    CultureInfo culture = HttpUtil.GetCultureInfoFromHeader(current.Language ?? ((deki != null) ? deki.Instance.SiteLanguage : string.Empty), context.Culture);
                    string[]    paths   = new string[visibleChildren.Length];
                    for (int i = 0; i < visibleChildren.Length; ++i)
                    {
                        paths[i] = XUri.Decode(visibleChildren[i].Title.AsPrefixedDbPath()).Replace("//", "\uFFEF").Replace("/", "\t");
                    }
                    Array.Sort(paths, visibleChildren, new CompareInfoComparer(culture.CompareInfo));
                }
                if (visibleChildren.Length > 0)
                {
                    doc.Start("ul");
                    if (reverse)
                    {
                        Array.Reverse(visibleChildren);
                    }
                    foreach (PageBE p in visibleChildren)
                    {
                        doc = BuildHtmlSiteMap(p, doc, allowedPagesById, filteredPagesById, depth - 1, reverse);
                    }
                    doc.End();
                }
            }
            doc.End();
            return(doc);
        }
Пример #5
0
        private static ServiceBE StopService(uint serviceId, ServiceBE service, ServiceStopType stopType)
        {
            if (IsLocalAuthService(serviceId))
            {
                return(service);
            }
            DekiContext context = DekiContext.Current;
            bool        saveBe  = false;

            if (service != null && service.ServiceLocal)
            {
                // local services should have their uri cleared out
                _log.DebugFormat("stopping service '{0}'", service.SID);
                service.Uri = null;
                saveBe      = true;
            }
            if (service != null && stopType == ServiceStopType.Disable)
            {
                // wipe out last error on disable
                service.ServiceLastStatus = null;
                saveBe = true;
            }
            var serviceInfo = context.Instance.RunningServices[serviceId];

            if (serviceInfo == null)
            {
                if (saveBe)
                {
                    service = UpdateService(service) ?? service;
                }

                // service is not registered as running, we're done here
                return(service);
            }

            try {
                context.Instance.DeregisterService(serviceId);
            } catch (Exception e) {
                // log the error, but ignore it otherwise
                if (service == null)
                {
                    context.Instance.Log.WarnExceptionMethodCall(e, "StopService", string.Format("Unable to stop {0} service id '{1}'", serviceInfo.IsLocal ? "local" : "remote", serviceId));
                }
                else
                {
                    context.Instance.Log.WarnExceptionMethodCall(e, "StopService", string.Format("Unable to stop {0} service id '{1}' with SID '{2}'", serviceInfo.IsLocal ? "local" : "remote", serviceId, service.SID));
                }
            }

            if (service != null && (stopType == ServiceStopType.Disable || saveBe))
            {
                service.ServiceEnabled = (stopType != ServiceStopType.Disable);
                service = UpdateService(service) ?? service;
            }
            return(service);
        }
Пример #6
0
        private static bool ValidateImpersonationToken(DekiContext context, Token token)
        {
            if (token.Timestamp < DateTime.UtcNow.Subtract(1.Minutes()))
            {
                return(false);
            }
            var userToken = string.IsNullOrEmpty(token.Username) ? token.UserId.ToString() : token.Username;
            var valid     = false;

            if (!string.IsNullOrEmpty(context.Instance.ApiKey))
            {
                valid = token.Hash.Equals(StringUtil.ComputeHashString(userToken + ":" + token.Timestamp.ToEpoch() + ":" + context.Instance.ApiKey, Encoding.UTF8));
            }
            if (!valid)
            {
                valid = token.Hash.Equals(StringUtil.ComputeHashString(userToken + ":" + token.Timestamp.ToEpoch() + ":" + context.Deki.MasterApiKey, Encoding.UTF8));
            }
            return(valid);
        }
Пример #7
0
 //--- Constructors ---
 protected AttachmentBL() {
     _dekiContext = DekiContext.Current;
     _session = DbUtils.CurrentSession;
     _resources = _dekiContext.Resources;
     _resourceBL = ResourceBL.Instance;
 }
Пример #8
0
        public static void InitializeCustomDekiScriptHeaders(PageBE page)
        {
            var           current = DreamContext.Current;
            DekiScriptMap env     = current.GetState <DekiScriptMap>("pageimplicitenv-" + page.ID);

            // check if we already have an initialized environment
            if (env == null)
            {
                DekiContext  deki     = DekiContext.Current;
                DekiInstance instance = deki.Instance;
                env = new DekiScriptMap();

                // add site fields
                DekiScriptMap siteFields = new DekiScriptMap();
                siteFields.Add("name", DekiScriptExpression.Constant(instance.SiteName));
                siteFields.Add("host", DekiScriptExpression.Constant(deki.UiUri.Uri.Host));
                siteFields.Add("language", DekiScriptExpression.Constant(instance.SiteLanguage));
                siteFields.Add("uri", DekiScriptExpression.Constant(deki.UiUri.Uri.ToString()));
                siteFields.Add("id", DekiScriptExpression.Constant(instance.Id));
                env.Add("site", siteFields);

                // add page fields
                DekiScriptMap pageFields = new DekiScriptMap();
                pageFields.Add("title", DekiScriptExpression.Constant(page.Title.AsUserFriendlyName()));
                pageFields.Add("path", DekiScriptExpression.Constant(page.Title.AsPrefixedDbPath()));
                pageFields.Add("namespace", DekiScriptExpression.Constant(Title.NSToString(page.Title.Namespace)));
                pageFields.Add("id", DekiScriptExpression.Constant(page.ID.ToString()));
                pageFields.Add("uri", DekiScriptExpression.Constant(Utils.AsPublicUiUri(page.Title)));
                pageFields.Add("date", DekiScriptExpression.Constant(page.TimeStamp.ToString("R")));
                pageFields.Add("language", DekiScriptExpression.Constant(string.IsNullOrEmpty(page.Language) ? null : page.Language));
                env.Add("page", pageFields);

                // add user fields
                DekiScriptMap userFields = new DekiScriptMap();
                if (deki.User != null)
                {
                    UserBE user = deki.User;
                    userFields.Add("id", DekiScriptExpression.Constant(user.ID.ToString()));
                    userFields.Add("name", DekiScriptExpression.Constant(user.Name));
                    userFields.Add("uri", DekiScriptExpression.Constant(Utils.AsPublicUiUri(Title.FromDbPath(NS.USER, user.Name, null))));
                    userFields.Add("emailhash", DekiScriptExpression.Constant(StringUtil.ComputeHashString((user.Email ?? string.Empty).Trim().ToLowerInvariant(), Encoding.UTF8)));
                    userFields.Add("anonymous", DekiScriptExpression.Constant(UserBL.IsAnonymous(user).ToString().ToLowerInvariant()));
                    userFields.Add("language", DekiScriptExpression.Constant(string.IsNullOrEmpty(user.Language) ? null : user.Language));
                }
                else
                {
                    userFields.Add("id", DekiScriptExpression.Constant("0"));
                    userFields.Add("name", DekiScriptExpression.Constant(string.Empty));
                    userFields.Add("uri", DekiScriptExpression.Constant(string.Empty));
                    userFields.Add("emailhash", DekiScriptExpression.Constant(string.Empty));
                    userFields.Add("anonymous", DekiScriptExpression.Constant("true"));
                    userFields.Add("language", DekiScriptNil.Value);
                }
                env.Add("user", userFields);

                // store env for later
                current.SetState("pageimplicitenv-" + page.ID, env);
            }

            // set implicit environment
            DreamContext.Current.SetState(env);
        }
Пример #9
0
        private DreamMessage PreProcessRequest(string verb, XUri uri, XUri normalizedUri, DreamMessage message)
        {
            DreamContext current  = DreamContext.Current;
            DekiContext  deki     = DekiContext.Current;
            DekiInstance instance = deki.Instance;

            // set preferred culture
            message.Headers.AcceptLanguage = string.Format("{0}, *;q=0.5", current.Culture.Name);

            // add the 'deki' header
            message.Headers[DekiExtService.DEKI_HEADER] = instance.Token;

            // convert implicit environment into a message headers
            DekiScriptMap implicitEnv = DreamContext.Current.GetState <DekiScriptMap>();

            if (implicitEnv != null)
            {
                foreach (KeyValuePair <string, DekiScriptLiteral> outer in implicitEnv.Value)
                {
                    DekiScriptMap map = outer.Value as DekiScriptMap;
                    if ((map != null) && !map.IsEmpty)
                    {
                        StringBuilder header = new StringBuilder();
                        foreach (KeyValuePair <string, DekiScriptLiteral> inner in map.Value)
                        {
                            string value = inner.Value.AsString();
                            if (value != null)
                            {
                                if (header.Length > 0)
                                {
                                    header.Append(", ");
                                }
                                header.AppendFormat("{0}.{1}={2}", outer.Key, inner.Key, value.QuoteString());
                            }
                        }

                        // add header
                        string headerValue = header.ToString();
                        message.Headers.Add(DekiExtService.IMPLICIT_ENVIRONMENT_HEADER, headerValue);
                    }
                }
            }

            // add digital signature
            DSACryptoServiceProvider dsa = instance.PrivateDigitalSignature;

            if (dsa != null)
            {
                MemoryStream data = new MemoryStream();

                // get message bytes
                byte[] bytes = message.AsBytes();
                data.Write(bytes, 0, bytes.Length);

                // retrieve headers to sign
                string[] headers = message.Headers.GetValues(DekiExtService.IMPLICIT_ENVIRONMENT_HEADER);
                if (!ArrayUtil.IsNullOrEmpty(headers))
                {
                    Array.Sort(headers, StringComparer.Ordinal);
                    bytes = Encoding.UTF8.GetBytes(string.Join(",", headers));
                    data.Write(bytes, 0, bytes.Length);
                }

                // add request date
                string date = DateTime.UtcNow.ToString(XDoc.RFC_DATETIME_FORMAT);
                bytes = Encoding.UTF8.GetBytes(date);
                data.Write(bytes, 0, bytes.Length);

                // sign data
                byte[] signature = dsa.SignData(data.GetBuffer());
                message.Headers.Add(DekiExtService.IMPLICIT_SIGNATURE_HEADER, string.Format("dsig=\"{0}\", date=\"{1}\"", Convert.ToBase64String(signature), date));
            }
            return(message);
        }
Пример #10
0
 protected virtual void ShutdownInstance(string wikiid, DekiInstance instance) {
     if(instance.Status == DekiInstanceStatus.RUNNING) {
         DekiContext dekiContext = new DekiContext(_dekiService, instance, DreamContext.Current.Request);
         DreamContext.Current.SetState<DekiContext>(dekiContext);
         lock(instance) {
             instance.Shutdown();
         }
     }
 }
Пример #11
0
        //--- Class Methods ---
        public static ServiceBE StartService(ServiceBE service, bool forceRefresh, bool disableOnFailure)
        {
            // create subordinate request id for service start
            var dreamContext = DreamContext.Current;
            var requestId    = dreamContext.GetState <string>(DreamHeaders.DREAM_REQUEST_ID);

            dreamContext.SetState(DreamHeaders.DREAM_REQUEST_ID, requestId + "-service_" + service.Id);

            try {
                var stopwatch = Stopwatch.StartNew();
                service.ServiceLastStatus = string.Empty;
                StopService(service.Id, service, ServiceStopType.Restart);
                DekiContext context            = DekiContext.Current;
                bool        dirtyServiceEntity = false;
                XUri        location;
                ServiceRepository.IServiceInfo serviceInfo = null;
                try {
                    // check if service is local
                    if (service.ServiceLocal)
                    {
                        if (string.IsNullOrEmpty(service.SID))
                        {
                            throw new Exception("missing SID");
                        }

                        // start service
                        if (IsLocalAuthService(service))
                        {
                            // this service is the built-in authentication provider; no need to start it
                            location = context.Deki.Self;
                        }
                        else
                        {
                            // convert local service configuration into an xdoc
                            XDoc config = new XDoc("config");
                            foreach (KeyValuePair <string, string> configEntry in ArrayUtil.AllKeyValues(service.Config))
                            {
                                config.InsertValueAt(configEntry.Key, configEntry.Value);
                            }

                            // if no apikey was provided, create a random one so that CreateService doesn't inject the parent one
                            if (config["apikey"].IsEmpty)
                            {
                                config.Elem("apikey", StringUtil.CreateAlphaNumericKey(16));
                            }

                            // add information for service to callback into deki
                            if (config["uri.deki"].IsEmpty)
                            {
                                config.Elem("uri.deki", context.Deki.Self);
                                config.Elem("wikiid.deki", context.Instance.Id);

                                // Providing master apikey to service for setups that don't use per instance keys
                                config.Elem("apikey.deki", context.Instance.ApiKey.IfNullOrEmpty(context.Deki.MasterApiKey));
                            }

                            // the service location must use the service ID and the instance ID
                            string servicePath = string.Format("services/{0}/{1}", context.Instance.Id, service.Id);
                            _log.DebugFormat("starting service '{0}' at path {1} w/ namespace {2}", service.SID, servicePath, service.Preferences["namespace"]);
                            serviceInfo = context.Instance.CreateLocalService(service, servicePath, config);
                            location    = serviceInfo.ServiceUri;
                        }

                        // check if the service uri has changed since last invocation (happens when service is started for the first time or server GUID has changed)
                        if (!service.Uri.EqualsInvariantIgnoreCase(location.ToString()))
                        {
                            dirtyServiceEntity = true;
                            service.Uri        = location.ToString();
                        }
                    }
                    else
                    {
                        _log.DebugFormat("registering remote service '{0}'", service.SID);
                        if (string.IsNullOrEmpty(service.Uri))
                        {
                            throw new Exception("missing URI");
                        }
                        location    = new XUri(service.Uri);
                        serviceInfo = context.Instance.RegisterRemoteService(service, location);
                    }

                    // check if service is an Extension service
                    if (service.Type == ServiceType.EXT)
                    {
                        if (service.ServiceLocal)
                        {
                            _log.DebugFormat("registering service '{0}' as extension", service.SID);
                        }
                        ExtensionBL.StartExtensionService(context, service, serviceInfo, forceRefresh);
                    }

                    //Successfully starting a service enables it.
                    if (!service.ServiceEnabled)
                    {
                        dirtyServiceEntity     = true;
                        service.ServiceEnabled = true;
                    }
                } catch (Exception e) {
                    dirtyServiceEntity = true;
                    DreamMessage dm = null;
                    if (e is DreamResponseException)
                    {
                        dm = ((DreamResponseException)e).Response;
                        string message = dm.HasDocument ? dm.ToDocument()[".//message"].AsText.IfNullOrEmpty(e.Message) : dm.ToText();
                        service.ServiceLastStatus = string.Format("unable to initialize service ({0})", message);
                    }
                    else
                    {
                        service.ServiceLastStatus = e.GetCoroutineStackTrace();
                    }
                    if (serviceInfo != null)
                    {
                        try {
                            context.Instance.DeregisterService(service.Id);
                        } catch { }
                    }

                    // A service that fails to start becomes disabled if it's started explicitly (not during deki startup)
                    if (disableOnFailure)
                    {
                        service.ServiceEnabled = false;
                    }
                    _log.ErrorExceptionMethodCall(e, "StartService", string.Format("Unable to start local service id '{0}' with SID '{1}' Error: '{2}'", service.Id, service.SID, service.ServiceLastStatus));
                    if (dm != null)
                    {
                        throw new ExternalServiceResponseException(dm);
                    }
                    else
                    {
                        throw;
                    }
                } finally {
                    // don't update remote services that haven't changed
                    if (dirtyServiceEntity)
                    {
                        service = UpdateService(service);
                    }
                }
                stopwatch.Stop();
                _log.InfoFormat("Service '{0}' ({1}) started in {2}ms", service.Description, service.SID, stopwatch.ElapsedMilliseconds);
                return(service);
            } finally {
                // restore the request id
                dreamContext.SetState(DreamHeaders.DREAM_REQUEST_ID, requestId);
            }
        }
Пример #12
0
        //--- Class Methods ---
        public static void StartExtensionService(DekiContext context, ServiceBE service, ServiceRepository.IServiceInfo serviceInfo, bool forceRefresh) {

            // retrieve document describing the extension functions
            XUri uri = new XUri(service.Uri);
            XDoc manifest = null;
            DekiWikiService deki = context.Deki;
            var extension = serviceInfo.Extension;
            if(!service.ServiceLocal) {
                lock(deki.RemoteExtensionLibraries) {
                    deki.RemoteExtensionLibraries.TryGetValue(uri, out manifest);
                }
            }
            if(manifest == null || forceRefresh) {
                manifest = Plug.New(uri).Get().ToDocument();

                // normalize the extension XML
                manifest = manifest.TransformAsXml(_extensionConverterXslt);

                // check if document describes a valid extension: either the extension has no functions, or the functions have end-points
                if(manifest.HasName("extension") && ((manifest["function"].ListLength == 0) || (manifest["function/uri"].ListLength > 0))) {

                    // add source uri for service
                    manifest.Attr("uri", uri);

                    // register service in extension list
                    lock(deki.RemoteExtensionLibraries) {
                        deki.RemoteExtensionLibraries[uri] = manifest;
                    }
                } else {
                    throw new ExtensionRemoveServiceInvalidOperationException(uri);
                }
            }
            extension.Manifest = manifest;

            // add function prefix if one is defined
            serviceInfo.Extension.SetPreference("namespace.custom", service.Preferences["namespace"]);
            string serviceNamespace = service.Preferences["namespace"] ?? manifest["namespace"].AsText;
            if(serviceNamespace != null) {
                serviceNamespace = serviceNamespace.Trim();
                if(string.IsNullOrEmpty(serviceInfo.Namespace)) {

                    // Note (arnec): Namespace from preferences is assigned at service creation. If we do not have one at this
                    // point, it came from the extension manifest and needs to be registered as our default. Otherwise the
                    // preference override persists as the namespace.
                    context.Instance.RunningServices.RegisterNamespace(serviceInfo, serviceNamespace);
                }
                if(serviceNamespace.Length != 0) {
                    if(!DekiScriptParser.IsIdentifier(serviceNamespace)) {
                        throw new ExtensionNamespaceInvalidArgumentException(service.Preferences["namespace"] ?? manifest["namespace"].AsText);
                    }
                } else {
                    serviceNamespace = null;
                }
            }
            serviceNamespace = (serviceNamespace == null) ? string.Empty : (serviceNamespace + ".");

            // add custom library title

            extension.SetPreference("title.custom", service.Preferences["title"]);
            extension.SetPreference("label.custom", service.Preferences["label"]);
            extension.SetPreference("description.custom", service.Preferences["description"]);
            extension.SetPreference("uri.logo.custom", service.Preferences["uri.logo"]);
            extension.SetPreference("functions", service.Preferences["functions"]);
            extension.SetPreference("protected", service.Preferences["protected"]);

            // add each extension function
            bool.TryParse(service.Preferences["protected"], out extension.IsProtected);
            var functions = new List<ServiceRepository.ExtensionFunctionInfo>();
            foreach(XDoc function in manifest["function"]) {
                XUri functionUri = function["uri"].AsUri;
                if(functionUri != null) {
                    functions.Add(new ServiceRepository.ExtensionFunctionInfo(serviceNamespace + function["name"].Contents, functionUri));
                }
            }
            extension.Functions = functions.ToArray();
        }
Пример #13
0
 private static bool ValidateImpersonationToken(DekiContext context, Token token) {
     if(token.Timestamp < DateTime.UtcNow.Subtract(1.Minutes())) {
         return false;
     }
     var userToken = string.IsNullOrEmpty(token.Username) ? token.UserId.ToString() : token.Username;
     var valid = false;
     if(!string.IsNullOrEmpty(context.Instance.ApiKey)) {
         valid = token.Hash.Equals(StringUtil.ComputeHashString(userToken + ":" + token.Timestamp.ToEpoch() + ":" + context.Instance.ApiKey, Encoding.UTF8));
     }
     if(!valid) {
         valid = token.Hash.Equals(StringUtil.ComputeHashString(userToken + ":" + token.Timestamp.ToEpoch() + ":" + context.Deki.MasterApiKey, Encoding.UTF8));
     }
     return valid;
 }
Пример #14
0
 //--- Class Methods ---
 internal static void Log(TimeSpan elapsed, PageBE basePage, DekiContext context, IDekiDataSession session) {
     _log.WarnFormat("slow page render for: {0}\n{1}", basePage.Title.AsPrefixedDbPath().IfNullOrEmpty("_homepage_"), CreateProfilerDoc(elapsed, basePage, context, session).ToPrettyString());
 }
Пример #15
0
 //--- Class Methods ---
 internal static void Log(TimeSpan elapsed, PageBE basePage, DekiContext context, IDekiDataSession session)
 {
     _log.WarnFormat("slow page render for: {0}\n{1}", basePage.Title.AsPrefixedDbPath().IfNullOrEmpty("_homepage_"), CreateProfilerDoc(elapsed, basePage, context, session).ToPrettyString());
 }
Пример #16
0
        public static DekiScriptEnv CreateEnvironment(PageBE page)
        {
            DekiScriptEnv commonEnv = DekiContext.Current.Instance.CreateEnvironment();

            // need to strip the config value back out for Deki
            commonEnv.Vars["config"] = new DekiScriptMap();

            // initialize environment
            DekiScriptEnv env      = commonEnv;
            DekiContext   deki     = DekiContext.Current;
            DekiInstance  instance = deki.Instance;

            // add site variables
            env.Vars.AddNativeValueAt("site.name", instance.SiteName);
            env.Vars.AddNativeValueAt("site.hostname", deki.UiUri.Uri.HostPort);
            env.Vars.AddNativeValueAt("site.api", deki.ApiUri.SchemeHostPortPath);
            env.Vars.AddNativeValueAt("site.language", instance.SiteLanguage);
            env.Vars.AddNativeValueAt("site.uri", deki.UiUri.Uri.ToString());
            env.Vars.AddNativeValueAt("site.pagecount", deki.Deki.PropertyAt("$sitepagecount"));
            env.Vars.AddNativeValueAt("site.usercount", deki.Deki.PropertyAt("$siteusercount"));
            env.Vars.AddNativeValueAt("site.homepage", deki.Deki.PropertyAt("$page", DekiContext.Current.Instance.HomePageId, true));
            env.Vars.AddNativeValueAt("site.feed", deki.ApiUri.At("site", "feed").ToString());
            env.Vars.AddNativeValueAt("site.tags", deki.Deki.PropertyAt("$sitetags"));
            env.Vars.AddNativeValueAt("site.users", deki.Deki.PropertyAt("$siteusers"));
            env.Vars.AddNativeValueAt("site.id", DekiScriptExpression.Constant(instance.Id));
            env.Vars.AddNativeValueAt("site.timezone", DekiScriptExpression.Constant(instance.SiteTimezone));

            // add page variables
            env.Vars.Add("page", deki.Deki.PropertyAt("$page", page.ID, true));

            // add user variables
            env.Vars.Add("user", deki.Deki.PropertyAt("$user", (deki.User != null) ? deki.User.ID : 0));

            // add instance functions & properties
            bool hasUnsafeContentPermission = DekiXmlParser.PageAuthorCanExecute();

            foreach (var service in instance.RunningServices.ExtensionServices)
            {
                if (service != null)
                {
                    var extension = service.Extension;
                    if (extension != null)
                    {
                        if (hasUnsafeContentPermission || !extension.IsProtected)
                        {
                            var functions = extension.Functions;
                            if (functions != null)
                            {
                                foreach (var function in functions)
                                {
                                    env.Vars.AddNativeValueAt(function.Name.ToLowerInvariant(), function.Uri);
                                }
                            }
                            else
                            {
                                _log.WarnFormat("CreateEnvironment - null functions (id: {0})", service.ServiceId);
                            }
                        }
                    }
                    else
                    {
                        _log.WarnFormat("CreateEnvironment - null extension (id: {0})", service.ServiceId);
                    }
                }
                else
                {
                    _log.Warn("CreateEnvironment - null service");
                }
            }
            return(env);
        }
Пример #17
0
        internal static XDoc CreateProfilerDoc(TimeSpan elapsed, PageBE basePage, DekiContext context, IDekiDataSession session) {
            var profiler = new XDoc("profiler")
                .Attr("elapsed", elapsed.TotalSeconds.ToString("###,0.00##"))
                .Attr("id", context.Instance.Id)
                .Attr("path", basePage.Title.AsPrefixedDbPath());
            var history = DekiXmlParser.GetParseState().ProfilerHistory;

            // show profiling for rendered pages
            profiler.Start("rendered-content");
            foreach(var pageHistory in history) {
                profiler.Start("page")
                    .Attr("wikiid", pageHistory.PageId)
                    .Attr("path", pageHistory.PagePath)
                    .Attr("elapsed", pageHistory.Elapsed.TotalSeconds.ToString("###,0.00##"))
                    .Attr("mode", pageHistory.Mode.ToString().ToLowerInvariant());
                foreach(var functionHistory in
                    from function in pageHistory.Functions
                    group function by function.Location
                        into functionByLocation
                        select new {
                            Function = functionByLocation.First(),
                            Count = functionByLocation.Count(),
                            TotalSeconds = functionByLocation.Sum(f => f.Elapsed.TotalSeconds)
                        }
                ) {
                    profiler.Start("function")
                        .Attr("name", functionHistory.Function.FunctionName)
                        .Attr("elapsed", functionHistory.TotalSeconds.ToString("###,0.00##"))
                        .Attr("count", functionHistory.Count)
                        .Attr("location", functionHistory.Function.Location)
                    .End();
                }
                profiler.End();
            }
            profiler.End();

            // show summary for function profiling
            profiler.Start("functions-summary");
            foreach(var functionHistory in
                from pageHistory in history
                from function in pageHistory.Functions
                group function by function.FunctionName
                    into functionByName
                    let totalSeconds = functionByName.Sum(f => f.Elapsed.TotalSeconds)
                    orderby totalSeconds descending
                    select new {
                        Function = functionByName.First(),
                        Count = functionByName.Count(),
                        TotalSeconds = totalSeconds,
                        MaxSeconds = functionByName.Max(f => f.Elapsed.TotalSeconds)
                    }
            ) {
                profiler.Start("function")
                    .Attr("name", functionHistory.Function.FunctionName)
                    .Attr("elapsed", functionHistory.TotalSeconds.ToString("###,0.00##"))
                    .Attr("average", (functionHistory.TotalSeconds / functionHistory.Count).ToString("###,0.00##"))
                    .Attr("max", functionHistory.MaxSeconds.ToString("###,0.00##"))
                    .Attr("count", functionHistory.Count)
                .End();
            }
            profiler.End();

            // show summary for page profiling
            profiler.Start("pages-summary");
            foreach(var pageHistory in
                from page in history
                group page by page.PageId.ToString() + page.Mode
                    into pageByIdAndMode
                    let totalSeconds = pageByIdAndMode.Sum(p => p.Elapsed.TotalSeconds)
                    orderby totalSeconds descending
                    select new {
                        Page = pageByIdAndMode.First(),
                        Count = pageByIdAndMode.Count(),
                        TotalSeconds = totalSeconds,
                        MaxSeconds = pageByIdAndMode.Max(p => p.Elapsed.TotalSeconds)
                    }
            ) {
                profiler.Start("page")
                    .Attr("id", pageHistory.Page.PageId)
                    .Attr("path", pageHistory.Page.PagePath)
                    .Attr("elapsed", pageHistory.TotalSeconds.ToString("###,0.00##"))
                    .Attr("average", (pageHistory.TotalSeconds / pageHistory.Count).ToString("###,0.00##"))
                    .Attr("max", pageHistory.MaxSeconds.ToString("###,0.00##"))
                    .Attr("count", pageHistory.Count)
                    .Attr("mode", pageHistory.Page.Mode.ToString().ToLowerInvariant())
                .End();
            }
            profiler.End();

            // show summary for query operations
            var dbprofiler = GetSessionProfiler(session);
            if(dbprofiler != null) {
                var dbhistory = dbprofiler.History;
                profiler.Start("db-summary")
                    .Attr("elapsed", dbhistory.Sum(p => p.Elapsed.TotalSeconds).ToString("###,0.00##"))
                    .Attr("count", dbhistory.Count);
                foreach(var dbsummary in
                    from dbentry in dbhistory
                    group dbentry by dbentry.Function
                        into dbentryByName
                        let totalSeconds = dbentryByName.Sum(f => f.Elapsed.TotalSeconds)
                        orderby totalSeconds descending
                        select new {
                            Query = dbentryByName.First(),
                            Count = dbentryByName.Count(),
                            TotalSeconds = totalSeconds,
                            MaxSeconds = dbentryByName.Max(f => f.Elapsed.TotalSeconds)
                        }
                ) {
                    profiler.Start("query")
                        .Attr("name", dbsummary.Query.Function)
                        .Attr("elapsed", dbsummary.TotalSeconds.ToString("###,0.00##"))
                        .Attr("average", (dbsummary.TotalSeconds / dbsummary.Count).ToString("###,0.00##"))
                        .Attr("max", dbsummary.MaxSeconds.ToString("###,0.00##"))
                        .Attr("count", dbsummary.Count)
                    .End();
                }
                profiler.End();
            }

            // add data stats
            Dictionary<string, string> stats;
            var sessionStats = session as IDekiDataStats;
            if(sessionStats != null) {
                profiler.Start("data-stats");
                stats = sessionStats.GetStats();
                if(stats != null) {
                    foreach(var pair in stats) {
                        profiler.Start("entry").Attr("name", pair.Key).Attr("value", pair.Value).End();
                    }
                }
                profiler.End();
            }

            // add misc. statistics
            stats = DekiContext.Current.Stats;
            if(stats.Count > 0) {
                profiler.Start("misc-stats");
                foreach(var pair in stats) {
                    profiler.Start("entry").Attr("name", pair.Key).Attr("value", pair.Value).End();
                }
                profiler.End();
            }
            return profiler;
        }
Пример #18
0
        internal static XDoc CreateProfilerDoc(TimeSpan elapsed, PageBE basePage, DekiContext context, IDekiDataSession session)
        {
            var profiler = new XDoc("profiler")
                           .Attr("elapsed", elapsed.TotalSeconds.ToString("###,0.00##"))
                           .Attr("id", context.Instance.Id)
                           .Attr("path", basePage.Title.AsPrefixedDbPath());
            var history = DekiXmlParser.GetParseState().ProfilerHistory;

            // show profiling for rendered pages
            profiler.Start("rendered-content");
            foreach (var pageHistory in history)
            {
                profiler.Start("page")
                .Attr("wikiid", pageHistory.PageId)
                .Attr("path", pageHistory.PagePath)
                .Attr("elapsed", pageHistory.Elapsed.TotalSeconds.ToString("###,0.00##"))
                .Attr("mode", pageHistory.Mode.ToString().ToLowerInvariant());
                foreach (var functionHistory in
                         from function in pageHistory.Functions
                         group function by function.Location
                         into functionByLocation
                         select new {
                    Function = functionByLocation.First(),
                    Count = functionByLocation.Count(),
                    TotalSeconds = functionByLocation.Sum(f => f.Elapsed.TotalSeconds)
                }
                         )
                {
                    profiler.Start("function")
                    .Attr("name", functionHistory.Function.FunctionName)
                    .Attr("elapsed", functionHistory.TotalSeconds.ToString("###,0.00##"))
                    .Attr("count", functionHistory.Count)
                    .Attr("location", functionHistory.Function.Location)
                    .End();
                }
                profiler.End();
            }
            profiler.End();

            // show summary for function profiling
            profiler.Start("functions-summary");
            foreach (var functionHistory in
                     from pageHistory in history
                     from function in pageHistory.Functions
                     group function by function.FunctionName
                     into functionByName
                     let totalSeconds = functionByName.Sum(f => f.Elapsed.TotalSeconds)
                                        orderby totalSeconds descending
                                        select new {
                Function = functionByName.First(),
                Count = functionByName.Count(),
                TotalSeconds = totalSeconds,
                MaxSeconds = functionByName.Max(f => f.Elapsed.TotalSeconds)
            }
                     )
            {
                profiler.Start("function")
                .Attr("name", functionHistory.Function.FunctionName)
                .Attr("elapsed", functionHistory.TotalSeconds.ToString("###,0.00##"))
                .Attr("average", (functionHistory.TotalSeconds / functionHistory.Count).ToString("###,0.00##"))
                .Attr("max", functionHistory.MaxSeconds.ToString("###,0.00##"))
                .Attr("count", functionHistory.Count)
                .End();
            }
            profiler.End();

            // show summary for page profiling
            profiler.Start("pages-summary");
            foreach (var pageHistory in
                     from page in history
                     group page by page.PageId.ToString() + page.Mode
                     into pageByIdAndMode
                     let totalSeconds = pageByIdAndMode.Sum(p => p.Elapsed.TotalSeconds)
                                        orderby totalSeconds descending
                                        select new {
                Page = pageByIdAndMode.First(),
                Count = pageByIdAndMode.Count(),
                TotalSeconds = totalSeconds,
                MaxSeconds = pageByIdAndMode.Max(p => p.Elapsed.TotalSeconds)
            }
                     )
            {
                profiler.Start("page")
                .Attr("id", pageHistory.Page.PageId)
                .Attr("path", pageHistory.Page.PagePath)
                .Attr("elapsed", pageHistory.TotalSeconds.ToString("###,0.00##"))
                .Attr("average", (pageHistory.TotalSeconds / pageHistory.Count).ToString("###,0.00##"))
                .Attr("max", pageHistory.MaxSeconds.ToString("###,0.00##"))
                .Attr("count", pageHistory.Count)
                .Attr("mode", pageHistory.Page.Mode.ToString().ToLowerInvariant())
                .End();
            }
            profiler.End();

            // show summary for query operations
            var dbprofiler = GetSessionProfiler(session);

            if (dbprofiler != null)
            {
                var dbhistory = dbprofiler.History;
                profiler.Start("db-summary")
                .Attr("elapsed", dbhistory.Sum(p => p.Elapsed.TotalSeconds).ToString("###,0.00##"))
                .Attr("count", dbhistory.Count);
                foreach (var dbsummary in
                         from dbentry in dbhistory
                         group dbentry by dbentry.Function
                         into dbentryByName
                         let totalSeconds = dbentryByName.Sum(f => f.Elapsed.TotalSeconds)
                                            orderby totalSeconds descending
                                            select new {
                    Query = dbentryByName.First(),
                    Count = dbentryByName.Count(),
                    TotalSeconds = totalSeconds,
                    MaxSeconds = dbentryByName.Max(f => f.Elapsed.TotalSeconds)
                }
                         )
                {
                    profiler.Start("query")
                    .Attr("name", dbsummary.Query.Function)
                    .Attr("elapsed", dbsummary.TotalSeconds.ToString("###,0.00##"))
                    .Attr("average", (dbsummary.TotalSeconds / dbsummary.Count).ToString("###,0.00##"))
                    .Attr("max", dbsummary.MaxSeconds.ToString("###,0.00##"))
                    .Attr("count", dbsummary.Count)
                    .End();
                }
                profiler.End();
            }

            // add data stats
            Dictionary <string, string> stats;
            var sessionStats = session as IDekiDataStats;

            if (sessionStats != null)
            {
                profiler.Start("data-stats");
                stats = sessionStats.GetStats();
                if (stats != null)
                {
                    foreach (var pair in stats)
                    {
                        profiler.Start("entry").Attr("name", pair.Key).Attr("value", pair.Value).End();
                    }
                }
                profiler.End();
            }

            // add misc. statistics
            stats = DekiContext.Current.Stats;
            if (stats.Count > 0)
            {
                profiler.Start("misc-stats");
                foreach (var pair in stats)
                {
                    profiler.Start("entry").Attr("name", pair.Key).Attr("value", pair.Value).End();
                }
                profiler.End();
            }
            return(profiler);
        }
Пример #19
0
        //--- Class Methods ---
        public static void StartExtensionService(DekiContext context, ServiceBE service, ServiceRepository.IServiceInfo serviceInfo, bool forceRefresh)
        {
            // retrieve document describing the extension functions
            XUri            uri       = new XUri(service.Uri);
            XDoc            manifest  = null;
            DekiWikiService deki      = context.Deki;
            var             extension = serviceInfo.Extension;

            if (!service.ServiceLocal)
            {
                lock (deki.RemoteExtensionLibraries) {
                    deki.RemoteExtensionLibraries.TryGetValue(uri, out manifest);
                }
            }
            if (manifest == null || forceRefresh)
            {
                manifest = Plug.New(uri).Get().ToDocument();

                // normalize the extension XML
                manifest = manifest.TransformAsXml(_extensionConverterXslt);

                // check if document describes a valid extension: either the extension has no functions, or the functions have end-points
                if (manifest.HasName("extension") && ((manifest["function"].ListLength == 0) || (manifest["function/uri"].ListLength > 0)))
                {
                    // add source uri for service
                    manifest.Attr("uri", uri);

                    // register service in extension list
                    lock (deki.RemoteExtensionLibraries) {
                        deki.RemoteExtensionLibraries[uri] = manifest;
                    }
                }
                else
                {
                    throw new ExtensionRemoveServiceInvalidOperationException(uri);
                }
            }
            extension.Manifest = manifest;

            // add function prefix if one is defined
            serviceInfo.Extension.SetPreference("namespace.custom", service.Preferences["namespace"]);
            string serviceNamespace = service.Preferences["namespace"] ?? manifest["namespace"].AsText;

            if (serviceNamespace != null)
            {
                serviceNamespace = serviceNamespace.Trim();
                if (string.IsNullOrEmpty(serviceInfo.Namespace))
                {
                    // Note (arnec): Namespace from preferences is assigned at service creation. If we do not have one at this
                    // point, it came from the extension manifest and needs to be registered as our default. Otherwise the
                    // preference override persists as the namespace.
                    context.Instance.RunningServices.RegisterNamespace(serviceInfo, serviceNamespace);
                }
                if (serviceNamespace.Length != 0)
                {
                    if (!DekiScriptParser.IsIdentifier(serviceNamespace))
                    {
                        throw new ExtensionNamespaceInvalidArgumentException(service.Preferences["namespace"] ?? manifest["namespace"].AsText);
                    }
                }
                else
                {
                    serviceNamespace = null;
                }
            }
            serviceNamespace = (serviceNamespace == null) ? string.Empty : (serviceNamespace + ".");

            // add custom library title

            extension.SetPreference("title.custom", service.Preferences["title"]);
            extension.SetPreference("label.custom", service.Preferences["label"]);
            extension.SetPreference("description.custom", service.Preferences["description"]);
            extension.SetPreference("uri.logo.custom", service.Preferences["uri.logo"]);
            extension.SetPreference("functions", service.Preferences["functions"]);
            extension.SetPreference("protected", service.Preferences["protected"]);

            // add each extension function
            bool.TryParse(service.Preferences["protected"], out extension.IsProtected);
            var functions = new List <ServiceRepository.ExtensionFunctionInfo>();

            foreach (XDoc function in manifest["function"])
            {
                XUri functionUri = function["uri"].AsUri;
                if (functionUri != null)
                {
                    functions.Add(new ServiceRepository.ExtensionFunctionInfo(serviceNamespace + function["name"].Contents, functionUri));
                }
            }
            extension.Functions = functions.ToArray();
        }
Пример #20
0
        protected virtual void ShutdownInstance(string wikiid, DekiInstance instance) {
            lock(instance) {
                _log.DebugFormat("shutting down instance '{0}'", wikiid);
                var context = DreamContext.Current;
                var currentDekiContext = context.GetState<DekiContext>();
                DekiContext tempDekiContext = null;
                try {
                    if(currentDekiContext == null || currentDekiContext.Instance.Id != wikiid) {
                        _log.DebugFormat("creating temp deki context for shutdown of instance '{0}'", wikiid);

                        // Note (arnec): the host header is only used for logging in the Epilogue which will never be invoked
                        // by this temporary dekicontext
                        var hostheader = wikiid + "-notused";
                        tempDekiContext = new DekiContext(_dekiService, instance, hostheader, context.StartTime, DekiWikiService.ResourceManager);
                        context.SetState(tempDekiContext);
                    }
                    instance.EndShutdown();
                } finally {
                    if(tempDekiContext != null) {
                        tempDekiContext.Dispose();
                    }
                    context.SetState(currentDekiContext);
                }
            }
        }
Пример #21
0
        public static XDoc GetUserXml(UserBE user, string relation, bool showPrivateInfo)
        {
            XDoc userXml = new XDoc(string.IsNullOrEmpty(relation) ? "user" : "user." + relation);

            userXml.Attr("id", user.ID);
            userXml.Attr("href", DekiContext.Current.ApiUri.At("users", user.ID.ToString()));
            userXml.Elem("nick", user.Name);
            userXml.Elem("username", user.Name);
            userXml.Elem("fullname", user.RealName ?? String.Empty);

            // check if we can add the email address
            if (showPrivateInfo)
            {
                userXml.Elem("email", user.Email);
            }
            else
            {
                userXml.Start("email").Attr("hidden", true).End();
            }

            // seat assignment and site ownership
            var license = DekiContext.Current.LicenseManager;

            if (license.IsSeatLicensingEnabled())
            {
                userXml.Start("license.seat").Value(user.LicenseSeat);
                if (user.LicenseSeat && (license.GetSiteOwnerUserId() ?? 0) == user.ID)
                {
                    userXml.Attr("owner", true);
                }
                userXml.End();
            }

            // add gravatar
            if (!IsAnonymous(user) && !string.IsNullOrEmpty(user.Email))
            {
                DekiContext context  = DekiContext.CurrentOrNull;
                XUri        gravatar = new XUri("http://www.gravatar.com/avatar");
                string      hash     = string.Empty;
                if (context != null)
                {
                    DekiInstance deki   = context.Instance;
                    string       secure = context.Instance.GravatarSalt ?? string.Empty;
                    if (!secure.EqualsInvariantIgnoreCase("hidden"))
                    {
                        hash = StringUtil.ComputeHashString(secure + (user.Email ?? string.Empty).Trim().ToLowerInvariant(), System.Text.Encoding.UTF8);
                    }

                    // add size, if any
                    string size = deki.GravatarSize;
                    if (size != null)
                    {
                        gravatar = gravatar.With("s", size);
                    }

                    // add rating, if any
                    string rating = deki.GravatarRating;
                    if (rating != null)
                    {
                        gravatar = gravatar.With("r", rating);
                    }

                    // add default icon, if any
                    string def = deki.GravatarDefault;
                    if (def != null)
                    {
                        gravatar = gravatar.With("d", def);
                    }
                }
                if (!string.IsNullOrEmpty(hash))
                {
                    userXml.Elem("hash.email", hash);
                    userXml.Elem("uri.gravatar", gravatar.At(hash + ".png"));
                    userXml.Elem("uri.avatar", gravatar.At(hash + ".png"));
                }
                else
                {
                    userXml.Elem("hash.email", string.Empty);
                    userXml.Elem("uri.gravatar", gravatar.At("no-email.png"));
                    userXml.Elem("uri.avatar", gravatar.At(hash + ".png"));
                }
            }
            return(userXml);
        }