source: trunk/eraser/Eraser.DefaultPlugins/ErasureTargets/FolderErasureTarget.cs @ 2085

Revision 2085, 6.7 KB checked in by lowjoel, 4 years ago (diff)
  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1/*
2 * $Id$
3 * Copyright 2008-2010 The Eraser Project
4 * Original Author: Joel Low <lowjoel@users.sourceforge.net>
5 * Modified By:
6 *
7 * This file is part of Eraser.
8 *
9 * Eraser is free software: you can redistribute it and/or modify it under the
10 * terms of the GNU General Public License as published by the Free Software
11 * Foundation, either version 3 of the License, or (at your option) any later
12 * version.
13 *
14 * Eraser is distributed in the hope that it will be useful, but WITHOUT ANY
15 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
17 *
18 * A copy of the GNU General Public License can be found at
19 * <http://www.gnu.org/licenses/>.
20 */
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using System.Text;
26
27using System.Text.RegularExpressions;
28using System.Runtime.Serialization;
29using System.Runtime.InteropServices;
30using System.Security.Permissions;
31using System.IO;
32
33using Eraser.Manager;
34using Eraser.Util;
35
36namespace Eraser.DefaultPlugins
37{
38    /// <summary>
39    /// Represents a folder and its files which are to be erased.
40    /// </summary>
41    [Serializable]
42    [Guid("F50B0A44-3AB1-4cab-B81E-1713AC3D28C9")]
43    public class FolderErasureTarget : FileSystemObjectErasureTarget
44    {
45        #region Serialization code
46        protected FolderErasureTarget(SerializationInfo info, StreamingContext context)
47            : base(info, context)
48        {
49            IncludeMask = (string)info.GetValue("IncludeMask", typeof(string));
50            ExcludeMask = (string)info.GetValue("ExcludeMask", typeof(string));
51            DeleteIfEmpty = (bool)info.GetValue("DeleteIfEmpty", typeof(bool));
52        }
53
54        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
55        public override void GetObjectData(SerializationInfo info, StreamingContext context)
56        {
57            base.GetObjectData(info, context);
58            info.AddValue("IncludeMask", IncludeMask);
59            info.AddValue("ExcludeMask", ExcludeMask);
60            info.AddValue("DeleteIfEmpty", DeleteIfEmpty);
61        }
62        #endregion
63
64        /// <summary>
65        /// Constructor.
66        /// </summary>
67        public FolderErasureTarget()
68        {
69            IncludeMask = string.Empty;
70            ExcludeMask = string.Empty;
71            DeleteIfEmpty = true;
72        }
73
74        public override Guid Guid
75        {
76            get { return GetType().GUID; }
77        }
78
79        public override string Name
80        {
81            get { return S._("Files in Folder"); }
82        }
83
84        public override IErasureTargetConfigurer Configurer
85        {
86            get { return new FolderErasureTargetConfigurer(); }
87        }
88
89        protected override List<StreamInfo> GetPaths(out long totalSize)
90        {
91            //Get a list to hold all the resulting streams.
92            List<StreamInfo> result = new List<StreamInfo>();
93
94            //Open the root of the search, including every file matching the pattern
95            DirectoryInfo dir = new DirectoryInfo(Path);
96
97            //List recursively all the files which match the include pattern.
98            FileInfo[] files = GetFiles(dir);
99
100            //Then exclude each file and finalize the list and total file size
101            totalSize = 0;
102            Regex includePattern = string.IsNullOrEmpty(IncludeMask) ? null :
103                new Regex(
104                    Regex.Escape(ExcludeMask).Replace("\\*", ".*").Replace("\\?", "."),
105                    RegexOptions.IgnoreCase | RegexOptions.Compiled);
106            Regex excludePattern = string.IsNullOrEmpty(ExcludeMask) ? null :
107                new Regex(
108                    Regex.Escape(ExcludeMask).Replace("\\*", ".*").Replace("\\?", "."),
109                    RegexOptions.IgnoreCase | RegexOptions.Compiled);
110            foreach (FileInfo file in files)
111            {
112                //Check that the file exists and is not a reparse point.
113                if (!file.Exists || (file.Attributes & FileAttributes.ReparsePoint) == 0)
114                    continue;
115
116                //Check that the file is included
117                if (includePattern != null && !includePattern.Match(file.FullName).Success)
118                    continue;
119
120                //Check that the file is not excluded
121                if (excludePattern != null && excludePattern.Match(file.FullName).Success)
122                    continue;
123
124                //Add the size of the file and its alternate data streams
125                totalSize += file.Length;
126                long adsesSize = 0;
127                result.AddRange(GetPathADSes(file, out adsesSize));
128                totalSize += adsesSize;
129
130                //And the file itself
131                result.Add(new StreamInfo(file.FullName));
132            }
133
134            //Return the filtered list.
135            return result;
136        }
137
138        /// <summary>
139        /// A wildcard expression stating the condition for the set of files to include.
140        /// The include mask is applied before the exclude mask is applied. If this value
141        /// is empty, all files and folders within the folder specified is included.
142        /// </summary>
143        public string IncludeMask { get; set; }
144
145        /// <summary>
146        /// A wildcard expression stating the condition for removing files from the set
147        /// of included files. If this value is omitted, all files and folders extracted
148        /// by the inclusion mask is erased.
149        /// </summary>
150        public string ExcludeMask { get; set; }
151
152        /// <summary>
153        /// Determines if Eraser should delete the folder after the erase process.
154        /// </summary>
155        public bool DeleteIfEmpty { get; set; }
156
157        public override void Execute()
158        {
159            Progress = new SteppedProgressManager();
160            try
161            {
162                base.Execute();
163
164                //If the user requested a folder removal, do it.
165                if (Directory.Exists(Path))
166                {
167                    ProgressManager step = new ProgressManager();
168                    Progress.Steps.Add(new SteppedProgressManagerStep(step,
169                        0.0f, S._("Removing folders...")));
170
171                    //Remove all subfolders which are empty.
172                    FileSystem fsManager = ManagerLibrary.Instance.FileSystemRegistrar[
173                        VolumeInfo.FromMountPoint(Path)];
174                    Action<DirectoryInfo> eraseEmptySubFolders = null;
175                    eraseEmptySubFolders = delegate(DirectoryInfo info)
176                    {
177                        foreach (DirectoryInfo subDir in info.GetDirectories())
178                            eraseEmptySubFolders(subDir);
179                        OnProgressChanged(this, new ProgressChangedEventArgs(step,
180                            new TaskProgressChangedEventArgs(info.FullName, 0, 0)));
181
182                        FileSystemInfo[] files = info.GetFileSystemInfos();
183                        if (files.Length == 0)
184                            fsManager.DeleteFolder(info);
185                    };
186
187                    DirectoryInfo directory = new DirectoryInfo(Path);
188                    foreach (DirectoryInfo subDir in directory.GetDirectories())
189                        eraseEmptySubFolders(subDir);
190
191                    if (DeleteIfEmpty)
192                    {
193                        //See if this is the root of a volume.
194                        bool isVolumeRoot = directory.Parent == null;
195                        foreach (VolumeInfo volume in VolumeInfo.Volumes)
196                            foreach (string mountPoint in volume.MountPoints)
197                                if (directory.FullName == mountPoint)
198                                    isVolumeRoot = true;
199
200                        //If the folder is a mount point, then don't delete it. If it isn't,
201                        //search for files under the folder to see if it is empty.
202                        if (!isVolumeRoot && directory.Exists &&
203                            directory.GetFiles("*", SearchOption.AllDirectories).Length == 0)
204                        {
205                            fsManager.DeleteFolder(directory);
206                        }
207                    }
208                }
209            }
210            finally
211            {
212                Progress = null;
213            }
214        }
215    }
216}
Note: See TracBrowser for help on using the repository browser.