/// <summary>
 /// Saves a message attachment to the attachment repository.
 /// </summary>
 /// <param name="attachment">The attachment to save.</param>
 /// <param name="data">The attachment data to save.</param>
 /// <returns>true if the attachment was attached successfully; otherise, false.</returns>
 /// <exception cref="ArgumentNullException"><paramref name="data"/> is null.</exception>
 public bool Save(CmoAttachment attachment, byte[] data)
 {
     return(Save(attachment, new WriteAttachmentEventHandler(delegate(string path)
     {
         /* due to Microsoft Connect bug #486256, we have to upload in chunks smaller than 64MB
          * (http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=486256
          */
         if (data == null)
         {
             throw new ArgumentNullException("data", "Attachment data cannot be null.");
         }
         using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None))
         {
             int offset = 0;
             int count = 33554432;                     // 32MB chunks
             int remaining = data.Length;
             while (remaining > 0)
             {
                 count = Math.Min(count, remaining);
                 fs.Write(data, offset, count);
                 offset += count;
                 remaining -= count;
             }
         }
     })));
 }
 /// <summary>
 /// Deletes a message attachment.
 /// </summary>
 /// <param name="attachment">The attachment to delete.</param>
 /// <returns>true if the attachment was removed successfully; otherwise, false.</returns>
 /// <exception cref="ArgumentException"><paramref name="attachment"/> has an invalid name.</exception>
 /// <exception cref="ArgumentNullException"><paramref name="attachment"/> is null or has a null file name.</exception>
 /// <exception cref="DirectoryNotFoundException">The attachment file path is invalid.</exception>
 /// <exception cref="IOException">An I/O error occurred while opening the file.</exception>
 /// <exception cref="NotSupportedException">The attachment file path is in an invalid format.</exception>
 /// <exception cref="PathTooLongException">The path to the attachment exceeds the system-defined maximum length.</exception>
 /// <exception cref="UnauthorizedAccessException">The attachment path specifies a read-only file or directory, or the operation is not supported on the current platform, or the caller does not have the required permission.</exception>
 public bool Delete(CmoAttachment attachment)
 {
     if (attachment != null)
     {
         string path = this.GetPath(attachment);
         if (File.Exists(path))
         {
             try
             {
                 // unmark as read-only
                 FileAttributes attributes = File.GetAttributes(path);
                 if ((attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
                 {
                     File.SetAttributes(path, attributes & ~FileAttributes.ReadOnly);
                 }
                 File.Delete(path);
                 return(true);
             }
             catch
             {
             }
         }
     }
     return(false);
 }
 /// <summary>
 /// Retrieves the full system file path to a file attachment.
 /// </summary>
 /// <param name="attachment">The attachment to find.</param>
 /// <returns>The full system file path to the attachment.</returns>
 /// <exception cref="ArgumentNullException"><paramref name="attachment"/> is null.</exception>
 internal string GetPath(CmoAttachment attachment)
 {
     if (attachment == null)
     {
         throw new ArgumentNullException("attachment", "The attachment cannot be null.");
     }
     return(string.Format("{0}\\{1}_{2}", GetMessageFolderName(attachment.CandidateID, attachment.MessageID), attachment.ID, attachment.FileName));
 }
        /// <summary>
        /// Saves a message attachment to the attachment repository.
        /// </summary>
        /// <param name="attachment">The attachment to save.</param>
        /// <param name="writeAttachment">The delegate method to use for writing the attachment to disk.</param>
        /// <returns>true if the attachment was attached successfully; otherise, false.</returns>
        /// <exception cref="ArgumentException"><paramref name="attachment"/> has an invalid name.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="attachment"/> is null or has a null file name, or <paramref name="writeAttachment"/> is not defined.</exception>
        /// <exception cref="DirectoryNotFoundException">The attachment file path is invalid.</exception>
        /// <exception cref="FileNotFoundException">The attachment file was not found.</exception>
        /// <exception cref="IOException">An I/O error occurred while opening the file.</exception>
        /// <exception cref="NotSupportedException">The attachment file path is in an invalid format.</exception>
        /// <exception cref="PathTooLongException">The path to the attachment exceeds the system-defined maximum length.</exception>
        /// <exception cref="SecurityException">The caller does not have the required permission.</exception>
        /// <exception cref="UnauthorizedAccessException">The attachment path specifies a read-only file or directory, or the operation is not supported on the current platform, or the caller does not have the required permission.</exception>
        private bool Save(CmoAttachment attachment, WriteAttachmentEventHandler writeAttachment)
        {
            if (attachment == null || writeAttachment == null)
            {
                return(false);
            }
            string path = GetPath(attachment);

            if (File.Exists(path))
            {
                return(false);
            }
            string folder = new FileInfo(path).DirectoryName;

            if (!Directory.Exists(folder))
            {
                Directory.CreateDirectory(folder);
            }
            writeAttachment(path);
            File.SetAttributes(path, File.GetAttributes(path) & FileAttributes.ReadOnly);
            return(true);
        }
 /// <summary>
 /// Retrieves a message attachment as a stream sequence of raw bytes.
 /// </summary>
 /// <param name="attachment">The attachment to get.</param>
 /// <returns>A <see cref="Stream"/> object representing the raw attachment data.</returns>
 /// <exception cref="ArgumentException"><paramref name="attachment"/> has an invalid name.</exception>
 /// <exception cref="ArgumentNullException"><paramref name="attachment"/> is null or has a null file name.</exception>
 /// <exception cref="DirectoryNotFoundException">The attachment file path is invalid.</exception>
 /// <exception cref="FileNotFoundException">The attachment file was not found.</exception>
 /// <exception cref="NotSupportedException">The attachment file path is in an invalid format.</exception>
 /// <exception cref="PathTooLongException">The path to the attachment exceeds the system-defined maximum length.</exception>
 /// <exception cref="UnauthorizedAccessException">The attachment path specifies a directory, or the caller does not have the required permission.</exception>
 internal Stream GetData(CmoAttachment attachment)
 {
     return(File.OpenRead(GetPath(attachment)));
 }
 /// <summary>
 /// Saves a message attachment to the attachment repository.
 /// </summary>
 /// <param name="attachment">The attachment to save.</param>
 /// <param name="contents">The attachment data to save.</param>
 /// <returns>true if the attachment was attached successfully; otherise, false.</returns>
 /// <exception cref="ArgumentException"><paramref name="attachment"/> has an invalid name.</exception>
 /// <exception cref="ArgumentNullException"><paramref name="attachment"/> is null or has a null file name.</exception>
 /// <exception cref="DirectoryNotFoundException">The attachment file path is invalid.</exception>
 /// <exception cref="FileNotFoundException">The attachment file was not found.</exception>
 /// <exception cref="IOException">An I/O error occurred while opening the file.</exception>
 /// <exception cref="NotSupportedException">The attachment file path is in an invalid format.</exception>
 /// <exception cref="PathTooLongException">The path to the attachment exceeds the system-defined maximum length.</exception>
 /// <exception cref="SecurityException">The caller does not have the required permission.</exception>
 /// <exception cref="UnauthorizedAccessException">The attachment path specifies a read-only file or directory, or the operation is not supported on the current platform, or the caller does not have the required permission.</exception>
 public bool Save(CmoAttachment attachment, string contents)
 {
     return(Save(attachment, new WriteAttachmentEventHandler(delegate(string path) { File.WriteAllText(path, contents); })));
 }