Esempio n. 1
0
        public void GetFileContent()
        {
            // GET:files/{fileid}
            // http://developer.mindtouch.com/Deki/API_Reference/GET%3afiles%2f%2f%7bfileid%7d

            Plug p = Utils.BuildPlugForAdmin();

            string       id   = null;
            string       path = null;
            DreamMessage msg  = PageUtils.CreateRandomPage(p, out id, out path);

            byte[] content  = FileUtils.GenerateRandomContent();
            string fileid   = null;
            string filename = null;

            msg = FileUtils.UploadRandomFile(p, id, content, string.Empty, out fileid, out filename);

            msg = p.At("files", fileid).Get();
            Assert.AreEqual(DreamStatus.Ok, msg.Status);
            Assert.IsTrue(Utils.ByteArraysAreEqual(content, msg.AsBytes()));

            // GET:files/{fileid}/{filename}
            // http://developer.mindtouch.com/Deki/API_Reference/GET%3afiles%2f%2f%7bfileid%7d%2f%2f%7bfilename%7d

            msg = p.At("files", fileid, "=" + filename).Get();
            Assert.AreEqual(DreamStatus.Ok, msg.Status);
            Assert.IsTrue(Utils.ByteArraysAreEqual(content, msg.AsBytes()));

            PageUtils.DeletePageByID(p, id, true);
        }
Esempio n. 2
0
        public void GetFileFromAnonymous()
        {
            //Assumptions:
            //
            //Actions:
            // create page
            // upload file to page
            // try get file from anonymous account
            //Expected result:
            // ok

            Plug p = Utils.BuildPlugForAdmin();

            string       id  = null;
            DreamMessage msg = PageUtils.CreateRandomPage(p, out id);

            byte[] content  = FileUtils.GenerateRandomContent();
            string fileid   = null;
            string filename = null;

            msg = FileUtils.UploadRandomFile(p, id, content, string.Empty, out fileid, out filename);

            p = Utils.BuildPlugForAnonymous();

            msg = p.At("files", fileid).Get();
            Assert.AreEqual(DreamStatus.Ok, msg.Status);
            Assert.IsTrue(Utils.ByteArraysAreEqual(content, msg.AsBytes()));

            p = Utils.BuildPlugForAdmin();
            PageUtils.DeletePageByID(p, id, true);
        }
Esempio n. 3
0
        public void UploadFileWithZeroSize()
        {
            // Acquire ADMIN permissions
            Plug p = Utils.BuildPlugForAdmin();

            /// Create a random page
            string       id   = null;
            string       path = null;
            DreamMessage msg  = PageUtils.CreateRandomPage(p, out id, out path);

            // Create a file with zero size and upload it to page
            byte[] content  = new byte[0];
            string fileid   = null;
            string filename = null;

            msg = FileUtils.UploadRandomFile(p, id, content, string.Empty, out fileid, out filename);

            // Retrieve file
            msg = p.At("files", fileid).Get();

            // Assert OK HTTP status returned
            Assert.AreEqual(DreamStatus.Ok, msg.Status);

            // Assert uploaded file content equals retrieved file content
            Assert.IsTrue(Utils.ByteArraysAreEqual(content, msg.AsBytes()));

            // Delete the page
            PageUtils.DeletePageByID(p, id, true);
        }
Esempio n. 4
0
        public void UploadFileWithConfigExtension()
        {
            // Acquire ADMIN permissions
            Plug p = Utils.BuildPlugForAdmin();

            // Create a random page
            string       id   = null;
            string       path = null;
            DreamMessage msg  = PageUtils.CreateRandomPage(p, out id, out path);

            // Create a file with random content and a .config extension
            byte[] content  = FileUtils.GenerateRandomContent();
            string fileid   = null;
            string filename = System.IO.Path.GetTempPath() + "/=file" + Utils.GenerateUniqueName() + ".config";

            FileUtils.CreateFile(content, filename);

            // Upload the file and assert it uploaded successfully
            msg = FileUtils.UploadFile(p, id, string.Empty, out fileid, filename);
            Assert.AreEqual(DreamStatus.Ok, msg.Status, "File upload failed!");

            // Assert uploaded file has only 1 revision
            msg = p.At("pages", id, "files").Get();
            Assert.AreEqual(1, msg.ToDocument()["file/revisions/@count"].AsInt, "File revision count does not equal 1!");

            // Retrieve file, assert retrieval is successful, and assert retrieved content matches generated content
            msg = p.At("files", fileid).Get();
            Assert.AreEqual(DreamStatus.Ok, msg.Status, "File retrieval failed!");
            Assert.IsTrue(Utils.ByteArraysAreEqual(content, msg.AsBytes()), "Retrieved content does not match generated content!");

            // Delete the page
            PageUtils.DeletePageByID(p, id, true);
        }
Esempio n. 5
0
        public object Fetch(
            [DekiExtParam("document id")] string id
            )
        {
            // fetch response from cache
            CacheEntry result;

            lock (_cacheLookup) {
                _cacheLookup.TryGetValue(id, out result);
            }

            // check if we have a cached entry
            XDoc document = null;

            if (result != null)
            {
                _log.DebugFormat("cache hit for '{0}'", result.Id);
                result.ResetMemoryExpiration();
                if (result.Cache != null)
                {
                    _log.DebugFormat("cache data in memory '{0}'", result.Id);
                    document = XDocFactory.From(result.Cache, MimeType.XML);
                }
                else
                {
                    // we have the result on disk, so let's fetch it
                    DreamMessage msg = Storage.At(CACHE_DATA, result.Guid + ".bin").GetAsync().Wait();
                    if (msg.IsSuccessful)
                    {
                        _log.DebugFormat("cache data pulled from disk");
                        result.Cache = Encoding.UTF8.GetString(msg.AsBytes());
                        document     = XDocFactory.From(result.Cache, MimeType.XML);
                    }
                    else
                    {
                        _log.DebugFormat("unable to fetch cache data from disk: {0}", msg.Status);
                    }
                }
            }

            // check if we have a document to convert
            if (document != null)
            {
                try {
                    DekiScriptList list = (DekiScriptList)DekiScriptLiteral.FromXml(document);
                    return(list[0]);
                } catch {
                    // the cached entry is corrupted, remove it
                    Clear(id);
                }
            }
            return(null);
        }
Esempio n. 6
0
        public void UploadFileWithLongName()
        {
            // Acquire ADMIN permissions
            Plug p = Utils.BuildPlugForAdmin();

            // Create a random page
            string       id   = null;
            string       path = null;
            DreamMessage msg  = PageUtils.CreateRandomPage(p, out id, out path);

            // Create a file with random content and with a long name
            string fileid   = null;
            string filename = System.IO.Path.GetTempPath() + "file" + Utils.GenerateUniqueName();

            filename = filename.PadRight(250, 'a');
            byte[] content = FileUtils.GenerateRandomContent();
            FileUtils.CreateFile(content, filename);

            // Upload the file, assert it uploaded successfully, and store filename returned in document
            msg = FileUtils.UploadFile(p, id, string.Empty, out fileid, filename);
            Assert.AreEqual(DreamStatus.Ok, msg.Status, "File upload failed");
            string savedFileName = msg.ToDocument()["filename"].AsText;

            // Retrieve the file and assert it retrieved successfully.
            msg = p.At("files", fileid).Get();
            Assert.AreEqual(DreamStatus.Ok, msg.Status, "File content retrieval failed");

            // Assert retrieved file content matches generated content
            Assert.IsTrue(Utils.ByteArraysAreEqual(content, msg.AsBytes()), "Retrieved file content does not match generated content!");

            // Retrieve page files and assert file is present
            msg = p.At("pages", id, "files").Get();
            Assert.AreEqual(savedFileName, msg.ToDocument()["file/filename"].AsText, "File is not attached to page!");

            // Delete the page
            PageUtils.DeletePageByID(p, id, true);
        }
Esempio n. 7
0
        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);
        }
Esempio n. 8
0
        private string CachedWebGet(XUri uri, double?ttl, bool?nilIfMissing)
        {
            string id = uri.ToString();

            // fetch message from cache or from the web
            CacheEntry result;
            bool       isNew = true;

            lock (_cacheLookup) {
                _cacheLookup.TryGetValue(id, out result);
            }

            // check if we have a cached entry
            if (result != null)
            {
                _log.DebugFormat("cache hit for '{0}'", result.Id);
                isNew = false;
                result.ResetMemoryExpiration();
                if (result.Cache != null)
                {
                    _log.DebugFormat("cache data in memory '{0}'", result.Id);
                    return(result.Cache);
                }

                // we have the result on disk, so let's fetch it
                DreamMessage msg = Storage.At(CACHE_DATA, result.Guid + ".bin").GetAsync().Wait();
                if (msg.IsSuccessful)
                {
                    _log.DebugFormat("cache data pulled from disk");
                    result.Cache = Encoding.UTF8.GetString(msg.AsBytes());
                    return(result.Cache);
                }
                _log.DebugFormat("unable to fetch cache data from disk: {0}", msg.Status);
            }
            else
            {
                _log.DebugFormat("new cache item for '{0}'", id);
                result = new CacheEntry(id, ttl);
            }

            // do the web request
            Result <DreamMessage> response = new Result <DreamMessage>();

            Plug.New(uri).WithTimeout(DEFAULT_WEB_TIMEOUT).InvokeEx("GET", DreamMessage.Ok(), response);
            DreamMessage message = response.Wait();

            try {
                // check message status
                if (!message.IsSuccessful)
                {
                    if (nilIfMissing.GetValueOrDefault())
                    {
                        return(null);
                    }
                    return(message.Status == DreamStatus.UnableToConnect
                        ? string.Format("(unable to fetch text document from uri [status: {0} ({1}), message: \"{2}\"])", (int)message.Status, message.Status, message.ToDocument()["message"].AsText)
                        : string.Format("(unable to fetch text document from uri [status: {0} ({1})])", (int)message.Status, message.Status));
                }

                // check message size
                Result resMemorize = message.Memorize(_insertTextLimit, new Result()).Block();
                if (resMemorize.HasException)
                {
                    return(nilIfMissing.GetValueOrDefault() ? null : "(text document is too large)");
                }

                // detect encoding and decode response
                var stream   = message.ToStream();
                var encoding = stream.DetectEncoding() ?? message.ContentType.CharSet;
                result.Cache = encoding.GetString(stream.ReadBytes(-1));
            } finally {
                message.Close();
            }

            // start timer to clean-up cached result
            if (result.Cache != null)
            {
                XDoc infoDoc = new XDoc("cache-entry")
                               .Elem("guid", result.Guid)
                               .Elem("id", result.Id)
                               .Elem("expires", result.Expires);
                lock (result) {
                    Storage.At(CACHE_DATA, result.Guid + ".bin").PutAsync(new DreamMessage(DreamStatus.Ok, null, MimeType.BINARY, Encoding.UTF8.GetBytes(result.Cache))).Wait();
                    Storage.At(CACHE_INFO, result.Guid + ".xml").PutAsync(infoDoc).Wait();
                }
                if (isNew)
                {
                    lock (_cacheLookup) {
                        _cacheLookup[id] = result;
                    }

                    // this timer removes the cache entry from disk
                    SetupCacheTimer(result);
                }
            }
            return(result.Cache);
        }
        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);
        }
Esempio n. 10
0
        public void LogoTest() // TODO: split
        {
            // GET:logo.png
            // ...

            // 1. Retrieve logo
            // (2) Assert logo retrieved successfully (200 OK HTTP response)
            // 3. Generate a PNG image
            // 4. Upload as logo
            // (5) Assert logo uploaded successfully (200 OK HTTP response)
            // 6. Retrieve logo once again
            // (7) Assert retrieved logo matches uploaded logo
            // 8. Delete logo
            // (9) Assert logo delete was successful (200 OK HTTP response)
            // 10. Retrieve logo once more
            // (11) Assert 404 Not Found HTTP response

            Plug p = Utils.BuildPlugForAdmin();

            DreamMessage msg = p.At("site", "logo.png").Get();

            Assert.AreEqual(DreamStatus.Ok, msg.Status, "Logo retrieval failed");

            // PUT:site/logo
            // ...

            byte[] imageData = null;

            System.Drawing.Bitmap pic = new System.Drawing.Bitmap(100, 100);
            using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(pic))
                g.DrawRectangle(System.Drawing.Pens.Blue, 10, 10, 80, 80);
            System.IO.MemoryStream stream = new System.IO.MemoryStream();
            pic.Save(stream, System.Drawing.Imaging.ImageFormat.Png);

            imageData = stream.ToArray();
            msg       = p.At("site", "logo").Put(DreamMessage.Ok(MimeType.PNG, imageData));
            Assert.AreEqual(DreamStatus.Ok, msg.Status, "Logo upload (PUT) failed");

            // GET:site/logo
            // ...

            msg = p.At("site", "logo").Get();
            Assert.AreEqual(DreamStatus.Ok, msg.Status);

            Utils.ByteArraysAreEqual(msg.AsBytes(), imageData);

            // GET:site/logo.png
            // ...

            msg = p.At("site", "logo.png").Get();
            Assert.AreEqual(DreamStatus.Ok, msg.Status, "Logo retrieval failed");

            Utils.ByteArraysAreEqual(msg.AsBytes(), imageData);

            // DELETE:site/logo
            // ...

            msg = p.At("site", "logo").Delete();
            Assert.AreEqual(DreamStatus.Ok, msg.Status, "Logo deletion failed");

            msg = p.At("site", "logo").GetAsync().Wait();
            Assert.AreEqual(DreamStatus.NotFound, msg.Status, "Logo successfully retrieved after deletion?!");
        }