示例#1
0
 public virtual void StartedPart(IDictionary <string, string> headers)
 {
     if (document == null)
     {
         jsonBuffer = new ByteArrayBuffer(1024);
     }
     else
     {
         curAttachment = database.GetAttachmentWriter();
         string contentDisposition = headers.Get("Content-Disposition");
         if (contentDisposition != null && contentDisposition.StartsWith("attachment; filename="
                                                                         ))
         {
             // TODO: Parse this less simplistically. Right now it assumes it's in exactly the same
             // format generated by -[CBL_Pusher uploadMultipartRevision:]. CouchDB (as of 1.2) doesn't
             // output any headers at all on attachments so there's no compatibility issue yet.
             string contentDispositionUnquoted = Misc.UnquoteString(contentDisposition);
             string name = Sharpen.Runtime.Substring(contentDispositionUnquoted, 21);
             if (name != null)
             {
                 attachmentsByName.Put(name, curAttachment);
             }
         }
     }
 }
        public void StartedPart(IDictionary <String, String> headers)
        {
            if (document == null)
            {
                StartJsonBuffer(headers);
            }
            else
            {
                Log.To.Sync.V(TAG, "{0} starting attachment #{1}...", this, attachmentsByDigest.Count + 1);
                curAttachment = database.AttachmentWriter;
                if (curAttachment == null)
                {
                    throw Misc.CreateExceptionAndLog(Log.To.Sync, StatusCode.AttachmentError, TAG,
                                                     "Cannot create blob store writer for the attachment");
                }

                var name = default(string);
                var contentDisposition = headers.Get("Content-Disposition");
                if (contentDisposition != null && contentDisposition.StartsWith("attachment; filename="))
                {
                    // TODO: Parse this less simplistically. Right now it assumes it's in exactly the same
                    // format generated by -[CBL_Pusher uploadMultipartRevision:]. CouchDB (as of 1.2) doesn't
                    // output any headers at all on attachments so there's no compatibility issue yet.
                    var contentDispositionUnquoted = Misc.UnquoteString(contentDisposition);
                    name = contentDispositionUnquoted.Substring(21);
                    if (name != null)
                    {
                        attachmentsByName[name] = curAttachment;
                    }
                }

                var contentEncoding = headers.Get("Content-Encoding");
                if (contentEncoding == "gzip")
                {
                    if (name != null)
                    {
                        try {
                            var attachEncoding = document.GetCast <IDictionary <string, object> >("_attachments").
                                                 GetCast <IDictionary <string, object> >(name).GetCast <string>("encoding");
                            if (attachEncoding != "gzip")
                            {
                                throw Misc.CreateExceptionAndLog(Log.To.Sync, StatusCode.UnsupportedType, TAG,
                                                                 "Attachment '{0}' MIME body is gzipped but attachment isn't",
                                                                 new SecureLogString(name, LogMessageSensitivity.PotentiallyInsecure));
                            }
                        } catch (NullReferenceException) {
                            throw Misc.CreateExceptionAndLog(Log.To.Sync, StatusCode.UnsupportedType, TAG,
                                                             "NullReferenceException caught; _attachments was not present or encoding was " +
                                                             "not present in _attachments");
                        }
                    }
                }
                else if (contentEncoding != null)
                {
                    throw Misc.CreateExceptionAndLog(Log.To.Sync, StatusCode.UnsupportedType, TAG,
                                                     "Received unsupported Content-Encoding '{0}'", contentEncoding);
                }
            }
        }
        public void StartedPart(IDictionary <String, String> headers)
        {
            if (document == null)
            {
                StartJsonBuffer(headers);
            }
            else
            {
                Log.V(TAG, "    Starting attachment #{0}...", attachmentsBySHA1Digest.Count + 1);
                curAttachment = database.AttachmentWriter;
                if (curAttachment == null)
                {
                    const string msg = "Cannot create blob store writer for the attachment";
                    Log.W(TAG, msg);
                    throw new CouchbaseLiteException(msg, StatusCode.AttachmentError);
                }

                var name = default(string);
                var contentDisposition = headers.Get("Content-Disposition");
                if (contentDisposition != null && contentDisposition.StartsWith("attachment; filename="))
                {
                    // TODO: Parse this less simplistically. Right now it assumes it's in exactly the same
                    // format generated by -[CBL_Pusher uploadMultipartRevision:]. CouchDB (as of 1.2) doesn't
                    // output any headers at all on attachments so there's no compatibility issue yet.
                    var contentDispositionUnquoted = Misc.UnquoteString(contentDisposition);
                    name = contentDispositionUnquoted.Substring(21);
                    if (name != null)
                    {
                        attachmentsByName.Put(name, curAttachment);
                    }
                }

                var contentEncoding = headers.Get("Content-Encoding");
                if (contentEncoding == "gzip")
                {
                    if (name != null)
                    {
                        try {
                            var attachEncoding = document.GetCast <IDictionary <string, object> >("_attachments").
                                                 GetCast <IDictionary <string, object> >(name).GetCast <string>("encoding");
                            if (attachEncoding != "gzip")
                            {
                                Log.W(TAG, "Attachment '{0}' MIME body is gzipped but attachment isn't", name);
                                throw new CouchbaseLiteException(StatusCode.UnsupportedType);
                            }
                        } catch (NullReferenceException) {
                            throw new CouchbaseLiteException(StatusCode.UnsupportedType);
                        }
                    }
                }
                else if (contentEncoding != null)
                {
                    Log.W(TAG, "Received unsupported Content-Encoding '{0}'", contentEncoding);
                    throw new CouchbaseLiteException(StatusCode.UnsupportedType);
                }
            }
        }
示例#4
0
 public void FinishedPart()
 {
     if (jsonBuffer != null)
     {
         ParseJsonBuffer();
     }
     else
     {
         curAttachment.Finish();
         String md5String = curAttachment.MD5DigestString();
         attachmentsByMd5Digest.Put(md5String, curAttachment);
         curAttachment = null;
     }
 }
 public void FinishedPart()
 {
     if (jsonBuffer != null)
     {
         ParseJsonBuffer();
     }
     else
     {
         curAttachment.Finish();
         String sha1String = curAttachment.SHA1DigestString();
         attachmentsBySHA1Digest.Put(sha1String, curAttachment);
         curAttachment = null;
     }
 }
 public void FinishedPart()
 {
     if (jsonBuffer != null)
     {
         ParseJsonBuffer();
     }
     else
     {
         curAttachment.Finish();
         var sha1String = curAttachment.SHA1DigestString();
         Log.To.Sync.V(TAG, "{0} finished attachment #{1}: {2}", this, attachmentsByDigest.Count + 1, curAttachment);
         attachmentsByDigest[sha1String] = curAttachment;
         curAttachment = null;
     }
 }
        // Update the given attachment using the provided info
        private static CouchbaseLiteResponse UpdateAttachment(ICouchbaseListenerContext context, Database db,
                                                              string attachment, string docId, BlobStoreWriter body)
        {
            var castContext      = context as ICouchbaseListenerContext2;
            var source           = castContext != null && !castContext.IsLoopbackRequest ? castContext.Sender : null;
            RevisionInternal rev = db.UpdateAttachment(attachment, body, context.RequestHeaders["Content-Type"], AttachmentEncoding.None,
                                                       docId, (context.GetQueryParam("rev") ?? context.IfMatch()).AsRevID(), source);

            var response = context.CreateResponse();

            response.JsonBody = new Body(new Dictionary <string, object> {
                { "ok", true },
                { "id", rev.DocID },
                { "rev", rev.RevID }
            });
            context.CacheWithEtag(rev.RevID.ToString());
            if (body != null)
            {
                response["Location"] = context.RequestUrl.AbsoluteUri;
            }

            return(response);
        }
        // Update the given attachment using the provided info
        private static CouchbaseLiteResponse UpdateAttachment(ICouchbaseListenerContext context, Database db, 
            string attachment, string docId, BlobStoreWriter body)
        {
            RevisionInternal rev = db.UpdateAttachment(attachment, body, context.RequestHeaders["Content-Type"], AttachmentEncoding.None,
                    docId, context.GetQueryParam("rev") ?? context.IfMatch());

            var response = context.CreateResponse();
            response.JsonBody = new Body(new Dictionary<string, object> {
                { "ok", true },
                { "id", rev.GetDocId() },
                { "rev", rev.GetRevId() }
            });
            context.CacheWithEtag(rev.GetRevId());
            if (body != null) {
                response["Location"] = context.RequestUrl.AbsoluteUri;
            }

            return response;
        }
示例#9
0
        private void RegisterAttachments()
        {
            int numAttachmentsInDoc = 0;
            IDictionary <string, object> attachments = (IDictionary <string, object>)document.Get
                                                           ("_attachments");

            if (attachments == null)
            {
                return;
            }
            foreach (string attachmentName in attachments.Keys)
            {
                IDictionary <string, object> attachment = (IDictionary <string, object>)attachments
                                                          .Get(attachmentName);
                int length = 0;
                if (attachment.ContainsKey("length"))
                {
                    length = ((int)attachment.Get("length"));
                }
                if (attachment.ContainsKey("encoded_length"))
                {
                    length = ((int)attachment.Get("encoded_length"));
                }
                if (attachment.ContainsKey("follows") && ((bool)attachment.Get("follows")) == true)
                {
                    // Check that each attachment in the JSON corresponds to an attachment MIME body.
                    // Look up the attachment by either its MIME Content-Disposition header or MD5 digest:
                    string          digest = (string)attachment.Get("digest");
                    BlobStoreWriter writer = attachmentsByName.Get(attachmentName);
                    if (writer != null)
                    {
                        // Identified the MIME body by the filename in its Disposition header:
                        string actualDigest = writer.MD5DigestString();
                        if (digest != null && !digest.Equals(actualDigest) && !digest.Equals(writer.SHA1DigestString
                                                                                                 ()))
                        {
                            string errMsg = string.Format("Attachment '%s' has incorrect MD5 digest (%s; should be %s)"
                                                          , attachmentName, digest, actualDigest);
                            throw new InvalidOperationException(errMsg);
                        }
                        attachment.Put("digest", actualDigest);
                    }
                    else
                    {
                        if (digest != null)
                        {
                            writer = attachmentsByMd5Digest.Get(digest);
                            if (writer == null)
                            {
                                string errMsg = string.Format("Attachment '%s' does not appear in MIME body (%s; should be %s)"
                                                              , attachmentName);
                                throw new InvalidOperationException(errMsg);
                            }
                        }
                        else
                        {
                            if (attachments.Count == 1 && attachmentsByMd5Digest.Count == 1)
                            {
                                // Else there's only one attachment, so just assume it matches & use it:
                                writer = attachmentsByMd5Digest.Values.GetEnumerator().Next();
                                attachment.Put("digest", writer.MD5DigestString());
                            }
                            else
                            {
                                // No digest metatata, no filename in MIME body; give up:
                                string errMsg = string.Format("Attachment '%s' has no digest metadata; cannot identify MIME body"
                                                              , attachmentName);
                                throw new InvalidOperationException(errMsg);
                            }
                        }
                    }
                    // Check that the length matches:
                    if (writer.GetLength() != length)
                    {
                        string errMsg = string.Format("Attachment '%s' has incorrect length field %d (should be %d)"
                                                      , attachmentName, length, writer.GetLength());
                        throw new InvalidOperationException(errMsg);
                    }
                    ++numAttachmentsInDoc;
                }
                else
                {
                    if (attachment.ContainsKey("data") && length > 1000)
                    {
                        string msg = string.Format("Attachment '%s' sent inline (len=%d).  Large attachments "
                                                   + "should be sent in MIME parts for reduced memory overhead.", attachmentName);
                        Log.W(Database.Tag, msg);
                    }
                }
            }
            if (numAttachmentsInDoc < attachmentsByMd5Digest.Count)
            {
                string msg = string.Format("More MIME bodies (%d) than attachments (%d) ", attachmentsByMd5Digest
                                           .Count, numAttachmentsInDoc);
                throw new InvalidOperationException(msg);
            }
            // hand over the (uninstalled) blobs to the database to remember:
            database.RememberAttachmentWritersForDigests(attachmentsByMd5Digest);
        }
示例#10
0
        // Update the given attachment using the provided info
        private static CouchbaseLiteResponse UpdateAttachment(ICouchbaseListenerContext context, Database db,
                                                              string attachment, string docId, BlobStoreWriter body)
        {
            RevisionInternal rev = db.UpdateAttachment(attachment, body, context.RequestHeaders["Content-Type"], AttachmentEncoding.None,
                                                       docId, context.GetQueryParam("rev") ?? context.IfMatch());

            var response = context.CreateResponse();

            response.JsonBody = new Body(new Dictionary <string, object> {
                { "ok", true },
                { "id", rev.GetDocId() },
                { "rev", rev.GetRevId() }
            });
            context.CacheWithEtag(rev.GetRevId());
            if (body != null)
            {
                response["Location"] = context.RequestUrl.AbsoluteUri;
            }

            return(response);
        }
        // Update the given attachment using the provided info
        private static CouchbaseLiteResponse UpdateAttachment(ICouchbaseListenerContext context, Database db, 
            string attachment, string docId, BlobStoreWriter body)
        {
            var castContext = context as ICouchbaseListenerContext2;
            var source = castContext != null && !castContext.IsLoopbackRequest ? castContext.Sender : null;
            RevisionInternal rev = db.UpdateAttachment(attachment, body, context.RequestHeaders["Content-Type"], AttachmentEncoding.None,
                    docId, (context.GetQueryParam("rev") ?? context.IfMatch()).AsRevID(), source);

            var response = context.CreateResponse();
            response.JsonBody = new Body(new Dictionary<string, object> {
                { "ok", true },
                { "id", rev.DocID },
                { "rev", rev.RevID }
            });
            context.CacheWithEtag(rev.RevID.ToString());
            if (body != null) {
                response["Location"] = context.RequestUrl.AbsoluteUri;
            }

            return response;
        }