예제 #1
0
        /// <exception cref="System.IO.FileNotFoundException"></exception>
        private void OpenTempFile()
        {
            string   uuid     = Misc.CreateGUID();
            string   filename = string.Format("{0}.blobtmp", uuid);
            FilePath tempDir  = store.TempDir();

            tempFile  = new FilePath(tempDir, filename);
            outStream = new BufferedOutputStream(new FileOutputStream(tempFile));
        }
예제 #2
0
        private static SavedRevision CreateRevisionWithRandomProps(SavedRevision parentRev, Boolean allowConflict)
        {
            var properties = new Dictionary <string, object>();

            properties["val"] = Misc.CreateGUID();
            var unsavedRevision = parentRev.CreateRevision();

            unsavedRevision.SetUserProperties(properties);
            return(unsavedRevision.Save(allowConflict));
        }
        /// <exception cref="System.Exception"></exception>
        public static SavedRevision CreateRevisionWithRandomProps(SavedRevision createRevFrom, bool allowConflict)
        {
            var properties = new Dictionary <string, object>();

            properties.Put(Misc.CreateGUID(), "val");

            var unsavedRevision = createRevFrom.CreateRevision();

            unsavedRevision.SetUserProperties(properties);

            return(unsavedRevision.Save(allowConflict));
        }
예제 #4
0
        /// <exception cref="System.IO.FileNotFoundException"></exception>
        private void OpenTempFile()
        {
            string uuid     = Misc.CreateGUID();
            string filename = string.Format("{0}.blobtmp", uuid);
            var    tempDir  = store.TempDir();

            tempFile = Path.Combine(tempDir, filename);
            if (store.EncryptionKey == null)
            {
                outStream = new BufferedStream(File.Open(tempFile, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite));
            }
            else
            {
                outStream = store.EncryptionKey.CreateStream(
                    new BufferedStream(File.Open(tempFile, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)));
            }
        }
예제 #5
0
        public AtomicAction ActionToChangeEncryptionKey(SymmetricKey newKey)
        {
            var action = new AtomicAction();

            // Find all the blob files:
            var blobs  = default(string[]);
            var oldKey = EncryptionKey;

            blobs = Directory.GetFiles(_path, "*" + FileExtension);
            if (blobs.Length == 0)
            {
                // No blobs, so nothing to encrypt. Just add/remove the encryption marker file:
                action.AddLogic(() =>
                {
                    Log.D(TAG, "{0} {1}", (newKey != null) ? "encrypting" : "decrypting", _path);
                    Log.D(TAG, "    No blobs to copy; done.");
                    EncryptionKey = newKey;
                    MarkEncrypted(newKey != null);
                }, () =>
                {
                    EncryptionKey = oldKey;
                    MarkEncrypted(oldKey != null);
                }, null);
                return(action);
            }

            // Create a new directory for the new blob store. Have to do this now, before starting the
            // action, because farther down we create an action to move it...
            var tempPath = Path.Combine(Path.GetTempPath(), String.Format("CouchbaseLite-Temp-{0}", Misc.CreateGUID()));

            action.AddLogic(() =>
            {
                Log.D(TAG, "{0} {1}", (newKey != null) ? "encrypting" : "decrypting", _path);
                Directory.CreateDirectory(tempPath);
            }, () => Directory.Delete(tempPath, true), null);

            var tempStore = default(BlobStore);

            action.AddLogic(() =>
            {
                tempStore = new BlobStore(tempPath, newKey);
                tempStore.MarkEncrypted(true);
            }, null, null);

            // Copy each of my blobs into the new store (which will update its encryption):
            action.AddLogic(() =>
            {
                foreach (var blobName in blobs)
                {
                    // Copy file by reading with old key and writing with new one:
                    Log.D(TAG, "    Copying {0}", blobName);
                    Stream readStream = File.Open(blobName, FileMode.Open, FileAccess.Read, FileShare.Read);
                    if (EncryptionKey != null)
                    {
                        readStream = EncryptionKey.DecryptStream(readStream);
                    }

                    var writer = new BlobStoreWriter(tempStore);
                    try {
                        writer.Read(readStream);
                        writer.Finish();
                        writer.Install();
                    } catch (Exception) {
                        writer.Cancel();
                        throw;
                    } finally {
                        readStream.Dispose();
                    }
                }
            }, null, null);

            // Replace the attachment dir with the new one:
            action.AddLogic(AtomicAction.MoveDirectory(tempPath, _path));

            // Finally update EncryptionKey:
            action.AddLogic(() =>
            {
                EncryptionKey = newKey;
            }, () =>
            {
                EncryptionKey = oldKey;
            }, null);

            return(action);
        }
        public void TestUpgradeMD5()
        {
            var store = database.Storage as SqliteCouchStore;

            if (store == null)
            {
                Assert.Inconclusive("This test is only valid for a SQLite based store, since any others will be too new to see this issue");
            }

            using (var client = new HttpClient()) {
                var couchDbUri = String.Format("http://{0}:5984/", GetReplicationServer());

                try {
                    var request = new HttpRequestMessage(HttpMethod.Get, new Uri(couchDbUri));
                    client.SendAsync(request).Wait();
                } catch (Exception) {
                    Assert.Inconclusive("Apache CouchDB not running");
                }

                var dbName     = "a" + Misc.CreateGUID();
                var putRequest = new HttpRequestMessage(HttpMethod.Put, new Uri(couchDbUri + dbName));
                var response   = client.SendAsync(putRequest).Result;
                Assert.AreEqual(HttpStatusCode.Created, response.StatusCode);


                // The API prevents new insertions with MD5 hashes, so we need to insert this bypassing the API
                // to simulate a legacy document
                var engine      = store.StorageEngine;
                var docName     = "doc" + Convert.ToString(DateTime.UtcNow.ToMillisecondsSinceEpoch());
                var contentVals = new ContentValues();
                contentVals["docid"] = docName;
                engine.Insert("docs", null, contentVals);

                contentVals                   = new ContentValues();
                contentVals["doc_id"]         = 1;
                contentVals["revid"]          = "1-1153b140e4c8674e2e6425c94de860a0";
                contentVals["current"]        = false;
                contentVals["deleted"]        = false;
                contentVals["no_attachments"] = true;
                string json = "{\"foo\":false}";
                contentVals["json"] = Encoding.UTF8.GetBytes(json);
                engine.Insert("revs", null, contentVals);

                contentVals                   = new ContentValues();
                contentVals["doc_id"]         = 1;
                contentVals["revid"]          = "2-bb71ce0da1de19f848177525c4ae5a8b";
                contentVals["current"]        = false;
                contentVals["deleted"]        = false;
                contentVals["no_attachments"] = false;
                contentVals["parent"]         = 1;
                json = "{\"foo\":false,\"_attachments\":{\"attachment\":{\"content_type\":\"image/png\",\"revpos\":2," +
                       "\"digest\":\"md5-ks1IBwCXbuY7VWAO9CkEjA==\",\"length\":519173,\"stub\":true}}}";
                contentVals["json"] = Encoding.UTF8.GetBytes(json);
                engine.Insert("revs", null, contentVals);

                contentVals                   = new ContentValues();
                contentVals["doc_id"]         = 1;
                contentVals["revid"]          = "3-a020d6aae370ab5cbc136c477f4e5928";
                contentVals["current"]        = true;
                contentVals["deleted"]        = false;
                contentVals["no_attachments"] = false;
                contentVals["parent"]         = 2;
                json = "{\"foo\":true,\"_attachments\":{\"attachment\":{\"content_type\":\"image/png\",\"revpos\":2," +
                       "\"digest\":\"md5-ks1IBwCXbuY7VWAO9CkEjA==\",\"length\":519173,\"stub\":true}}}";
                contentVals["json"] = Encoding.UTF8.GetBytes(json);
                engine.Insert("revs", null, contentVals);

                var attachmentStream = (InputStream)GetAsset("attachment.png");
                var fileStream       = File.OpenWrite(Path.Combine(database.AttachmentStorePath, "92CD480700976EE63B55600EF429048C.blob"));
                attachmentStream.Wrapped.CopyTo(fileStream);
                attachmentStream.Dispose();
                fileStream.Dispose();

                var baseEndpoint = String.Format("http://{0}:5984/{1}/{2}", GetReplicationServer(), dbName, docName);
                var endpoint     = baseEndpoint;
                putRequest         = new HttpRequestMessage(HttpMethod.Put, new Uri(endpoint));
                putRequest.Content = new StringContent("{\"foo\":false}");
                putRequest.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                response = client.SendAsync(putRequest).Result;
                Assert.AreEqual(HttpStatusCode.Created, response.StatusCode);


                attachmentStream = (InputStream)GetAsset("attachment.png");
                var baos = new MemoryStream();
                attachmentStream.Wrapped.CopyTo(baos);
                attachmentStream.Dispose();
                endpoint = baseEndpoint + "/attachment?rev=1-1153b140e4c8674e2e6425c94de860a0";

                putRequest         = new HttpRequestMessage(HttpMethod.Put, new Uri(endpoint));
                putRequest.Content = new ByteArrayContent(baos.ToArray());
                putRequest.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
                baos.Dispose();
                response = client.SendAsync(putRequest).Result;
                Assert.AreEqual(HttpStatusCode.Created, response.StatusCode);

                endpoint           = baseEndpoint + "?rev=2-bb71ce0da1de19f848177525c4ae5a8b";
                putRequest         = new HttpRequestMessage(HttpMethod.Put, new Uri(endpoint));
                putRequest.Content = new StringContent("{\"foo\":true,\"_attachments\":{\"attachment\":{\"content_type\":\"image/png\",\"revpos\":2,\"digest\":\"md5-ks1IBwCXbuY7VWAO9CkEjA==\",\"length\":519173,\"stub\":true}}}");
                putRequest.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                response = client.SendAsync(putRequest).Result;
                Assert.AreEqual(HttpStatusCode.Created, response.StatusCode);

                var pull = database.CreatePullReplication(new Uri(couchDbUri + dbName));
                pull.Continuous = true;
                pull.Start();

                endpoint           = baseEndpoint + "?rev=3-a020d6aae370ab5cbc136c477f4e5928";
                putRequest         = new HttpRequestMessage(HttpMethod.Put, new Uri(endpoint));
                putRequest.Content = new StringContent("{\"foo\":false,\"_attachments\":{\"attachment\":{\"content_type\":\"image/png\",\"revpos\":2,\"digest\":\"md5-ks1IBwCXbuY7VWAO9CkEjA==\",\"length\":519173,\"stub\":true}}}");
                putRequest.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                response = client.SendAsync(putRequest).Result;
                Assert.AreEqual(HttpStatusCode.Created, response.StatusCode);

                Sleep(1000);
                while (pull.Status == ReplicationStatus.Active)
                {
                    Sleep(500);
                }

                var doc = database.GetExistingDocument(docName);
                Assert.AreEqual("4-a91f8875144c6162874371c07a08ea17", doc.CurrentRevisionId);
                var attachment = doc.CurrentRevision.Attachments.ElementAtOrDefault(0);
                Assert.IsNotNull(attachment);
                var attachmentsDict = doc.GetProperty("_attachments").AsDictionary <string, object>();
                var attachmentDict  = attachmentsDict.Get("attachment").AsDictionary <string, object>();
                Assert.AreEqual("md5-ks1IBwCXbuY7VWAO9CkEjA==", attachmentDict["digest"]);

                var deleteRequest = new HttpRequestMessage(HttpMethod.Delete, baseEndpoint + "/attachment?rev=4-a91f8875144c6162874371c07a08ea17");
                response = client.SendAsync(deleteRequest).Result;
                Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);

                attachmentStream = (InputStream)GetAsset("attachment2.png");
                baos             = new MemoryStream();
                attachmentStream.Wrapped.CopyTo(baos);
                attachmentStream.Dispose();
                endpoint = baseEndpoint + "/attachment?rev=5-4737cb66c6a7ef1b11e872cb6fa4d51a";

                putRequest         = new HttpRequestMessage(HttpMethod.Put, endpoint);
                putRequest.Content = new ByteArrayContent(baos.ToArray());
                putRequest.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
                baos.Dispose();
                response = client.SendAsync(putRequest).Result;
                Assert.AreEqual(HttpStatusCode.Created, response.StatusCode);

                Sleep(1000);
                while (pull.Status == ReplicationStatus.Active)
                {
                    Sleep(500);
                }

                doc = database.GetExistingDocument(docName);
                Assert.AreEqual("6-e3a7423a9a9de094a0d12d7f3b44634c", doc.CurrentRevisionId);
                attachment = doc.CurrentRevision.Attachments.ElementAtOrDefault(0);
                Assert.IsNotNull(attachment);
                attachmentsDict = doc.GetProperty("_attachments").AsDictionary <string, object>();
                attachmentDict  = attachmentsDict.Get("attachment").AsDictionary <string, object>();
                Assert.AreEqual("sha1-9ijdmMf0mK7c11WQPw7DBQcX5pE=", attachmentDict["digest"]);

                deleteRequest = new HttpRequestMessage(HttpMethod.Delete, couchDbUri + dbName);
                response      = client.SendAsync(deleteRequest).Result;
                Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
            }
        }