public Yield ExpandFolder(DreamContext context, DreamMessage request, Result <DreamMessage> response) { if (_directoryInfo == null) { throw new DreamBadRequestException("folder is misconfigured"); } // Extract the folder to expand string foldername = context.GetParam("foldername", String.Empty); foldername = XUri.Decode(foldername); if (foldername.Contains("..")) { response.Return(DreamMessage.Forbidden("Relative paths are not allowed")); yield break; } // Extract the search pattern string pattern = context.GetParam("pattern", null); DirectoryInfo currentDirectory = new DirectoryInfo(_directoryInfo.FullName + Path.DirectorySeparatorChar + foldername); XDoc result = new XDoc("results"); // If specified, retrieve all the directories under the current directory bool topDirectoryOnly = context.GetParam("topDirectoryOnly", false); if (!topDirectoryOnly) { foreach (DirectoryInfo directory in currentDirectory.GetDirectories()) { string encodedDirectoryName = XUri.DoubleEncodeSegment((foldername + Path.DirectorySeparatorChar + directory.Name).Replace("+", "%2b")); XUri dynamicExpandUri = DreamContext.Current.AsPublicUri(Self.At("expand", encodedDirectoryName)).With("dream.out.format", "json"); if (null != pattern) { dynamicExpandUri = dynamicExpandUri.With("pattern", pattern); } result.Start("result").Elem("name", directory.Name).Elem("dynamicexpanduri", dynamicExpandUri.ToString()).End(); } } // Retrieve files according to the search pattern FileInfo[] files; if (null != pattern) { files = currentDirectory.GetFiles(pattern, SearchOption.TopDirectoryOnly); } else { files = currentDirectory.GetFiles(); } foreach (FileInfo file in files) { string encodedFileName = XUri.DoubleEncodeSegment((foldername + Path.DirectorySeparatorChar + file.Name).Replace("+", "%2b")); XUri href = DreamContext.Current.AsPublicUri(Self.At("doc", encodedFileName)); result.Start("result").Elem("name", file.Name).Elem("href", href.ToString()).Elem("labelstyle", "iconitext-16 ext-" + file.Extension.TrimStart('.').ToLowerInvariant()).End(); } response.Return(DreamMessage.Ok(result)); yield break; }
public Yield GetFile(DreamContext context, DreamMessage request, Result <DreamMessage> response) { if (_directoryInfo == null) { throw new DreamBadRequestException("folder is misconfigured"); } // Extract the filename string filename = context.GetParam("filename", String.Empty); filename = XUri.Decode(filename); if (filename.Contains("..")) { response.Return(DreamMessage.Forbidden("Relative paths are not allowed")); yield break; } FileInfo currentFile = new FileInfo(_directoryInfo.FullName + Path.DirectorySeparatorChar + filename); // Retrieve the file DreamMessage message = GetFile(currentFile.FullName); message.Headers.ContentDisposition = new ContentDisposition(true, currentFile.CreationTimeUtc, currentFile.LastWriteTimeUtc, null, currentFile.Name, currentFile.Length); response.Return(message); yield break; }
public Yield GetSubscription(DreamContext context, DreamMessage request, Result <DreamMessage> response) { var wikiId = GetWikiIdFromRequest(request); Result <PageSubscriptionUser> userResult; yield return(userResult = Coroutine.Invoke(GetRequestUser, request, new Result <PageSubscriptionUser>()).Catch()); if (userResult.HasException) { ReturnUserError(userResult.Exception, response); yield break; } var userInfo = userResult.Value; var currentPageId = context.GetParam <uint>("pageid"); XDoc pageDoc = null; yield return(_deki .At("pages", currentPageId.ToString()) .WithHeaders(request.Headers) .Get(new Result <XDoc>()) .Set(x => pageDoc = x)); var perms = (pageDoc["security/permissions.effective/operations"].AsText ?? "").Split(','); var canSubscribe = false; foreach (var perm in perms) { if ("SUBSCRIBE".EqualsInvariantIgnoreCase(perm.Trim())) { canSubscribe = true; } } if (!canSubscribe) { response.Return(DreamMessage.Forbidden(string.Format("User is not authorized to subscribe to page {0}.", currentPageId))); yield break; } var pages = GetPageList(currentPageId, pageDoc["page.parent"]); var dataSession = GetDataSession(wikiId); var subscriptions = dataSession.GetSubscriptionsForUser(userInfo.Id, pages) .Where(x => x.PageId == currentPageId || x.IncludeChildPages); var subscriptionDoc = new XDoc("subscriptions"); foreach (var tuple in subscriptions) { subscriptionDoc.Start("subscription.page").Attr("id", tuple.PageId).Attr("depth", tuple.IncludeChildPages ? "infinity" : "0").End(); } response.Return(DreamMessage.Ok(subscriptionDoc)); }
public Yield SubscribeUserToChange(DreamContext context, DreamMessage request, Result <DreamMessage> response) { Result <PageSubscriptionUser> userResult; yield return(userResult = Coroutine.Invoke(GetRequestUser, request, new Result <PageSubscriptionUser>()).Catch()); if (userResult.HasException) { ReturnUserError(userResult.Exception, response); yield break; } var userInfo = userResult.Value; var pageId = context.GetParam <uint>("pageid"); var userId = context.GetParam <uint>("userid"); if (userId != userInfo.Id && !userInfo.IsAdmin) { response.Return(DreamMessage.Forbidden("Administrator access is required.")); yield break; } var wikiId = GetWikiIdFromRequest(request); DreamMessage userMsg = null; yield return(_deki.At("users", userId.ToString()).Get(new Result <DreamMessage>()).Set(x => userMsg = x)); if (!userMsg.IsSuccessful) { response.Return(userMsg); } DreamMessage pageAuth = null; yield return(_deki .At("pages", pageId.ToString(), "allowed") .With("permissions", "read,subscribe") .WithHeaders(request.Headers) .Post(new XDoc("users").Start("user").Attr("id", userInfo.Id).End(), new Result <DreamMessage>()) .Set(x => pageAuth = x)); if (!pageAuth.IsSuccessful || pageAuth.ToDocument()["user/@id"].AsText != userInfo.Id.ToString()) { throw new DreamForbiddenException("User not permitted to subscribe to page"); } GetDataSession(wikiId).Subscribe(userId, pageId, context.GetParam("depth", "0") == "0" ? false : true); response.Return(DreamMessage.Ok()); yield break; }
internal Yield PublishEvent(DreamContext context, DreamMessage request, Result <DreamMessage> response) { DispatcherEvent ev; try { ev = new DispatcherEvent(request); _log.DebugFormat("{0} received event '{1}'", this.Self.Uri, ev.Id); if (ev.Channel.Scheme == "pubsub") { response.Return(DreamMessage.Forbidden("events published into this service cannot be of scheme 'pubsub'")); yield break; } _dispatcher.Dispatch(ev); response.Return(DreamMessage.Ok(ev.GetEventEnvelope())); } catch (Exception e) { response.Return(DreamMessage.BadRequest(e.Message)); } yield break; }
protected Yield ReplaceSubscribeSet(DreamContext context, DreamMessage request, Result <DreamMessage> response) { try { string setId = context.GetParam("id"); _log.DebugFormat("Updating set {0}", setId); if (!string.IsNullOrEmpty(request.Headers.DreamEventId)) { _log.DebugFormat("'{0}' update is event: {1} - {2}", setId, request.Headers.DreamEventChannel, request.Headers.DreamEventId); } XDoc subscriptionDocument = request.ToDocument(); PubSubSubscriptionSet set = _dispatcher.ReplaceSet(setId, subscriptionDocument); if (set != null) { long?version = subscriptionDocument["@version"].AsLong; if (version.HasValue && version.Value <= set.Version) { _log.DebugFormat("set not modified: {0}", setId); response.Return(DreamMessage.NotModified()); } else { if (version.HasValue) { _log.DebugFormat("Updating set '{0}' from version {1} to {2}", setId, set.Version, version); } else { _log.DebugFormat("Updating set '{0}'", setId); } response.Return(DreamMessage.Ok()); } } else { _log.DebugFormat("no such set: {0}", setId); response.Return(DreamMessage.NotFound("There is no subscription set at this location")); } } catch (ArgumentException e) { response.Return(DreamMessage.Forbidden(e.Message)); } yield break; }
private void HandleLdapException(LdapException x) { switch (x.ResultCode) { case LdapException.Ldap_TIMEOUT: throw new TimeoutException("Ldap lookup timed out", x); case LdapException.OPERATIONS_ERROR: case LdapException.INVALID_DN_SYNTAX: if (x.ResultCode == 1 && x.LdapErrorMessage.Contains("DSID-0C090627")) { throw new DreamAbortException(DreamMessage.Forbidden(string.Format("Account '{0}' is disabled", this._username))); } throw new ArgumentException(string.Format("The search base '{0}' may have invalid format (Example: 'DC=sales,DC=acme,DC=com') or the account used for binding may be disabled. Error returned from LDAP: {1}", _config.LdapSearchBase, x.LdapErrorMessage), x); default: throw x; } }
public Yield PostExtensionFunction(DreamContext context, DreamMessage request, Result <DreamMessage> response) { var name = context.GetParam("function"); XUri uri = Self.At(name); // check if deki server is permitted to invoke this function if (this is IDreamServiceLicense) { string deki; if (context.ServiceLicense.TryGetValue("deki", out deki) && !deki.EqualsInvariant(request.Headers[DEKI_HEADER] ?? string.Empty)) { throw new DreamAbortException(DreamMessage.Forbidden("deki server is not licensed for this service")); } } // check if any functions were found DekiScriptInvocationTargetDescriptor descriptor; if (!_functions.TryGetValue(uri, out descriptor)) { response.Return(DreamMessage.NotFound(string.Format("function {0} not found", context.GetParam("function")))); yield break; } // check if invoker has access to function if ((descriptor.Access != DreamAccess.Public) && (descriptor.Access > DetermineAccess(context, request))) { response.Return(DreamMessage.Forbidden("insufficient access privileges")); yield break; } // check if request has a requested culture context.Culture = HttpUtil.GetCultureInfoFromHeader(request.Headers.AcceptLanguage, context.Culture); // check for implicit arguments context.SetState(GetImplicitEnvironment(request, _publicDigitalSignature)); // create custom environment DekiScriptEnv env = CreateEnvironment(); // create custom target for custom environment var target = descriptor.Target as DekiScriptExpressionInvocationTarget; if (target != null) { // TODO (steveb): re-initializing the invocation target works for the first call, but not if the function calls another function in the same extension! target = new DekiScriptExpressionInvocationTarget(target.Access, target.Parameters, target.Expression, env); } // invoke target DekiScriptLiteral eval; if (target != null) { eval = target.Invoke(ScriptRuntime, DekiScriptLiteral.FromXml(request.ToDocument())); } else { eval = descriptor.Target.Invoke(ScriptRuntime, DekiScriptLiteral.FromXml(request.ToDocument())); } // invoke function response.Return(DreamMessage.Ok(new DekiScriptList().Add(eval).ToXml())); yield break; }
public static DekiScriptMap GetImplicitEnvironment(DreamMessage message, DSACryptoServiceProvider publicDigitalSignature) { DekiScriptMap env = new DekiScriptMap(); // retrieve implicit arguments string[] headers = message.Headers.GetValues(IMPLICIT_ENVIRONMENT_HEADER); if (!ArrayUtil.IsNullOrEmpty(headers)) { env.AddAt("__implicit", new DekiScriptList(new ArrayList(headers))); foreach (string implicitArg in headers) { foreach (KeyValuePair <string, string> arg in HttpUtil.ParseNameValuePairs(implicitArg)) { env.AddNativeValueAt(arg.Key, arg.Value); } } } if (publicDigitalSignature != null) { bool valid = false; try { Dictionary <string, string> values = HttpUtil.ParseNameValuePairs(message.Headers[IMPLICIT_SIGNATURE_HEADER]); // verify date DateTime date = DateTime.Parse(values["date"]).ToUniversalTime(); double delta = DateTime.UtcNow.Subtract(date).TotalSeconds; if ((delta < -60) || (delta > 60)) { throw new DreamAbortException(DreamMessage.Forbidden("date in message signature is too far apart from server date")); } // verify message MemoryStream data = new MemoryStream(); byte[] bytes = null; // get message bytes bytes = message.AsBytes(); data.Write(bytes, 0, bytes.Length); // retrieve headers to verify 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 bytes = Encoding.UTF8.GetBytes(values["date"]); data.Write(bytes, 0, bytes.Length); // verify signature byte[] signature = Convert.FromBase64String(values["dsig"]); valid = publicDigitalSignature.VerifyData(data.GetBuffer(), signature); } catch (Exception e) { if (e is DreamAbortException) { throw; } } if (!valid) { throw new DreamAbortException(DreamMessage.Forbidden("invalid or missing digital signature")); } } return(env); }
private static DreamMessage Map(MindTouchForbiddenException e, DekiResources resources) { return(DreamMessage.Forbidden(resources.Localize(e.Resource))); }
private static DreamMessage Map(TooManyResultsException e, DekiResources resources) { return(DreamMessage.Forbidden(resources.Localize(DekiResources.SITE_TOO_BIG_TO_GENERATE_SITEMAP()))); }