/// <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)); }
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)); }
/// <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))); } }
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); } }