public static async Task UploadAttachment(this Vault vault, PasswordRecord record, IAttachmentUploadTask uploadTask) { var fileStream = uploadTask.Stream; if (fileStream == null) { throw new KeeperInvalidParameter("Vault::UploadAttachment", "uploadTask", "GetStream()", "null"); } var thumbStream = uploadTask.Thumbnail?.Stream; var command = new RequestUploadCommand(); command.fileCount = 1; command.thumbnailCount = thumbStream != null ? 1 : 0; var rs = await vault.Auth.ExecuteAuthCommand <RequestUploadCommand, RequestUpoadResponse>(command); if (rs.fileUploads == null || rs.fileUploads.Length < 1) { throw new KeeperInvalidParameter("Vault::UploadAttachment", "request_upload", "file_uploads", "empty"); } UploadParameters fileUpload = rs.fileUploads[0]; UploadParameters thumbUpload = null; if (rs.thumbnailUploads != null && rs.thumbnailUploads.Length > 0) { thumbUpload = rs.thumbnailUploads[0]; } var key = CryptoUtils.GenerateEncryptionKey(); var atta = new AttachmentFile { Id = fileUpload.fileID, Name = uploadTask.Name, Title = uploadTask.Title, Key = key.Base64UrlEncode(), Type = uploadTask.MimeType, LastModified = DateTimeOffset.Now, }; var transform = new EncryptAesV1Transform(key); using (var cryptoStream = new CryptoStream(fileStream, transform, CryptoStreamMode.Read)) { await UploadSingleFile(fileUpload, cryptoStream); atta.Size = transform.EncryptedBytes; } if (thumbUpload != null) { try { transform = new EncryptAesV1Transform(key); using (var cryptoStream = new CryptoStream(thumbStream, transform, CryptoStreamMode.Read)) { await UploadSingleFile(thumbUpload, cryptoStream); } var thumbnail = new AttachmentFileThumb { Id = thumbUpload.fileID, Type = uploadTask.Thumbnail.MimeType, Size = uploadTask.Thumbnail.Size }; var ts = new AttachmentFileThumb[] { thumbnail }; if (atta.Thumbnails == null) { atta.Thumbnails = ts; } else { atta.Thumbnails = atta.Thumbnails.Concat(ts).ToArray(); } } catch (Exception e) { Trace.TraceError("Upload Thumbname: {0}: \"{1}\"", e.GetType().Name, e.Message); } } record.Attachments.Add(atta); }
internal static async Task UploadSingleFile(UploadParameters upload, Stream source) { string boundary = "----------" + DateTime.Now.Ticks.ToString("x"); byte[] boundaryBytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary); var request = (HttpWebRequest)WebRequest.Create(new Uri(upload.url)); request.Method = "POST"; request.ContentType = "multipart/form-data; boundary=" + boundary; using (var requestStream = await Task.Factory.FromAsync(request.BeginGetRequestStream, request.EndGetRequestStream, null)) { string parameterTemplate = "\r\nContent-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}"; if (upload.parameters != null) { foreach (var pair in upload.parameters) { await requestStream.WriteAsync(boundaryBytes, 0, boundaryBytes.Length); string formitem = string.Format(parameterTemplate, pair.Key, pair.Value); byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem); requestStream.Write(formitembytes, 0, formitembytes.Length); } } await requestStream.WriteAsync(boundaryBytes, 0, boundaryBytes.Length); string fileTemplate = "\r\nContent-Disposition: form-data; name=\"{0}\"\r\nContent-Type: application/octet-stream\r\n\r\n"; var fileItem = string.Format(fileTemplate, upload.fileParameter); var fileBytes = Encoding.UTF8.GetBytes(fileItem); await requestStream.WriteAsync(fileBytes, 0, fileBytes.Length); await source.CopyToAsync(requestStream); await requestStream.WriteAsync(boundaryBytes, 0, boundaryBytes.Length); var trailer = Encoding.ASCII.GetBytes("--\r\n"); await requestStream.WriteAsync(trailer, 0, trailer.Length); } HttpWebResponse response; try { response = (HttpWebResponse)await Task.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null); if ((int)response.StatusCode != upload.successStatusCode) { throw new KeeperInvalidParameter("Vault::UploadSingleFile", "StatusCode", response.StatusCode.ToString(), "not success"); } } catch (WebException e) { response = (HttpWebResponse)e.Response; if (response.ContentType == "application/xml") { using (var stream = new MemoryStream()) { await response.GetResponseStream().CopyToAsync(stream); string responseText = Encoding.UTF8.GetString(stream.ToArray()); Trace.TraceError(responseText); } } throw e; } }