Exemple #1
0
        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;
        }
Exemple #2
0
        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;
        }
Exemple #5
0
        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;
        }
Exemple #6
0
 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())));
 }