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); } } }
//--- Constructor --- public SiteBL() { var dekiContext = DekiContext.Current; _dekiInstance = dekiContext.Instance; _user = dekiContext.User; }
protected override void ShutdownInstance(string wikiid, DekiInstance instance) { lock (instance) { // On instance shutdown, remove host to wikiId association. lock (_hostsToWikiIds) { foreach (var hostDoc in instance.Config["host"]) { var host = hostDoc.AsText; _hostsToWikiIds.Remove(host); } } base.ShutdownInstance(wikiid, instance); } }
protected DekiInstance CreateWikiInstance(string wikiId, XDoc instanceConfig) { List <DekiInstance> instances = null; DekiInstance instance; lock (_instances) { instance = GetWikiInstance(wikiId); if (instance == null) { var licenseStoragePlug = _dekiService.Storage; _loggerRepositories[wikiId] = new ContextLoggerRepository("[" + wikiId + "] "); var licenseController = GetLicenseController(wikiId, licenseStoragePlug); _instances[wikiId] = instance = new DekiInstance(_dekiService, wikiId, instanceConfig, licenseController); } // Schedule new instance for shutdown if inactive-instance-timeout enabled. if (InactiveInstanceTimeOut != TimeSpan.MaxValue) { var timer = _timerFactory.New(OnInstanceExpireTimer, wikiId); _instanceExpireTimers[wikiId] = timer; } if (_instances.Count > _maxInstances) { instances = _instances.Values.ToList(); } } // Hit the instance number limit? Look for least recently accessed wiki and shut it down. if (instances != null) { Async.Fork(() => { _log.DebugFormat("looking for excess instances to shut down"); var excessInstances = (from candidate in instances where DateTime.UtcNow - candidate.InstanceLastUpdateTime >= _minInstanceIdletime orderby candidate.InstanceLastUpdateTime select candidate.Id) .Take(instances.Count - _maxInstances); foreach (var shutdownId in excessInstances) { _log.DebugFormat("shutting down instance '{0}'", shutdownId); OutOfContextShutdown(shutdownId); } }); } return(instance); }
public static XDoc GetServiceXmlVerbose(DekiInstance instance, ServiceBE service, string relation, bool privateDetails) { XDoc serviceXml = GetServiceXml(service, relation); serviceXml.Start("sid").Value(service.SID ?? string.Empty).End(); serviceXml.Start("uri").Value(XUri.TryParse(service.Uri)).End(); serviceXml.Start("type").Value(service.Type.ToString().ToLowerInvariant()).End(); serviceXml.Start("description").Value(service.Description ?? "").End(); serviceXml.Elem("date.modified", service.ServiceLastEdit); serviceXml.Elem("status", service.ServiceEnabled ? "enabled" : "disabled"); serviceXml.Start("local").Value(service.ServiceLocal).Attr("deprecated", true).End(); serviceXml.Elem("init", service.ServiceLocal ? "native" : "remote"); var serviceInfo = instance.RunningServices[service.Id]; if (serviceInfo != null && !string.IsNullOrEmpty(serviceInfo.Namespace)) { serviceXml.Elem("namespace", serviceInfo.Namespace); } if (privateDetails) { serviceXml.Elem("lasterror", service.ServiceLastStatus ?? ""); serviceXml.Start("config"); foreach (string key in service.Config.AllKeys) { serviceXml.Start("value").Attr("key", key).Value(service.Config[key]).End(); } serviceXml.End(); serviceXml.Start("preferences"); foreach (string key in service.Preferences.AllKeys) { serviceXml.Start("value").Attr("key", key).Value(service.Preferences[key]).End(); } serviceXml.End(); } return(serviceXml); }
public static XDoc GetServiceXmlVerbose(DekiInstance instance, ServiceBE service, string relation) { return(GetServiceXmlVerbose(DekiContext.Current.Instance, service, relation, true)); }
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); }
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); }
protected DekiInstance CreateWikiInstance(string wikiId, XDoc instanceConfig) { List<DekiInstance> instances = null; DekiInstance instance; lock(_instances) { instance = GetWikiInstance(wikiId); if(instance == null) { var licenseStoragePlug = _dekiService.Storage; _loggerRepositories[wikiId] = new ContextLoggerRepository("[" + wikiId + "] "); var licenseController = GetLicenseController(wikiId, licenseStoragePlug); _instances[wikiId] = instance = new DekiInstance(_dekiService, wikiId, instanceConfig, licenseController); } // Schedule new instance for shutdown if inactive-instance-timeout enabled. if(InactiveInstanceTimeOut != TimeSpan.MaxValue) { var timer = _timerFactory.New(OnInstanceExpireTimer, wikiId); _instanceExpireTimers[wikiId] = timer; } if(_instances.Count > _maxInstances) { instances = _instances.Values.ToList(); } } // Hit the instance number limit? Look for least recently accessed wiki and shut it down. if(instances != null) { Async.Fork(() => { _log.DebugFormat("looking for excess instances to shut down"); var excessInstances = (from candidate in instances where DateTime.UtcNow - candidate.InstanceLastUpdateTime >= _minInstanceIdletime orderby candidate.InstanceLastUpdateTime select candidate.Id) .Take(instances.Count - _maxInstances); foreach(var shutdownId in excessInstances) { _log.DebugFormat("shutting down instance '{0}'", shutdownId); OutOfContextShutdown(shutdownId); } }); } return instance; }
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); }
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(); } } }
protected DekiInstance CreateWikiInstance(string wikiId, XDoc instanceConfig) { List<KeyValuePair<string, DekiInstance>> instanceList = null; DekiInstance instance = null; int instanceCount = 0; //throw exception if licensing does not allow startup of another wiki instance MindTouch.Deki.Logic.LicenseBL.IsDekiInstanceStartupAllowed(true); lock(_instances) { instance = GetWikiInstance(wikiId); if(instance == null) { _instances[wikiId] = instance = new DekiInstance(_dekiService, wikiId, instanceConfig); instance.InstanceCreationTime = DateTime.UtcNow; } //Schedule new instance for shutdown if inactive-instance-timeout enabled. if(InactiveInstanceTimeOut != TimeSpan.MaxValue) { TaskTimer timer = new TaskTimer(OnInstanceExpireTimer, wikiId); _instanceExpireTimers[wikiId] = timer; } instanceCount = _instances.Count; if(maxInstances != 0 && instanceCount > maxInstances) { instanceList = new List<KeyValuePair<string, DekiInstance>>(_instances); } } //Hit the instance number limit? Look for least recently accessed wiki and shut it down. if(instanceList != null) { instanceList.Sort(delegate(KeyValuePair<string, DekiInstance> left, KeyValuePair<string, DekiInstance> right) { return DateTime.Compare(left.Value.InstanceLastAccessedTime, right.Value.InstanceLastAccessedTime); }); List<KeyValuePair<string, DekiInstance>> instancesToExamine = instanceList.GetRange(0, instanceList.Count - (int)maxInstances); if(instancesToExamine.Count > 0) { Async.Fork(delegate() { foreach(KeyValuePair<string, DekiInstance> instancePair in instancesToExamine) { if((DateTime.UtcNow - instancePair.Value.InstanceLastAccessedTime).TotalSeconds >= MIN_SECS_FROM_ACCESS_TO_SHUTDOWN) { ShutdownInstance(instancePair.Key); } } }, null); } } return instance; }
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); }
public static XDoc GetServiceXmlVerbose(DekiInstance instance, ServiceBE service, string relation) { return GetServiceXmlVerbose(DekiContext.Current.Instance, service, relation, true); }
protected override void ShutdownInstance(string wikiid, DekiInstance instance) { //On instance shutdown, remove host to wikiId association. string hosts = instance.Config["hosts"].AsText; if (!string.IsNullOrEmpty(hosts)) { lock (_hostsToWikiIds) { foreach (string host in hosts.Split(',')) { _hostsToWikiIds.Remove(host); } } } base.ShutdownInstance(wikiid, instance); }
public static XDoc GetServiceXmlVerbose(DekiInstance instance, ServiceBE service, string relation, bool privateDetails) { XDoc serviceXml = GetServiceXml(service, relation); serviceXml.Start("sid").Value(service.SID ?? string.Empty).End(); serviceXml.Start("uri").Value(XUri.TryParse(service.Uri)).End(); serviceXml.Start("type").Value(service.Type.ToString().ToLowerInvariant()).End(); serviceXml.Start("description").Value(service.Description ?? "").End(); serviceXml.Elem("date.modified", service.ServiceLastEdit); serviceXml.Elem("status", service.ServiceEnabled ? "enabled" : "disabled"); serviceXml.Start("local").Value(service.ServiceLocal).Attr("deprecated", true).End(); serviceXml.Elem("init", service.ServiceLocal ? "native" : "remote"); var serviceInfo = instance.RunningServices[service.Id]; if(serviceInfo != null && !string.IsNullOrEmpty(serviceInfo.Namespace)) { serviceXml.Elem("namespace", serviceInfo.Namespace); } if(privateDetails) { serviceXml.Elem("lasterror", service.ServiceLastStatus ?? ""); serviceXml.Start("config"); foreach(string key in service.Config.AllKeys) serviceXml.Start("value").Attr("key", key).Value(service.Config[key]).End(); serviceXml.End(); serviceXml.Start("preferences"); foreach(string key in service.Preferences.AllKeys) serviceXml.Start("value").Attr("key", key).Value(service.Preferences[key]).End(); serviceXml.End(); } return serviceXml; }
protected override void ShutdownInstance(string wikiid, DekiInstance instance) { lock(instance) { // On instance shutdown, remove host to wikiId association. lock(_hostsToWikiIds) { foreach(var hostDoc in instance.Config["host"]) { var host = hostDoc.AsText; _hostsToWikiIds.Remove(host); } } base.ShutdownInstance(wikiid, instance); } }
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); } } }
//--- Constructor --- public SiteBL() { var dekiContext = DekiContext.Current; _dekiInstance = dekiContext.Instance; _user = dekiContext.User; }