private void UpdateHash(HashAlgorithm hash, long length, UpdateChecksum update) { HashAlgorithmReuse reuse = hash as HashAlgorithmReuse; if (reuse != null && update != null) { using (HashAlgorithm hashReuse = (HashAlgorithm)reuse.Clone()) { hashReuse.TransformFinalBlock(new byte[0], 0, 0); update(hashReuse.Hash, length); } } }
/// <summary> /// Uploads the localFileStream to remoteDocument. /// </summary> /// <returns> /// The new CMIS document. /// </returns> /// <param name='remoteDocument'> /// Remote document where the local content should be uploaded to. /// </param> /// <param name='localFileStream'> /// Local file stream. /// </param> /// <param name='transmission'> /// Transmission status where the uploader should report its uploading status. /// </param> /// <param name='hashAlg'> /// Hash alg which should be used to calculate a checksum over the uploaded content. /// </param> /// <param name='overwrite'> /// If true, the local content will overwrite the existing content. /// </param> /// <exception cref="CmisSync.Lib.Tasks.UploadFailedException">If upload fails</exception> public virtual IDocument UploadFile( IDocument remoteDocument, Stream localFileStream, Transmission transmission, HashAlgorithm hashAlg, bool overwrite = true, UpdateChecksum update = null) { if (remoteDocument == null) { throw new ArgumentException("remoteDocument can not be null"); } if (localFileStream == null) { throw new ArgumentException("localFileStream can not be null"); } if (transmission == null) { throw new ArgumentException("status can not be null"); } if (hashAlg == null) { throw new ArgumentException("hashAlg can not be null"); } using (NonClosingHashStream hashstream = new NonClosingHashStream(localFileStream, hashAlg, CryptoStreamMode.Read)) using (var transmissionStream = transmission.CreateStream(hashstream)) { ContentStream contentStream = new ContentStream(); contentStream.FileName = remoteDocument.Name; contentStream.MimeType = Cmis.MimeType.GetMIMEType(contentStream.FileName); contentStream.Stream = transmissionStream; try { remoteDocument.SetContentStream(contentStream, overwrite, true); } catch (Exception e) { throw new UploadFailedException(e, remoteDocument); } } hashAlg.TransformFinalBlock(new byte[0], 0, 0); return(remoteDocument); }
/// <summary> /// Uploads the localFileStream to remoteDocument. /// </summary> /// <returns> /// The new CMIS document. /// </returns> /// <param name='remoteDocument'> /// Remote document where the local content should be uploaded to. /// </param> /// <param name='localFileStream'> /// Local file stream. /// </param> /// <param name='transmission'> /// Transmission status where the uploader should report its uploading status. /// </param> /// <param name='hashAlg'> /// Hash alg which should be used to calculate a checksum over the uploaded content. /// </param> /// <param name='overwrite'> /// If true, the local content will overwrite the existing content. /// </param> /// <exception cref="CmisSync.Lib.Tasks.UploadFailedException">If upload fails</exception> public virtual IDocument UploadFile( IDocument remoteDocument, Stream localFileStream, Transmission transmission, HashAlgorithm hashAlg, bool overwrite = true, UpdateChecksum update = null) { if (remoteDocument == null) { throw new ArgumentException("remoteDocument can not be null"); } if (localFileStream == null) { throw new ArgumentException("localFileStream can not be null"); } if (transmission == null) { throw new ArgumentException("status can not be null"); } if (hashAlg == null) { throw new ArgumentException("hashAlg can not be null"); } using(NonClosingHashStream hashstream = new NonClosingHashStream(localFileStream, hashAlg, CryptoStreamMode.Read)) using(var transmissionStream = transmission.CreateStream(hashstream)) { ContentStream contentStream = new ContentStream(); contentStream.FileName = remoteDocument.Name; contentStream.MimeType = Cmis.MimeType.GetMIMEType(contentStream.FileName); contentStream.Stream = transmissionStream; try { remoteDocument.SetContentStream(contentStream, overwrite, true); } catch(Exception e) { throw new UploadFailedException(e, remoteDocument); } } hashAlg.TransformFinalBlock(new byte[0], 0, 0); return remoteDocument; }
/// <summary> /// Downloads the file and returns the SHA-1 hash of the content of the saved file /// </summary> /// <param name="remoteDocument">Remote document.</param> /// <param name="localFileStream">Local taget file stream.</param> /// <param name="transmission">Transmission status.</param> /// <param name="hashAlg">Hash algoritm, which should be used to calculate hash of the uploaded stream content</param> /// <param name="update">Not or not yet used</param> /// <exception cref="IOException">On any disc or network io exception</exception> /// <exception cref="DisposeException">If the remote object has been disposed before the dowload is finished</exception> /// <exception cref="AbortException">If download is aborted</exception> /// <exception cref="CmisException">On exceptions thrown by the CMIS Server/Client</exception> public void DownloadFile( IDocument remoteDocument, Stream localFileStream, Transmission transmission, HashAlgorithm hashAlg, UpdateChecksum update = null) { { byte[] buffer = new byte[8 * 1024]; int len; while ((len = localFileStream.Read(buffer, 0, buffer.Length)) > 0) { hashAlg.TransformBlock(buffer, 0, len, buffer, 0); } } long?fileLength = remoteDocument.ContentStreamLength; // Download content if exists if (fileLength > 0) { long offset = localFileStream.Position; long remainingBytes = (fileLength != null) ? (long)fileLength - offset : this.ChunkSize; try { do { offset += this.DownloadNextChunk(remoteDocument, offset, remainingBytes, transmission, localFileStream, hashAlg); } while(fileLength == null); } catch (DotCMIS.Exceptions.CmisConstraintException) { } } else { transmission.Position = 0; transmission.Length = 0; } hashAlg.TransformFinalBlock(new byte[0], 0, 0); }
/// <summary> /// Downloads the file and returns the SHA-1 hash of the content of the saved file /// </summary> /// <param name="remoteDocument">Remote document.</param> /// <param name="localFileStream">Local taget file stream.</param> /// <param name="transmission">Transmission status.</param> /// <param name="hashAlg">Hash algoritm, which should be used to calculate hash of the uploaded stream content</param> /// <exception cref="IOException">On any disc or network io exception</exception> /// <exception cref="DisposeException">If the remote object has been disposed before the dowload is finished</exception> /// <exception cref="AbortException">If download is aborted</exception> /// <exception cref="CmisException">On exceptions thrown by the CMIS Server/Client</exception> public void DownloadFile( IDocument remoteDocument, Stream localFileStream, Transmission transmission, HashAlgorithm hashAlg, UpdateChecksum update = null) { byte[] buffer = new byte[8 * 1024]; int len; if (localFileStream.Length > 0) { localFileStream.Seek(0, SeekOrigin.Begin); while ((len = localFileStream.Read(buffer, 0, buffer.Length)) > 0) { hashAlg.TransformBlock(buffer, 0, len, buffer, 0); } } long offset = localFileStream.Position; long? fileLength = remoteDocument.ContentStreamLength; if (fileLength <= offset) { transmission.Length = fileLength.GetValueOrDefault(); transmission.Position = offset; hashAlg.TransformFinalBlock(new byte[0], 0, 0); return; } DotCMIS.Data.IContentStream contentStream = null; if (offset > 0) { long remainingBytes = (long)fileLength - offset; transmission.Length = remoteDocument.ContentStreamLength; transmission.Position = offset; contentStream = remoteDocument.GetContentStream(remoteDocument.ContentStreamId, offset, remainingBytes); } else { contentStream = remoteDocument.GetContentStream(); } using (var transmissionStream = transmission.CreateStream(localFileStream)) using (CryptoStream hashstream = new CryptoStream(transmissionStream, hashAlg, CryptoStreamMode.Write)) using (Stream remoteStream = contentStream != null ? contentStream.Stream : new MemoryStream(0)) { transmission.Length = remoteDocument.ContentStreamLength; transmission.Position = offset; int written = 0; while ((len = remoteStream.Read(buffer, 0, buffer.Length)) > 0) { lock (this.disposeLock) { if (this.disposed) { transmission.Status = TransmissionStatus.ABORTED; throw new ObjectDisposedException(transmission.Path); } try { hashstream.Write(buffer, 0, len); hashstream.Flush(); written += len; } catch (Exception) { this.UpdateHash(hashAlg, localFileStream.Length, update); throw; } if (written >= 1024 * 1024) { this.UpdateHash(hashAlg, localFileStream.Length, update); written = 0; } } } if (written > 0) { this.UpdateHash(hashAlg, localFileStream.Length, update); } } }
/// <summary> /// Uploads the file. /// Resumes an upload if the given localFileStream.Position is larger than zero. /// </summary> /// <returns> /// The new CMIS document. /// </returns> /// <param name='remoteDocument'> /// Remote document where the local content should be uploaded to. /// </param> /// <param name='localFileStream'> /// Local file stream. /// </param> /// <param name='transmission'> /// Transmission status where the uploader should report its uploading status. /// </param> /// <param name='hashAlg'> /// Hash alg which should be used to calculate a checksum over the uploaded content. /// </param> /// <param name='overwrite'> /// If true, the local content will overwrite the existing content. /// </param> /// <param name="update">Is called on every new chunk, if not <c>null</c>.</param> /// <exception cref="CmisSync.Lib.Tasks.UploadFailedException"> /// Contains the last successful remote document state. This is needed for continue a failed upload. /// </exception> public override IDocument UploadFile( IDocument remoteDocument, Stream localFileStream, Transmission transmission, HashAlgorithm hashAlg, bool overwrite = true, UpdateChecksum update = null) { IDocument result = remoteDocument; for (long offset = localFileStream.Position; offset < localFileStream.Length; offset += this.ChunkSize) { bool isFirstChunk = offset == 0; bool isLastChunk = (offset + this.ChunkSize) >= localFileStream.Length; using (var hashstream = new NonClosingHashStream(localFileStream, hashAlg, CryptoStreamMode.Read)) using (var chunkstream = new ChunkedStream(hashstream, this.ChunkSize)) using (var offsetstream = new OffsetStream(chunkstream, offset)) using (var transmissionStream = transmission.CreateStream(offsetstream)) { transmission.Length = localFileStream.Length; transmission.Position = offset; chunkstream.ChunkPosition = offset; ContentStream contentStream = new ContentStream(); contentStream.FileName = remoteDocument.Name; contentStream.MimeType = Cmis.MimeType.GetMIMEType(remoteDocument.Name); if (isLastChunk) { contentStream.Length = localFileStream.Length - offset; } else { contentStream.Length = this.ChunkSize; } contentStream.Stream = transmissionStream; try { if (isFirstChunk && result.ContentStreamId != null && overwrite) { result.DeleteContentStream(true); } result.AppendContentStream(contentStream, isLastChunk, true); HashAlgorithmReuse reuse = hashAlg as HashAlgorithmReuse; if (reuse != null && update != null) { using (HashAlgorithm hash = (HashAlgorithm)reuse.Clone()) { hash.TransformFinalBlock(new byte[0], 0, 0); update(hash.Hash, result.ContentStreamLength.GetValueOrDefault()); } } } catch (Exception e) { if (e is FileTransmission.AbortException) { throw; } if (e.InnerException is FileTransmission.AbortException) { throw e.InnerException; } throw new UploadFailedException(e, result); } } } hashAlg.TransformFinalBlock(new byte[0], 0, 0); return result; }
/// <summary> /// Downloads the file and returns the SHA-1 hash of the content of the saved file /// </summary> /// <param name="remoteDocument">Remote document.</param> /// <param name="localFileStream">Local taget file stream.</param> /// <param name="transmission">Transmission status.</param> /// <param name="hashAlg">Hash algoritm, which should be used to calculate hash of the uploaded stream content</param> /// <param name="update">Not or not yet used</param> /// <exception cref="IOException">On any disc or network io exception</exception> /// <exception cref="DisposeException">If the remote object has been disposed before the dowload is finished</exception> /// <exception cref="AbortException">If download is aborted</exception> /// <exception cref="CmisException">On exceptions thrown by the CMIS Server/Client</exception> public void DownloadFile( IDocument remoteDocument, Stream localFileStream, Transmission transmission, HashAlgorithm hashAlg, UpdateChecksum update = null) { { byte[] buffer = new byte[8 * 1024]; int len; while ((len = localFileStream.Read(buffer, 0, buffer.Length)) > 0) { hashAlg.TransformBlock(buffer, 0, len, buffer, 0); } } long? fileLength = remoteDocument.ContentStreamLength; // Download content if exists if (fileLength > 0) { long offset = localFileStream.Position; long remainingBytes = (fileLength != null) ? (long)fileLength - offset : this.ChunkSize; try { do { offset += this.DownloadNextChunk(remoteDocument, offset, remainingBytes, transmission, localFileStream, hashAlg); } while(fileLength == null); } catch (DotCMIS.Exceptions.CmisConstraintException) { } } else { transmission.Position = 0; transmission.Length = 0; } hashAlg.TransformFinalBlock(new byte[0], 0, 0); }
/// <summary> /// Downloads the file and returns the SHA-1 hash of the content of the saved file /// </summary> /// <param name="remoteDocument">Remote document.</param> /// <param name="localFileStream">Local taget file stream.</param> /// <param name="transmission">Transmission status.</param> /// <param name="hashAlg">Hash algoritm, which should be used to calculate hash of the uploaded stream content</param> /// <exception cref="IOException">On any disc or network io exception</exception> /// <exception cref="DisposeException">If the remote object has been disposed before the dowload is finished</exception> /// <exception cref="AbortException">If download is aborted</exception> /// <exception cref="CmisException">On exceptions thrown by the CMIS Server/Client</exception> public void DownloadFile( IDocument remoteDocument, Stream localFileStream, Transmission transmission, HashAlgorithm hashAlg, UpdateChecksum update = null) { byte[] buffer = new byte[8 * 1024]; int len; if (localFileStream.Length > 0) { localFileStream.Seek(0, SeekOrigin.Begin); while ((len = localFileStream.Read(buffer, 0, buffer.Length)) > 0) { hashAlg.TransformBlock(buffer, 0, len, buffer, 0); } } long offset = localFileStream.Position; long?fileLength = remoteDocument.ContentStreamLength; if (fileLength <= offset) { transmission.Length = fileLength.GetValueOrDefault(); transmission.Position = offset; hashAlg.TransformFinalBlock(new byte[0], 0, 0); return; } DotCMIS.Data.IContentStream contentStream = null; if (offset > 0) { long remainingBytes = (long)fileLength - offset; transmission.Length = remoteDocument.ContentStreamLength; transmission.Position = offset; contentStream = remoteDocument.GetContentStream(remoteDocument.ContentStreamId, offset, remainingBytes); } else { contentStream = remoteDocument.GetContentStream(); } using (var transmissionStream = transmission.CreateStream(localFileStream)) using (CryptoStream hashstream = new CryptoStream(transmissionStream, hashAlg, CryptoStreamMode.Write)) using (Stream remoteStream = contentStream != null ? contentStream.Stream : new MemoryStream(0)) { transmission.Length = remoteDocument.ContentStreamLength; transmission.Position = offset; int written = 0; while ((len = remoteStream.Read(buffer, 0, buffer.Length)) > 0) { lock (this.disposeLock) { if (this.disposed) { transmission.Status = TransmissionStatus.ABORTED; throw new ObjectDisposedException(transmission.Path); } try { hashstream.Write(buffer, 0, len); hashstream.Flush(); written += len; } catch (Exception) { this.UpdateHash(hashAlg, localFileStream.Length, update); throw; } if (written >= 1024 * 1024) { this.UpdateHash(hashAlg, localFileStream.Length, update); written = 0; } } } if (written > 0) { this.UpdateHash(hashAlg, localFileStream.Length, update); } } }
/// <summary> /// Uploads the file. /// Resumes an upload if the given localFileStream.Position is larger than zero. /// </summary> /// <returns> /// The new CMIS document. /// </returns> /// <param name='remoteDocument'> /// Remote document where the local content should be uploaded to. /// </param> /// <param name='localFileStream'> /// Local file stream. /// </param> /// <param name='transmission'> /// Transmission status where the uploader should report its uploading status. /// </param> /// <param name='hashAlg'> /// Hash alg which should be used to calculate a checksum over the uploaded content. /// </param> /// <param name='overwrite'> /// If true, the local content will overwrite the existing content. /// </param> /// <param name="update">Is called on every new chunk, if not <c>null</c>.</param> /// <exception cref="CmisSync.Lib.Tasks.UploadFailedException"> /// Contains the last successful remote document state. This is needed for continue a failed upload. /// </exception> public override IDocument UploadFile( IDocument remoteDocument, Stream localFileStream, Transmission transmission, HashAlgorithm hashAlg, bool overwrite = true, UpdateChecksum update = null) { IDocument result = remoteDocument; for (long offset = localFileStream.Position; offset < localFileStream.Length; offset += this.ChunkSize) { bool isFirstChunk = offset == 0; bool isLastChunk = (offset + this.ChunkSize) >= localFileStream.Length; using (var hashstream = new NonClosingHashStream(localFileStream, hashAlg, CryptoStreamMode.Read)) using (var chunkstream = new ChunkedStream(hashstream, this.ChunkSize)) using (var offsetstream = new OffsetStream(chunkstream, offset)) using (var transmissionStream = transmission.CreateStream(offsetstream)) { transmission.Length = localFileStream.Length; transmission.Position = offset; chunkstream.ChunkPosition = offset; ContentStream contentStream = new ContentStream(); contentStream.FileName = remoteDocument.Name; contentStream.MimeType = Cmis.MimeType.GetMIMEType(remoteDocument.Name); if (isLastChunk) { contentStream.Length = localFileStream.Length - offset; } else { contentStream.Length = this.ChunkSize; } contentStream.Stream = transmissionStream; try { if (isFirstChunk && result.ContentStreamId != null && overwrite) { result.DeleteContentStream(true); } result.AppendContentStream(contentStream, isLastChunk, true); HashAlgorithmReuse reuse = hashAlg as HashAlgorithmReuse; if (reuse != null && update != null) { using (HashAlgorithm hash = (HashAlgorithm)reuse.Clone()) { hash.TransformFinalBlock(new byte[0], 0, 0); update(hash.Hash, result.ContentStreamLength.GetValueOrDefault()); } } } catch (Exception e) { if (e is FileTransmission.AbortException) { throw; } if (e.InnerException is FileTransmission.AbortException) { throw e.InnerException; } throw new UploadFailedException(e, result); } } } hashAlg.TransformFinalBlock(new byte[0], 0, 0); return(result); }