示例#1
0
        string GetWidgetContent(DreamContext context, string widgetType, string id, string mode, XDoc data)
        {
            if (mode.ToLowerInvariant() != "edit")
            {
                Plug plug        = Plug.New(Env.RootUri.At("wiki-data", widgetType, "render"));
                XDoc widgetXhtml = plug.Post(data).Document;
                if (widgetXhtml == null || widgetXhtml.IsEmpty)
                {
                    LogUtils.LogWarning(_log, string.Format("GetWidgetContent: null/empty document for /wiki-data/{0}/render/ (data)", widgetType), data);
                    throw new DreamAbortException(DreamMessage.BadRequest("no widget data"));
                }
                return(widgetXhtml.ToString());
            }
            else
            {
                Plug normalizePlug = Plug.New(Env.RootUri.At("wiki-data", widgetType, "normalize"));
                data = normalizePlug.Post(data).Document;

                Plug   renderPlug = Plug.New(Env.RootUri.At("wiki-data", widgetType, "render"));
                XDoc   renderHtml = renderPlug.Post(data).Document;
                string jsonData   = data.ToJson();
                return(new XDoc("div")
                       .Attr("class", "widget").Attr("widgetid", id).Attr("widgettype", widgetType).Attr("style", "display:none")
                       .Start("div")
                       .Attr("class", "data")
                       .Value(string.Format("Widget.registerWidget({0},{1})", id, jsonData))
                       .End()
                       .Start("div")
                       .Attr("class", "view")
                       .Add(renderHtml)
                       .End()
                       .ToString());
            }
        }
示例#2
0
        public void Returns_callback_gets_request_data()
        {
            var doc     = new XDoc("doc").Elem("foo", StringUtil.CreateAlphaNumericKey(6));
            var success = new XDoc("yay");
            var uri     = new XUri("http://mock/foo/").With("foo", "baz");

            MockPlug.Setup(new XUri("http://mock/foo")).Returns(invocation => {
                if (invocation.Verb != "POST")
                {
                    return(DreamMessage.BadRequest("wrong verb: " + invocation.Verb));
                }
                if (invocation.Uri != uri)
                {
                    return(DreamMessage.BadRequest("wrong uri: " + invocation.Uri));
                }
                if (invocation.Request.Headers["header"] != "value")
                {
                    return(DreamMessage.BadRequest("wrong header value"));
                }
                if (invocation.Request.ToDocument() != doc)
                {
                    return(DreamMessage.BadRequest("wrong body"));
                }
                return(DreamMessage.Ok(success));
            });
            var msg = Plug.New(uri).WithHeader("header", "value").Post(doc, new Result <DreamMessage>()).Wait();

            Assert.IsTrue(msg.IsSuccessful, msg.ToDocument().ToPrettyString());
            Assert.AreEqual(success, msg.ToDocument());
        }
示例#3
0
        public DreamMessage GetPageHandler(DreamContext context, DreamMessage message)
        {
            page cur = null;//deki.GetCur(true); Max: commented out to allow compilation

            if (cur == null)
            {
                return(DreamMessage.BadRequest("can't load page"));
            }
            string mode = context.Uri.GetParam("mode", "raw").ToLowerInvariant();

            switch (mode)
            {
            case "raw":
                return(DreamMessage.Ok(MimeType.HTML, cur.Text));

            case "xml":
                string xml    = string.Format(DekiWikiService.XHTML_LOOSE, cur.Text);
                XDoc   result = XDoc.FromXml(xml);
                return(DreamMessage.Ok(MimeType.XHTML, result.ToXHtml()));

            case "export":
            case "edit":
            case "print":
            case "view":
                return(DreamMessage.Ok(MimeType.HTML, /*deki.Render(cur.Text, mode) Max:Removed to allow compilation*/ ""));
            }
            return(DreamMessage.NotImplemented(string.Format("'mode={0}' is not supported")));
        }
示例#4
0
        private DreamMessage GetFile(DreamContext context)
        {
            DreamMessage message;

            string[] parts    = context.GetSuffixes(UriPathFormat.Decoded);
            string   filename = _resourcesPath;

            foreach (string part in parts)
            {
                if (part.EqualsInvariant(".."))
                {
                    _log.WarnFormat("attempted to access file outside of target folder: {0}", string.Join("/", parts));
                    throw new DreamBadRequestException("paths cannot contain '..'");
                }
                filename = Path.Combine(filename, part);
            }
            try {
                message = DreamMessage.FromFile(filename, context.Verb == Verb.HEAD);
            } catch (FileNotFoundException e) {
                message = DreamMessage.NotFound("resource not found: " + String.Join("/", context.GetSuffixes(UriPathFormat.Decoded)));
            } catch (Exception e) {
                message = DreamMessage.BadRequest("invalid path");
            }
            return(message);
        }
示例#5
0
 internal DreamMessage Call(string verb, XUri uri, XDoc request)
 {
     _verb    = verb;
     _uri     = uri;
     _request = request;
     return(DreamMessage.BadRequest("unexpected call"));
 }
示例#6
0
        public Yield GetFileHandler(DreamContext context, DreamMessage request, Result <DreamMessage> response)
        {
            string suffixPath = string.Join("" + Path.DirectorySeparatorChar, context.GetSuffixes(UriPathFormat.Decoded));
            string filename   = Path.Combine(_path, suffixPath);

            if (Directory.Exists(filename))
            {
                XDoc   ret     = new XDoc("files");
                string pattern = context.GetParam("pattern", "");
                AddDirectories(new DirectoryInfo(filename), pattern, ret);
                AddFiles(new DirectoryInfo(filename), pattern, ret);
                response.Return(DreamMessage.Ok(ret));
                yield break;
            }

            DreamMessage message;

            try {
                message = DreamMessage.FromFile(filename, StringUtil.EqualsInvariant(context.Verb, "HEAD"));
            } catch (FileNotFoundException) {
                message = DreamMessage.NotFound("file not found");
            } catch (Exception) {
                message = DreamMessage.BadRequest("invalid path");
            }

            // open file and stream it to the requester
            response.Return(message);
        }
示例#7
0
        public Yield PostImport(DreamContext context, DreamMessage request, Result <DreamMessage> response)
        {
            string       uri            = context.GetParam("uri", null);
            string       reltopath      = context.GetParam("reltopatch", "/");
            DreamMessage packageMessage = request;

            if (!string.IsNullOrEmpty(uri))
            {
                Result <DreamMessage> packageResult;
                yield return(packageResult = Plug.New(uri).InvokeEx("GET", DreamMessage.Ok(), new Result <DreamMessage>()));

                packageMessage = packageResult.Value;
                if (!packageMessage.IsSuccessful)
                {
                    throw new DreamAbortException(DreamMessage.BadRequest(string.Format("Unable to retrieve package from Uri '{0}': {1}", uri, packageMessage.Status)));
                }
            }
            string        tempFile   = Path.GetTempFileName();
            Stream        tempStream = File.Create(tempFile);
            Result <long> copyResult;

            // TODO (steveb): use WithCleanup() to dispose of resources in case of failure
            yield return(copyResult = packageMessage.ToStream().CopyTo(tempStream, packageMessage.ContentLength, new Result <long>()).Catch());

            tempStream.Dispose();
            if (copyResult.HasException)
            {
                response.Throw(copyResult.Exception);
                yield break;
            }
            ArchivePackageReader   archivePackageReader = new ArchivePackageReader(File.OpenRead(tempFile));
            Result <ImportManager> importerResult;
            Plug authorizedDekiApi = _dekiApi.WithHeaders(request.Headers);

            // TODO (steveb): use WithCleanup() to dispose of resources in case of failure
            yield return(importerResult = ImportManager.CreateAsync(authorizedDekiApi, reltopath, archivePackageReader, new Result <ImportManager>()).Catch());

            if (importerResult.HasException)
            {
                archivePackageReader.Dispose();
                File.Delete(tempFile);
                response.Throw(importerResult.Exception);
                yield break;
            }
            ImportManager importManager = importerResult.Value;
            Result        importResult;

            yield return(importResult = importManager.ImportAsync(new Result()).Catch());

            archivePackageReader.Dispose();
            File.Delete(tempFile);
            if (importResult.HasException)
            {
                response.Throw(importResult.Exception);
                yield break;
            }
            response.Return(DreamMessage.Ok());
            yield break;
        }
示例#8
0
 public void Get_via_internal_routing_follows_301_but_expects_query_to_be_in_location()
 {
     using (var hostInfo = DreamTestHelper.CreateRandomPortHost()) {
         var mock           = MockService.CreateMockService(hostInfo);
         var redirectCalled = 0;
         var targetCalled   = 0;
         mock.Service.CatchAllCallback = delegate(DreamContext context, DreamMessage request, Result <DreamMessage> response) {
             var msg     = "nothing here";
             var q       = context.Uri.GetParam("q");
             var forward = context.Uri.GetParam("forward");
             if (context.Uri.LastSegment == "redirect")
             {
                 _log.Debug("called redirect");
                 var redirect = context.Service.Self.Uri.At("target").AsPublicUri();
                 if (forward == "true")
                 {
                     redirect = redirect.With("q", q);
                 }
                 redirectCalled++;
                 var headers = new DreamHeaders();
                 headers.Add(DreamHeaders.LOCATION, redirect.ToString());
                 response.Return(new DreamMessage(DreamStatus.MovedPermanently, headers));
                 return;
             }
             if (context.Uri.LastSegment == "target")
             {
                 _log.Debug("called target");
                 if (q == "x")
                 {
                     _log.Debug("target request had query");
                     targetCalled++;
                     response.Return(DreamMessage.Ok());
                     return;
                 }
                 response.Return(DreamMessage.BadRequest("missing query param"));
                 return;
             }
             _log.DebugFormat("called uri: {0} => {1}", context.Uri, msg);
             response.Return(DreamMessage.NotFound(msg));
         };
         var uri = mock.AtLocalMachine.At("redirect");
         _log.DebugFormat("calling redirect service at {0}", uri);
         var r = Plug.New(uri).With("q", "x").Get(new Result <DreamMessage>()).Wait();
         Assert.AreEqual(DreamStatus.BadRequest, r.Status);
         Assert.AreEqual(1, redirectCalled, "redirect without forward called incorrectly");
         Assert.AreEqual(0, targetCalled, "target without forward called incorrectly");
         redirectCalled = 0;
         targetCalled   = 0;
         r = Plug.New(uri).With("q", "x").With("forward", "true").Get(new Result <DreamMessage>()).Wait();
         Assert.IsTrue(r.IsSuccessful, r.HasDocument ? r.ToDocument()["message"].AsText : "request failed: " + r.Status);
         Assert.AreEqual(1, redirectCalled, "redirect with forward called incorrectly");
         Assert.AreEqual(1, targetCalled, "target with forward called incorrectly");
     }
 }
示例#9
0
        public void Plug_extension_to_return_document_sets_exception_on_non_OK_response()
        {
            var autoMockPlug = MockPlug.Register(new XUri("mock://mock"));

            autoMockPlug.Expect().Verb("GET").Response(DreamMessage.BadRequest("bad puppy"));
            var r = Plug.New("mock://mock").Get(new Result <XDoc>()).Block();

            Assert.IsTrue(r.HasException);
            Assert.AreEqual(typeof(DreamResponseException), r.Exception.GetType());
            Assert.AreEqual(DreamStatus.BadRequest, ((DreamResponseException)r.Exception).Response.Status);
        }
        protected page Authorize(DreamContext context, user user, DekiAccessLevel access, string pageIdName)
        {
            page result;
            long id = context.Uri.GetParam <long>(pageIdName, 0);

            if (id == 0)
            {
                string title = context.Uri.GetParam("title", "");
                if (string.IsNullOrEmpty(title))
                {
                    throw new DreamAbortException(DreamMessage.NotFound(""));
                }

                result = page.GetCurByTitle(title);
            }
            else
            {
                result = page.GetCurByID((ulong)id);
            }

            // check that page was found
            if ((result == null) || (result.ID <= 0))
            {
                throw new DreamAbortException(DreamMessage.NotFound(""));
            }

            // check if action is allowed
            string action;

            switch (access)
            {
            case DekiAccessLevel.Read:
                action = DekiWikiConstants.ACTION_READ;
                break;

            case DekiAccessLevel.Write:
                action = DekiWikiConstants.ACTION_EDIT;
                break;

            case DekiAccessLevel.Destroy:
                action = DekiWikiConstants.ACTION_DELETE;
                break;

            default:
                throw new DreamAbortException(DreamMessage.BadRequest(string.Format("unknown action {0}", access)));
            }
            if (!result.userCan(action, user))
            {
                throw new DreamAbortException(DreamMessage.AccessDenied(DekiWikiService.AUTHREALM, ""));
            }

            // return page
            return(result);
        }
示例#11
0
        private DreamMessage GetFile(string filename)
        {
            DreamMessage message;

            try {
                message = DreamMessage.FromFile(filename);
            } catch (FileNotFoundException e) {
                message = DreamMessage.NotFound("file not found");
            } catch (Exception e) {
                message = DreamMessage.BadRequest("invalid path");
            }
            return(message);
        }
示例#12
0
        internal Yield ConfigureSmtp(DreamContext context, DreamMessage request, Result <DreamMessage> response)
        {
            var configuration = context.GetParam("configuration");
            var settingsDoc   = request.ToDocument();

            _log.DebugFormat("configuring settings for configuration '{0}'", configuration);
            var host   = settingsDoc["smtp-host"].AsText;
            var apikey = settingsDoc["apikey"].AsText;

            if (string.IsNullOrEmpty(host) && string.IsNullOrEmpty(apikey))
            {
                response.Return(DreamMessage.BadRequest("must specify either new smtp config with a host or specify an apikey"));
                yield break;
            }
            SmtpSettings settings;

            if (string.IsNullOrEmpty(host))
            {
                settings = new SmtpSettings()
                {
                    Host         = _defaultSettings.Host,
                    Apikey       = apikey,
                    AuthPassword = _defaultSettings.AuthPassword,
                    AuthUser     = _defaultSettings.AuthUser,
                    EnableSsl    = _defaultSettings.EnableSsl,
                    Port         = _defaultSettings.Port,
                };
            }
            else
            {
                _log.DebugFormat("Smtp Host: {0}", host);
                settings = new SmtpSettings {
                    Host         = host,
                    AuthUser     = settingsDoc["smtp-auth-user"].AsText,
                    AuthPassword = settingsDoc["smtp-auth-password"].AsText,
                    Apikey       = apikey,

                    // Note (arnec): ssl requires mono 2.0 and likely root certificate import via 'mozroots --import --ask-remove --machine'
                    EnableSsl = settingsDoc["use-ssl"].AsBool ?? false
                };
                if (settingsDoc["smtp-port"].AsInt.HasValue)
                {
                    settings.Port = settingsDoc["smtp-port"].AsInt.Value;
                }
            }
            lock (_smtpSettings) {
                _smtpSettings[configuration] = settings;
            }
            response.Return(DreamMessage.Ok());
            yield break;
        }
示例#13
0
        public void Returns_callback_gets_response_headers_if_added_after_callback()
        {
            var success = new XDoc("yay");

            MockPlug.Setup(new XUri("http://mock/foo"))
            .Returns(invocation => {
                return(invocation.ResponseHeaders["foo"] != "bar" ? DreamMessage.BadRequest("wrong response header") : DreamMessage.Ok(success));
            })
            .WithResponseHeader("foo", "bar");
            var msg = Plug.New("http://mock/foo/").Get(new Result <DreamMessage>()).Wait();

            Assert.IsTrue(msg.IsSuccessful, msg.ToDocument().ToPrettyString());
            Assert.AreEqual(success, msg.ToDocument());
        }
示例#14
0
        public DreamMessage GetContentHandler(DreamContext context, DreamMessage message)
        {
            user        user     = Authenticate(context, message, DekiUserLevel.User);
            page        page     = Authorize(context, user, DekiAccessLevel.Read, "pageid");
            DekiContext deki     = new DekiContext(message, this.DekiConfig);
            bool        nofollow = (context.Uri.GetParam("nofollow", 0, null) != null);
            string      contents = page.getContent(nofollow);
            string      xml      = string.Format(DekiWikiService.XHTML_LOOSE, contents);
            XDoc        doc      = XDoc.FromXml(xml);

            if (doc == null)
            {
                LogUtils.LogWarning(_log, "GetContentHandler: null document page content", page.PrefixedName, contents);
                throw new DreamAbortException(DreamMessage.BadRequest("null document"));
            }
            XDoc   result = new XDoc("list");
            string type   = context.Uri.GetParam("type", 0, null);
            string id     = context.Uri.GetParam("id", 0, null);

            if (id != null)
            {
                XDoc widget = doc[string.Format("//default:span[@widgetid={0}]", id)];
                if (widget.IsEmpty)
                {
                    LogUtils.LogWarning(_log, "GetContentHandler: widget not found for ID", id);
                    return(DreamMessage.NotFound(""));
                }
                LogUtils.LogTrace(_log, "GetContentHandler: widget by id (id, xspan)", id, widget);
                result.Add(ConvertFromXSpan(widget));
            }
            else if (type != null)
            {
                foreach (XDoc widget in doc[string.Format("//default:span[@widgettype='{0}']", type)])
                {
                    result.Add(ConvertFromXSpan(widget));
                }
                LogUtils.LogTrace(_log, "GetContentHandler: widget by type (type, #)", type, result.Count);
            }
            else
            {
                foreach (XDoc widget in doc["//default:span[@class='widget']"])
                {
                    result.Add(ConvertFromXSpan(widget));
                }
                LogUtils.LogTrace(_log, "GetContentHandler: all widgets (#)", type, result.Count);
            }
            return(DreamMessage.Ok(result));
        }
示例#15
0
        public DreamMessage PostEditHandler(DreamContext context, DreamMessage message)
        {
            XDoc xhtml = message.ContentType.Contains("/html")
                ? XDoc.FromHtml(new StreamReader(message.Stream, message.ContentEncoding))
                : message.Document;

            if (xhtml == null || xhtml.IsEmpty)
            {
                LogUtils.LogWarning(_log, "PostEditHandler: null/empty input document");
                throw new DreamAbortException(DreamMessage.BadRequest("null/empty input document"));
            }
            string baseHref = context.Uri.GetParam("baseHref", 0, "http://mos/");
            string pageID   = context.Uri.GetParam("context", "");

            XHTMLConverter.Convert(xhtml, baseHref, pageID, true);
            ConvertAllWidgets("PostEditHandler", xhtml, "edit", pageID);
            return(DreamMessage.Ok(MimeType.XHTML, xhtml.ToXHtml()));
        }
示例#16
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;
        }
示例#17
0
        public DreamMessage GetNavHandler(DreamContext context, DreamMessage message)
        {
            DekiContext deki = null; // new DekiContext(message, this.DekiConfig);
            page        cur  = null; // deki.GetCur(true); Max: Commented out to allow compilation

            if (cur == null)
            {
                return(DreamMessage.BadRequest("can't load page"));
            }
            int  maxLevel                = context.Uri.GetParam <int>("max-level", 1);
            bool filterRedirects         = context.Uri.GetParam <bool>("redirects", true);
            ICollection <string> columns = context.Uri.GetParams("column");
            string filter                = filterRedirects ? " AND page_is_redirect=0" : "";

            XDoc ret = new XDoc("nav");

            AddCur(deki, cur, ret, columns, filter, maxLevel);
            return(DreamMessage.Ok(ret));
        }
示例#18
0
        public DreamMessage PostPasteHandler(DreamContext context, DreamMessage message)
        {
            XDoc xhtml = message.ContentType.Contains("/html")
                ? XDoc.FromHtml(new StreamReader(message.Stream, message.ContentEncoding))
                : message.Document;

            if (xhtml == null || xhtml.IsEmpty)
            {
                LogUtils.LogWarning(_log, "PostEditHandler: null/empty input document");
                throw new DreamAbortException(DreamMessage.BadRequest("null/empty input document"));
            }
            string baseHref = context.Uri.GetParam("baseHref", 0, "http://mos/");
            string pageID   = context.Uri.GetParam("context", "");

            XHTMLConverter.Convert(xhtml, baseHref, pageID, true);

            MindTouch.Dream.Plug plug = MindTouch.Dream.Plug.New(Env.RootUri);
            foreach (XDoc nodeWithClass in xhtml["//*[@class='vcard']"])
            {
                XDoc replacement = plug.At("wiki-data", "dekibizcard", "hcardtoedit").Post(nodeWithClass).Document;
                if (replacement != null && !replacement.IsEmpty)
                {
                    nodeWithClass.Replace(replacement);
                }
            }

            bool insertMagic = context.Uri.GetParam <bool>("insertMagic", false);

            if (insertMagic)
            {
                Plug widgetStorage = Plug.New(Env.RootUri).At("mount", "deki-widgets");
                Plug widgetToEdit  = Plug.New(Env.RootUri.At("wiki-data", "dekibizcard", "edit"));
                XDoc files         = widgetStorage.With("pattern", "*.vcf").Get().Document;
                foreach (XDoc fileName in files["file/name"])
                {
                    XDoc vcard       = XDoc.FromVersit(widgetStorage.At(fileName.Contents).Get().Text, "dekibizcard");
                    XDoc widgetXhtml = widgetToEdit.Post(vcard).Document;
                    xhtml["//body"].Add(widgetXhtml);
                }
            }
            return(DreamMessage.Ok(MimeType.HTML, xhtml.ToString()));
        }
示例#19
0
        public Yield DeleteFile(DreamContext context, DreamMessage request, Result <DreamMessage> response)
        {
            var path   = GetPath(context);
            var result = DreamMessage.Ok();

            if (Directory.Exists(path))
            {
                // folder delete
                try {
                    Directory.Delete(path, true);
                } catch { }
            }
            else if (File.Exists(path))
            {
                // delete target file
                try {
                    _expirationEntries.Delete(path);
                    try {
                        File.Delete(path);
                    } catch { }
                    WriteMeta(path, null, null);
                } catch (FileNotFoundException) {
                } catch (DirectoryNotFoundException) {
                } catch (PathTooLongException) {
                    result = DreamMessage.BadRequest("path too long");
                } catch (NotSupportedException) {
                    result = DreamMessage.BadRequest("not supported");
                }

                // try to clean up empty directory
                string folderpath = Path.GetDirectoryName(path);
                if (Directory.Exists(folderpath) && (Directory.GetFileSystemEntries(folderpath).Length == 0))
                {
                    try {
                        Directory.Delete(folderpath);
                    } catch { }
                }
            }
            response.Return(result);
            yield break;
        }
示例#20
0
        public Yield PutFile(DreamContext context, DreamMessage request, Result <DreamMessage> response)
        {
            string   filepath   = GetPath(context);
            string   folderpath = Path.GetDirectoryName(filepath);
            double   ttl        = context.GetParam("ttl", 0.0);
            TimeSpan?timeToLive = null;

            if (ttl > 0.0)
            {
                timeToLive = TimeSpan.FromSeconds(ttl);
            }
            if (Directory.Exists(filepath))
            {
                // filepath is actually an existing directory
                response.Return(DreamMessage.Conflict("there exists a directory at the specified file path"));
                yield break;
            }

            // create folder if need be
            if (!Directory.Exists(folderpath))
            {
                Directory.CreateDirectory(folderpath);
            }

            // save request stream in target file
            DreamMessage result;

            try {
                request.ToStream().CopyToFile(filepath, request.ContentLength);
                WriteMeta(filepath, timeToLive, null);
                result = DreamMessage.Ok();
            } catch (DirectoryNotFoundException) {
                result = DreamMessage.NotFound("directory not found");
            } catch (PathTooLongException) {
                result = DreamMessage.BadRequest("path too long");
            } catch (NotSupportedException) {
                result = DreamMessage.BadRequest("not supported");
            }
            response.Return(result);
            yield break;
        }
示例#21
0
 void MockPlug.IMockInvokee.Invoke(Plug plug, string verb, XUri uri, DreamMessage request, Result <DreamMessage> response)
 {
     lock (this) {
         if (_failed)
         {
             _log.DebugFormat("we've already failed, no point checking more expectations");
             response.Return(DreamMessage.InternalError());
             return;
         }
         _log.DebugFormat("{0}={1}", verb, uri);
         XDoc requestDoc = request.HasDocument ? request.ToDocument() : null;
         if (_expectations.Count == _current)
         {
             _log.DebugFormat("excess");
             ExcessInterception excess = new ExcessInterception();
             _excess.Add(excess);
             ;
             response.Return(excess.Call(verb, uri, requestDoc));
             return;
         }
         AutoMockInvokeExpectation expectation = _expectations[_current];
         expectation.Call(verb, uri, request);
         if (!expectation.Verify())
         {
             AddFailure(_expectations[_current].VerificationFailure);
             _log.DebugFormat("got failure, setting reset event ({0})", _current);
             _failed = true;
             _resetEvent.Set();
             response.Return(DreamMessage.BadRequest("expectation failure"));
             return;
         }
         _current++;
         _log.DebugFormat("expected");
         if (_expectations.Count == _current)
         {
             _log.DebugFormat("setting reset event");
             _resetEvent.Set();
         }
         response.Return(expectation.GetResponse());
     }
 }
示例#22
0
 private DreamMessage ExceptionTranslation(DreamContext context, Exception exception)
 {
     if (exception is CustomException)
     {
         _log.DebugFormat("caught custom exception");
         if (context.IsTaskEnvDisposed)
         {
             return(DreamMessage.BadRequest("context is disposed"));
         }
         if (ContextVar == null)
         {
             return(DreamMessage.BadRequest("context var wasn't set"));
         }
         if (ContextVar != context.GetState <ContextLifeSpan>())
         {
             return(DreamMessage.BadRequest("context vars didn't match"));
         }
         return(DreamMessage.Ok());
     }
     return(null);
 }
示例#23
0
        public Yield GetFileOrFolderListing(DreamContext context, DreamMessage request, Result <DreamMessage> response)
        {
            bool   head = StringUtil.EqualsInvariant(context.Verb, "HEAD");
            string path = GetPath(context);

            DreamMessage result;

            if (File.Exists(path))
            {
                // dealing with a file request
                TouchMeta(path);

                // check if request contains a 'if-modified-since' header
                var lastmodified = File.GetLastWriteTime(path);
                if (request.CheckCacheRevalidation(lastmodified) && (lastmodified.Year >= 1900))
                {
                    response.Return(DreamMessage.NotModified());
                    yield break;
                }

                // retrieve file
                try {
                    result = DreamMessage.FromFile(path, head);
                } catch (FileNotFoundException) {
                    result = DreamMessage.NotFound("file not found");
                } catch (Exception) {
                    result = DreamMessage.BadRequest("invalid path");
                }

                // add caching headers if file was found
                if (!head && result.IsSuccessful)
                {
                    // add caching information; this will avoid unnecessary data transfers by user-agents with caches
                    result.SetCacheMustRevalidate(lastmodified);
                }
            }
            else if (Directory.Exists(path))
            {
                // dealing with a directory request
                if (head)
                {
                    // HEAD for a directory doesn't really mean anything, so we just return ok, to indicate that it exists
                    result = DreamMessage.Ok();
                }
                else
                {
                    var doc = new XDoc("files");

                    // list directory contents
                    var directories = Directory.GetDirectories(path);
                    foreach (var dir in directories)
                    {
                        if (dir.EndsWithInvariantIgnoreCase(META))
                        {
                            continue;
                        }
                        doc.Start("folder")
                        .Elem("name", Path.GetFileName(dir))
                        .End();
                    }
                    foreach (var filepath in Directory.GetFiles(path))
                    {
                        var file = new FileInfo(filepath);
                        doc.Start("file")
                        .Elem("name", file.Name)
                        .Elem("size", file.Length)
                        .Elem("date.created", file.CreationTimeUtc)
                        .Elem("date.modified", file.LastWriteTimeUtc);
                        var entry = SyncMeta(filepath);
                        if (entry != null)
                        {
                            doc.Elem("date.expire", entry.When);
                            doc.Elem("date.ttl", entry.TTL);
                        }
                        doc.End();
                    }
                    result = DreamMessage.Ok(doc);
                }
            }
            else
            {
                // nothin here
                result = DreamMessage.NotFound("no such file or folder");
            }

            response.Return(result);
            yield break;
        }
示例#24
0
        public void Page_delete_events_skip_page_auth()
        {
            XUri mockDeki   = new XUri("http://mock/deki");
            int  dekiCalled = 0;

            MockPlug.Register(mockDeki, delegate(Plug p, string v, XUri u, DreamMessage r, Result <DreamMessage> r2) {
                _log.DebugFormat("mockDeki called at: {0}", u);
                dekiCalled++;
                r2.Return(DreamMessage.BadRequest("shouldn't have called deki"));
            });

            XUri           authorizedRecipient  = new XUri("http://mock/authorized2");
            AutoResetEvent authorizedResetEvent = new AutoResetEvent(false);
            XDoc           authorizedReceived   = null;

            MockPlug.Register(authorizedRecipient, delegate(Plug p, string v, XUri u, DreamMessage r, Result <DreamMessage> r2) {
                _log.DebugFormat("authorizedRecipient called at: {0}", u);
                authorizedReceived = r.ToDocument();
                authorizedResetEvent.Set();
                r2.Return(DreamMessage.Ok());
            });

            XUri mockRecipient       = new XUri("http://mock/r1");
            int  mockRecipientCalled = 0;

            MockPlug.Register(mockRecipient, delegate(Plug p, string v, XUri u, DreamMessage r, Result <DreamMessage> r2) {
                _log.DebugFormat("mockRecipient called at: {0}", u);
                mockRecipientCalled++;
                r2.Return(DreamMessage.Ok());
            });

            XUri           dispatcherUri = new XUri("http://mock/dispatcher");
            DekiDispatcher dispatcher    = new DekiDispatcher(
                new DispatcherConfig {
                ServiceUri          = dispatcherUri,
                ServiceAccessCookie = new DreamCookie("service-key", "foo", dispatcherUri),
                ServiceConfig       = new XDoc("config").Elem("uri.deki", mockDeki).Elem("authtoken", "abc")
            },
                _mockRepository.Object
                );

            XDoc sub1 = new XDoc("subscription-set")
                        .Elem("uri.owner", authorizedRecipient)
                        .Start("subscription")
                        .Attr("id", "1")
                        .Elem("channel", "event://default/deki/pages/*")
                        .Start("recipient").Attr("authtoken", "abc").Elem("uri", authorizedRecipient).End()
                        .End();

            Thread.Sleep(100);
            _log.DebugFormat("registering sub set 1");
            dispatcher.RegisterSet("abc", sub1, "def");
            XDoc sub2 = new XDoc("subscription-set")
                        .Elem("uri.owner", mockRecipient.At("1"))
                        .Start("subscription")
                        .Attr("id", "1")
                        .Elem("uri.resource", "deki://default/pages/10")
                        .Elem("channel", "event://default/deki/pages/*")
                        .Start("recipient").Attr("userid", "1").Elem("uri", "http://mock/r1/match").End()
                        .End();

            Thread.Sleep(100);
            _log.DebugFormat("registering sub set 2");
            dispatcher.RegisterSet("abc", sub2, "def");

            XDoc evDoc = new XDoc("deki-event")
                         .Attr("wikiid", "default")
                         .Elem("channel", "event://default/deki/pages/delete")
                         .Elem("uri", "deki://default/pages/10")
                         .Elem("pageid", "10");
            var ev = new DispatcherEvent(evDoc, new XUri("event://default/deki/pages/delete"), new XUri("deki://default/pages/10"), new XUri("http://default/deki/pages/10"));

            _log.DebugFormat("ready to dispatch event");

            // Meh. Testing multithreaded code is wonky. This 1000ms sleep is required, otherwise the event below never fires
            Thread.Sleep(1000);
            dispatcher.Dispatch(ev);

            // since we're waiting for more than one dekiPageAuthEvent, we give it a chance to finish after the first triggers
            Assert.IsTrue(authorizedResetEvent.WaitOne(5000, false));
            Assert.AreEqual(0, dekiCalled);
            Assert.AreEqual(0, mockRecipientCalled);
            Assert.AreEqual(evDoc, authorizedReceived);
        }
 //--- Misc exception handlers ---
 private static DreamMessage Map(MindTouchInvalidOperationException e, DekiResources resources)
 {
     return(DreamMessage.BadRequest(e.Message));
 }
 private static DreamMessage Map(DekiLicenseException e, DekiResources resources)
 {
     return(DreamMessage.BadRequest(e.Message));
 }
 //--- generic ResourcedMindTouchException handlers ---
 private static DreamMessage Map(MindTouchInvalidCallException e, DekiResources resources)
 {
     return(DreamMessage.BadRequest(resources.Localize(e.Resource)));
 }
 private DreamMessage MapPlainException(DreamContext context, Exception exception)
 {
     return(DreamMessage.BadRequest(exception.Message));
 }
示例#29
0
        public Yield GetQueuedItem(DreamContext context, DreamMessage request, Result <DreamMessage> response)
        {
            uint   pageId      = context.GetParam <uint>("pageid", 0);
            string containerId = context.GetParam("containerId", null);
            string authtoken   = null;

            foreach (DreamCookie cookie in request.Cookies)
            {
                if (StringUtil.EqualsInvariantIgnoreCase("authtoken", cookie.Name))
                {
                    authtoken = cookie.Value;
                    break;
                }
            }
            if (pageId == 0)
            {
                _log.WarnFormat("Bad pageId");
                response.Return(DreamMessage.BadRequest("Bad pageId"));
                yield break;
            }
            if (string.IsNullOrEmpty(containerId))
            {
                _log.WarnFormat("Missing containerId");
                response.Return(DreamMessage.BadRequest("Missing containerId"));
                yield break;
            }
            if (string.IsNullOrEmpty(authtoken))
            {
                _log.WarnFormat("Unable to retrieve subscriber credentials from cookie");
                response.Return(DreamMessage.BadRequest("Unable to retrieve subscriber credentials from cookie"));
                yield break;
            }
            Tuplet <string, DateTime> userCache;

            if (!_userCache.TryGetValue(authtoken, out userCache))
            {
                Result <DreamMessage> userResult;
                yield return(userResult = _deki.At("users", "current").WithHeader("X-Authtoken", authtoken).GetAsync());

                if (!userResult.Value.IsSuccessful)
                {
                    _log.WarnFormat("Unable to retrieve user info for provided credentials");
                    response.Return(DreamMessage.BadRequest("Unable to retrieve user info for provided credentials"));
                    yield break;
                }
                XDoc userDoc = userResult.Value.ToDocument();
                _log.DebugFormat("caching user info for '{0}': {1}", userDoc["username"].AsText, userDoc["@href"].AsUri.AsPublicUri());
                userCache = new Tuplet <string, DateTime>(userDoc["@href"].AsUri.AsPublicUri().Path, DateTime.UtcNow);
                lock (_userCache) {
                    _userCache[authtoken] = userCache;
                }
            }
            string subscriber = userCache.Item1;

            lock (_subscriptions) {
                Subscription subscription;
                if (!_subscriptions.TryGetValue(pageId, out subscription))
                {
                    subscription           = new Subscription();
                    _subscriptions[pageId] = subscription;
                    _log.DebugFormat("created subscription for {0}", pageId);
                }
                _log.DebugFormat("checking subscription for {0}", subscriber);
                if (!subscription.HasChanged(subscriber))
                {
                    response.Return(DreamMessage.Ok());
                    yield break;
                }
            }
            XDoc doc = new XDoc("div")
                       .Attr("class", "systemmsg")
                       .Start("div")
                       .Attr("class", "inner")
                       .Value("The page has changed. Click ")
                       .Start("a")
                       .Attr("rel", "custom")
                       .Attr("href", "")
                       .Value("here")
                       .End()
                       .Value(" to reload.")
                       .End()
                       .Start("script")
                       .Attr("type", "text/javascript")
                       .Value(string.Format("$('#{0}').slideDown('slow');", containerId))
                       .End();

            _log.DebugFormat("page {0} changed deliverd", pageId);
            response.Return(DreamMessage.Ok(doc));
            yield break;
        }