/// <summary> /// Process a ZIP file that is embedded within the parent ZIP file. Its contents are extracted and turned into /// albums and media objects just like items in the parent ZIP file. /// </summary> /// <param name="zipFile">A reference to a ZIP file contained within the parent ZIP file. Notice that we don't do /// anything with this parameter other than verify that its extension is "ZIP". That's because we actually extract /// the file from the parent ZIP file by calling the ExtractFileFromZipStream method, which extracts the file from /// the class-level member variable _zipStream</param> /// <param name="parentAlbum">The album that should contain the top-level directories and files found in the ZIP /// file.</param> private void ExtractEmbeddedZipFile(ZipEntry zipFile, IAlbum parentAlbum) { #region Validation if (!Path.GetExtension(zipFile.Name).Equals(".zip", StringComparison.OrdinalIgnoreCase)) { throw new ArgumentException(String.Concat("The zipFile parameter of the method ExtractEmbeddedZipFile in class ZipUtility must be a ZIP file. Instead, it had the file extension ", Path.GetExtension(zipFile.Name), ".")); } if (parentAlbum == null) { throw new ArgumentNullException("parentAlbum"); } #endregion string filepath = Path.Combine(parentAlbum.FullPhysicalPathOnDisk, Guid.NewGuid().ToString("N") + ".zip"); try { ExtractFileFromZipStream(filepath); using (ZipUtility zip = new ZipUtility(this._userName, this._roles)) { this._skippedFiles.AddRange(zip.ExtractZipFile(new FileInfo(filepath).OpenRead(), parentAlbum, true)); } } finally { File.Delete(filepath); } }
/// <summary> /// Process a ZIP file that is embedded within the parent ZIP file. Its contents are extracted and turned into /// albums and media objects just like items in the parent ZIP file. /// </summary> /// <param name="zipFile">A reference to a ZIP file contained within the parent ZIP file. Notice that we don't do /// anything with this parameter other than verify that its extension is "ZIP". That's because we actually extract /// the file from the parent ZIP file by calling the ExtractMediaObjectFile method, which extracts the file from /// the class-level member variable _zipStream</param> /// <param name="parentAlbum">The album that should contain the top-level directories and files found in the ZIP /// file.</param> private void ExtractEmbeddedZipFile(ZipEntry zipFile, IAlbum parentAlbum) { #region Validation if (Path.GetExtension(zipFile.Name).ToUpperInvariant() != ".ZIP") { throw new ArgumentException(String.Concat("The zipFile parameter of the method ExtractEmbeddedZipFile in class ZipUtility must be a ZIP file. Instead, it had the file extension ", Path.GetExtension(zipFile.Name), ".")); } if (parentAlbum == null) { throw new ArgumentNullException("parentAlbum"); } #endregion string filepath = Path.Combine(parentAlbum.FullPhysicalPathOnDisk, Guid.NewGuid().ToString("N") + ".config"); try { ExtractMediaObjectFile(filepath); using (ZipUtility zip = new ZipUtility(this._userName, this._roles)) { this._skippedFiles.AddRange(zip.ExtractZipFile(new FileInfo(filepath).OpenRead(), parentAlbum, true)); } } finally { File.Delete(filepath); } }
private static List<ActionResult> CreateMediaObjectFromFile(AddMediaObjectSettings options) { string sourceFilePath = Path.Combine(AppSetting.Instance.PhysicalApplicationPath, GlobalConstants.TempUploadDirectory, options.FileNameOnServer); try { IAlbum album = AlbumController.LoadAlbumInstance(options.AlbumId, true); if ((Path.GetExtension(options.FileName).Equals(".zip", StringComparison.OrdinalIgnoreCase)) && (options.ExtractZipFile)) { // Extract the files from the zipped file. using (ZipUtility zip = new ZipUtility(Utils.UserName, RoleController.GetGalleryServerRolesForUser())) { using (FileStream fs = new FileStream(sourceFilePath, FileMode.Open, FileAccess.Read)) { return zip.ExtractZipFile(fs, album, options.DiscardOriginalFile); } } } else { string albumPhysicalPath = album.FullPhysicalPathOnDisk; string filename = HelperFunctions.ValidateFileName(albumPhysicalPath, options.FileName); string filepath = Path.Combine(albumPhysicalPath, filename); MoveFile(filepath, sourceFilePath); ActionResult result = CreateMediaObject(filepath, album, options); return new List<ActionResult>() { result }; } } catch (Exception ex) { AppErrorController.LogError(ex); return new List<ActionResult>() { new ActionResult() { Title = options.FileName, Status = ActionResultStatus.Error, Message = "The event log may have additional details." } }; } finally { try { // If the file still exists in the temp directory, delete it. Typically this happens when we've // extracted the contents of a zip file (since other files will have already been moved to the dest album.) if (File.Exists(sourceFilePath)) { File.Delete(sourceFilePath); } } catch (IOException) { } // Ignore an error; not a big deal if it continues to exist in the temp directory catch (UnauthorizedAccessException) { } // Ignore an error; not a big deal if it continues to exist in the temp directory } }
private void BuildAndSendZipFile(List<int> albumIds, List<int> mediaObjectIds) { IMimeType mimeType = Factory.LoadMimeType("dummy.zip"); string zipFilename = Utils.UrlEncode("Media Files".Replace(" ", "_")); using (ZipUtility zip = new ZipUtility(Utils.UserName, GetGalleryServerRolesForUser())) { int bufferSize = AppSetting.Instance.MediaObjectDownloadBufferSize; byte[] buffer = new byte[bufferSize]; Stream stream = null; try { // Create an in-memory ZIP file. stream = zip.CreateZipStream(this.GetAlbumId(), albumIds, mediaObjectIds, GetImageSize()); // Send to user. Response.AddHeader("Content-Disposition", "attachment; filename=" + zipFilename + ".zip"); Response.Clear(); Response.ContentType = (mimeType != null ? mimeType.FullType : "application/octet-stream"); Response.Buffer = false; stream.Position = 0; int byteCount; while ((byteCount = stream.Read(buffer, 0, buffer.Length)) > 0) { if (Response.IsClientConnected) { Response.OutputStream.Write(buffer, 0, byteCount); Response.Flush(); } else { return; } } } finally { if (stream != null) stream.Close(); Response.End(); } } }
/// <summary> /// Adds the uploaded files to the gallery. This method is called when the application is operating under full trust. In this case, /// the ComponentArt Upload control is used. The logic is nearly identical to that in AddUploadedFilesLessThanFullTrust - the only /// differences are syntax differences arising from the different file upload control. /// </summary> /// <param name="files">The files to add to the gallery.</param> private void AddUploadedFilesForFullTrust(UploadedFileInfoCollection files) { // Clear the list of hash keys so we're starting with a fresh load from the data store. try { MediaObjectHashKeys.Clear(); string albumPhysicalPath = this.GetAlbum().FullPhysicalPathOnDisk; HelperFunctions.BeginTransaction(); UploadedFileInfo[] fileInfos = new UploadedFileInfo[files.Count]; files.CopyTo(fileInfos, 0); Array.Reverse(fileInfos); foreach (UploadedFileInfo file in fileInfos) { if (String.IsNullOrEmpty(file.FileName)) continue; if ((System.IO.Path.GetExtension(file.FileName).ToUpperInvariant() == ".ZIP") && (!chkDoNotExtractZipFile.Checked)) { #region Extract the files from the zipped file. lock (file) { if (File.Exists(file.TempFileName)) { string userName = (String.IsNullOrEmpty(User.Identity.Name) ? "Anonymous" : User.Identity.Name); using (ZipUtility zip = new ZipUtility(userName, WebsiteController.GetRolesForUser(), User.Identity.IsAuthenticated)) { this._skippedFiles.AddRange(zip.ExtractZipFile(file.GetStream(), this.GetAlbum())); } } else { // When one of the files causes an OutOfMemoryException, this can cause the other files to disappear from the // temp upload directory. This seems to be an issue with the ComponentArt Upload control, since this does not // seem to happen with the ASP.NET FileUpload control. If the file doesn't exist, make a note of it and move on // to the next one. this._skippedFiles.Add(new KeyValuePair<string, string>(file.FileName, Resources.GalleryServerPro.Task_Add_Objects_Uploaded_File_Does_Not_Exist_Msg)); continue; // Skip to the next file. } } #endregion } else { #region Add the file string filename = HelperFunctions.ValidateFileName(albumPhysicalPath, file.FileName); string filepath = Path.Combine(albumPhysicalPath, filename); #if DEBUG TechInfoSystems.TracingTools.Tools.MarkSpot(string.Format(CultureInfo.CurrentCulture, "Attempting to move file {0} to {1}...", file.FileName, filepath)); #endif lock (file) { if (File.Exists(file.TempFileName)) { file.SaveAs(filepath); } else { // When one of the files causes an OutOfMemoryException, this can cause the other files to disappear from the // temp upload directory. This seems to be an issue with the ComponentArt Upload control, since this does not // seem to happen with the ASP.NET FileUpload control. If the file doesn't exist, make a note of it and move on // to the next one. this._skippedFiles.Add(new KeyValuePair<string, string>(file.FileName, Resources.GalleryServerPro.Task_Add_Objects_Uploaded_File_Does_Not_Exist_Msg)); continue; // Skip to the next file. } } try { IGalleryObject go = Factory.CreateMediaObjectInstance(filepath, this.GetAlbum()); WebsiteController.SaveGalleryObject(go); } catch (UnsupportedMediaObjectTypeException ex) { File.Delete(filepath); this._skippedFiles.Add(new KeyValuePair<string, string>(filename, ex.Message)); } #endregion } } HelperFunctions.CommitTransaction(); } catch { HelperFunctions.RollbackTransaction(); throw; } finally { // Delete the uploaded temporary files, as by this time they have been saved to the destination directory. foreach (UploadedFileInfo file in files) { System.IO.File.Delete(file.TempFileName); } // Clear the list of hash keys to free up memory. MediaObjectHashKeys.Clear(); HelperFunctions.PurgeCache(); } }
private string SaveFileToTempDirectory(FileUpload fileToRestore) { // Save file to temp directory, ensuring that we are not overwriting an existing file. If the uploaded file is a ZIP archive, // extract the embedded XML file and save that. string filePath; if (Path.GetExtension(fileToRestore.FileName).Equals(".zip", StringComparison.OrdinalIgnoreCase)) { using (ZipUtility zip = new ZipUtility(Utils.UserName, GetGalleryServerRolesForUser())) { filePath = zip.ExtractNextFileFromZip(fileToRestore.FileContent, AppSetting.Instance.TempUploadDirectory); } } else { string fileName = HelperFunctions.ValidateFileName(AppSetting.Instance.TempUploadDirectory, fileToRestore.FileName); filePath = Path.Combine(AppSetting.Instance.TempUploadDirectory, fileName); fileToRestore.SaveAs(filePath); } return filePath; }
/// <summary> /// Adds the uploaded files to the gallery. This method is called when the application is operating at lesss than full trust. In this case, /// the ASP.NET FileUpload control is used. The logic is nearly identical to that in AddUploadedFilesForFullTrust - the only /// differences are syntax differences arising from the different file upload control. /// </summary> private void AddUploadedFilesLessThanFullTrust() { // Clear the list of hash keys so we're starting with a fresh load from the data store. try { MediaObjectHashKeys.Clear(); string albumPhysicalPath = this.GetAlbum().FullPhysicalPathOnDisk; HelperFunctions.BeginTransaction(); for (int i = 0; i < 5; i++) { FileUpload file = (FileUpload)phUpload.FindControl("fuUpload" + i); if (!file.HasFile) continue; if ((System.IO.Path.GetExtension(file.FileName).ToUpperInvariant() == ".ZIP") && (!chkDoNotExtractZipFile.Checked)) { #region Extract the files from the zipped file. // Extract the files from the zipped file. string userName = (String.IsNullOrEmpty(User.Identity.Name) ? "Anonymous" : User.Identity.Name); using (ZipUtility zip = new ZipUtility(userName, WebsiteController.GetRolesForUser(), User.Identity.IsAuthenticated)) { this._skippedFiles.AddRange(zip.ExtractZipFile(file.FileContent, this.GetAlbum())); } #endregion } else { #region Add the file string filename = HelperFunctions.ValidateFileName(albumPhysicalPath, file.FileName); string filepath = Path.Combine(albumPhysicalPath, filename); #if DEBUG TechInfoSystems.TracingTools.Tools.MarkSpot(string.Format(CultureInfo.CurrentCulture, "Attempting to move file {0} to {1}...", file.FileName, filepath)); #endif file.SaveAs(filepath); try { IGalleryObject go = Factory.CreateMediaObjectInstance(filepath, this.GetAlbum()); WebsiteController.SaveGalleryObject(go); } catch (UnsupportedMediaObjectTypeException ex) { File.Delete(filepath); this._skippedFiles.Add(new KeyValuePair<string, string>(filename, ex.Message)); } #endregion } } HelperFunctions.CommitTransaction(); } catch { HelperFunctions.RollbackTransaction(); throw; } finally { // Clear the list of hash keys to free up memory. MediaObjectHashKeys.Clear(); HelperFunctions.PurgeCache(); } }
/// <summary> /// Process a ZIP file that is embedded within the parent ZIP file. Its contents are extracted and turned into /// albums and media objects just like items in the parent ZIP file. /// </summary> /// <param name="zipFile">A reference to a ZIP file contained within the parent ZIP file. Notice that we don't do /// anything with this parameter other than verify that its extension is "ZIP". That's because we actually extract /// the file from the parent ZIP file by calling the ExtractFileFromZipStream method, which extracts the file from /// the class-level member variable _zipStream</param> /// <param name="parentAlbum">The album that should contain the top-level directories and files found in the ZIP /// file.</param> /// <exception cref="ArgumentNullException">Thrown when <paramref name="parentAlbum" /> is null.</exception> /// <exception cref="ArgumentException">Thrown when the file extension of <paramref name="zipFile" /> is not "zip".</exception> private void ExtractEmbeddedZipFile(ZipEntry zipFile, IAlbum parentAlbum) { #region Validation if (!Path.GetExtension(zipFile.Name).Equals(".zip", StringComparison.OrdinalIgnoreCase)) throw new ArgumentException(String.Concat("The zipFile parameter of the method ExtractEmbeddedZipFile in class ZipUtility must be a ZIP file. Instead, it had the file extension ", Path.GetExtension(zipFile.Name), ".")); if (parentAlbum == null) throw new ArgumentNullException("parentAlbum"); #endregion string filepath = Path.Combine(parentAlbum.FullPhysicalPathOnDisk, Guid.NewGuid().ToString("N") + ".zip"); try { ExtractFileFromZipStream(filepath); using (ZipUtility zip = new ZipUtility(this._userName, this._roles)) { this._fileExtractionResults.AddRange(zip.ExtractZipFile(new FileInfo(filepath).OpenRead(), parentAlbum, true)); } } finally { File.Delete(filepath); } }
/// <summary> /// Adds the uploaded files to the gallery. This method is called when the application is operating at lesss than full trust. In this case, /// the ASP.NET FileUpload control is used. The logic is nearly identical to that in AddUploadedFilesForFullTrust - the only /// differences are syntax differences arising from the different file upload control. /// </summary> private void AddUploadedFilesLessThanFullTrust() { // Clear the list of hash keys so we're starting with a fresh load from the data store. try { MediaObjectHashKeys.Clear(); string albumPhysicalPath = this.GetAlbum().FullPhysicalPathOnDisk; HelperFunctions.BeginTransaction(); for (int i = 0; i < 5; i++) { FileUpload file = (FileUpload)phUpload.FindControl("fuUpload" + i); if (!file.HasFile) continue; if ((System.IO.Path.GetExtension(file.FileName).Equals(".zip", StringComparison.OrdinalIgnoreCase)) && (!chkDoNotExtractZipFile.Checked)) { #region Extract the files from the zipped file. // Extract the files from the zipped file. using (ZipUtility zip = new ZipUtility(Utils.UserName, GetGalleryServerRolesForUser())) { this._skippedFiles.AddRange(zip.ExtractZipFile(file.FileContent, this.GetAlbum(), chkDiscardOriginalImage.Checked)); } #endregion } else { #region Add the file string filename = HelperFunctions.ValidateFileName(albumPhysicalPath, file.FileName); string filepath = Path.Combine(albumPhysicalPath, filename); file.SaveAs(filepath); try { using (IGalleryObject go = Factory.CreateMediaObjectInstance(filepath, this.GetAlbum())) { GalleryObjectController.SaveGalleryObject(go); Business.Image img = go as Business.Image; bool isImage = (img != null); if ((chkDiscardOriginalImage.Checked) && isImage) { img.DeleteHiResImage(); GalleryObjectController.SaveGalleryObject(img); } } } catch (UnsupportedMediaObjectTypeException ex) { try { File.Delete(filepath); } catch (UnauthorizedAccessException) { } // Ignore an error; the file will end up getting deleted during cleanup maintenance this._skippedFiles.Add(new KeyValuePair<string, string>(filename, ex.Message)); } #endregion } } HelperFunctions.CommitTransaction(); } catch { HelperFunctions.RollbackTransaction(); throw; } finally { // Clear the list of hash keys to free up memory. MediaObjectHashKeys.Clear(); HelperFunctions.PurgeCache(); } }
/// <summary> /// Adds the uploaded files to the gallery. This method is called when the application is operating under full trust. In this case, /// the ComponentArt Upload control is used. The logic is nearly identical to that in AddUploadedFilesLessThanFullTrust - the only /// differences are syntax differences arising from the different file upload control. /// </summary> /// <param name="files">The files to add to the gallery.</param> private void AddUploadedFilesForFullTrust(UploadedFileInfoCollection files) { // Clear the list of hash keys so we're starting with a fresh load from the data store. try { MediaObjectHashKeys.Clear(); string albumPhysicalPath = this.GetAlbum().FullPhysicalPathOnDisk; HelperFunctions.BeginTransaction(); UploadedFileInfo[] fileInfos = new UploadedFileInfo[files.Count]; files.CopyTo(fileInfos, 0); Array.Reverse(fileInfos); foreach (UploadedFileInfo file in fileInfos) { if (String.IsNullOrEmpty(file.FileName)) continue; if ((System.IO.Path.GetExtension(file.FileName).Equals(".zip", StringComparison.OrdinalIgnoreCase)) && (!chkDoNotExtractZipFile.Checked)) { #region Extract the files from the zipped file. lock (file) { if (File.Exists(file.TempFileName)) { using (ZipUtility zip = new ZipUtility(Utils.UserName, GetGalleryServerRolesForUser())) { this._skippedFiles.AddRange(zip.ExtractZipFile(file.GetStream(), this.GetAlbum(), chkDiscardOriginalImage.Checked)); } } else { // When one of the files causes an OutOfMemoryException, this can cause the other files to disappear from the // temp upload directory. This seems to be an issue with the ComponentArt Upload control, since this does not // seem to happen with the ASP.NET FileUpload control. If the file doesn't exist, make a note of it and move on // to the next one. this._skippedFiles.Add(new KeyValuePair<string, string>(file.FileName, Resources.GalleryServerPro.Task_Add_Objects_Uploaded_File_Does_Not_Exist_Msg)); continue; // Skip to the next file. } } #endregion } else { #region Add the file string filename = HelperFunctions.ValidateFileName(albumPhysicalPath, file.FileName); string filepath = Path.Combine(albumPhysicalPath, filename); lock (file) { if (File.Exists(file.TempFileName)) { file.SaveAs(filepath); } else { // When one of the files causes an OutOfMemoryException, this can cause the other files to disappear from the // temp upload directory. This seems to be an issue with the ComponentArt Upload control, since this does not // seem to happen with the ASP.NET FileUpload control. If the file doesn't exist, make a note of it and move on // to the next one. this._skippedFiles.Add(new KeyValuePair<string, string>(file.FileName, Resources.GalleryServerPro.Task_Add_Objects_Uploaded_File_Does_Not_Exist_Msg)); continue; // Skip to the next file. } } try { using (IGalleryObject go = Factory.CreateMediaObjectInstance(filepath, this.GetAlbum())) { GalleryObjectController.SaveGalleryObject(go); Business.Image img = go as Business.Image; bool isImage = (img != null); if ((chkDiscardOriginalImage.Checked) && isImage) { img.DeleteHiResImage(); GalleryObjectController.SaveGalleryObject(img); } } } catch (UnsupportedMediaObjectTypeException ex) { try { File.Delete(filepath); } catch (UnauthorizedAccessException) { } // Ignore an error; the file will end up getting deleted during cleanup maintenance this._skippedFiles.Add(new KeyValuePair<string, string>(filename, ex.Message)); } #endregion } } HelperFunctions.CommitTransaction(); } catch { HelperFunctions.RollbackTransaction(); throw; } finally { // Delete the uploaded temporary files, as by this time they have been saved to the destination directory. foreach (UploadedFileInfo file in files) { try { System.IO.File.Delete(file.TempFileName); } catch (UnauthorizedAccessException) { } // Ignore an error; the file will end up getting deleted during cleanup maintenance } // Clear the list of hash keys to free up memory. MediaObjectHashKeys.Clear(); HelperFunctions.PurgeCache(); } }
/// <summary> /// Creates the media object from the file specified in <paramref name="options" />. /// </summary> /// <param name="options">The options.</param> /// <returns>List{ActionResult}.</returns> /// <exception cref="Events.CustomExceptions.GallerySecurityException">Thrown when user is not authorized to add a media object to the album.</exception> /// <remarks>This function can be invoked from a thread that does not have access to the current HTTP context (for example, when /// uploading ZIP files). Therefore, be sure nothing in this body (or the functions it calls) uses HttpContext.Current, or at /// least check it for null first.</remarks> private static List<ActionResult> CreateMediaObjectFromFile(AddMediaObjectSettings options) { string sourceFilePath = Path.Combine(AppSetting.Instance.PhysicalApplicationPath, GlobalConstants.TempUploadDirectory, options.FileNameOnServer); try { IAlbum album = AlbumController.LoadAlbumInstance(options.AlbumId, true, true); if (HttpContext.Current != null) SecurityManager.ThrowIfUserNotAuthorized(SecurityActions.AddMediaObject, RoleController.GetGalleryServerRolesForUser(), album.Id, album.GalleryId, Utils.IsAuthenticated, album.IsPrivate, album.IsVirtualAlbum); else { // We are extracting files from a zip archive (we know this because this is the only scenario that happens on a background // thread where HttpContext.Current is null). Tweak the security check slightly to ensure the HTTP context isn't used. // The changes are still secure because options.CurrentUserName is assigned in the server's API method. SecurityManager.ThrowIfUserNotAuthorized(SecurityActions.AddMediaObject, RoleController.GetGalleryServerRolesForUser(options.CurrentUserName), album.Id, album.GalleryId, !String.IsNullOrWhiteSpace(options.CurrentUserName), album.IsPrivate, album.IsVirtualAlbum); } var extension = Path.GetExtension(options.FileName); if (extension != null && ((extension.Equals(".zip", StringComparison.OrdinalIgnoreCase)) && (options.ExtractZipFile))) { List<ActionResult> result; // Extract the files from the zipped file. using (var zip = new ZipUtility(options.CurrentUserName, RoleController.GetGalleryServerRolesForUser(options.CurrentUserName))) { using (var fs = new FileStream(sourceFilePath, FileMode.Open, FileAccess.Read)) { result = zip.ExtractZipFile(fs, album, options.DiscardOriginalFile); } } album.SortAsync(true, options.CurrentUserName, true); return result; } else { string albumPhysicalPath = album.FullPhysicalPathOnDisk; string filename = HelperFunctions.ValidateFileName(albumPhysicalPath, options.FileName); string filepath = Path.Combine(albumPhysicalPath, filename); MoveFile(filepath, sourceFilePath); ActionResult result = CreateMediaObject(filepath, album, options); album.Sort(true, options.CurrentUserName); return new List<ActionResult> { result }; } } catch (Exception ex) { AppEventController.LogError(ex); return new List<ActionResult> { new ActionResult { Title = options.FileName, Status = ActionResultStatus.Error.ToString(), Message = "The event log may have additional details." } }; } finally { try { // If the file still exists in the temp directory, delete it. Typically this happens when we've // extracted the contents of a zip file (since other files will have already been moved to the dest album.) if (File.Exists(sourceFilePath)) { File.Delete(sourceFilePath); } } catch (IOException) { } // Ignore an error; not a big deal if it continues to exist in the temp directory catch (UnauthorizedAccessException) { } // Ignore an error; not a big deal if it continues to exist in the temp directory } }