Esempio n. 1
0
        /// <summary>
        /// Creates common filters
        /// </summary>
        /// <param name="group">The groups to create the filters for</param>
        /// <returns>Common filters</returns>
        private static IEnumerable <string> CreateCommonFilters(FilterGroup group)
        {
            if (group.HasFlag(FilterGroup.CacheFiles))
            {
                // TODO: The control_dir_v2 might be under a different path for OEM branded instances.
                // However, the AppName is loaded and controlled by the AutoUpdater assembly, which we can't reference here without an ugly circular dependency or dependency injection.
                // What is the best way to solve this?
                yield return(FilterGroups.CreateWildcardFilter(@"*/Duplicati/control_dir_v2/")); // Duplicati uses this directory to store lock files and communicate with other processes.

                yield return(FilterGroups.CreateWildcardFilter(@"*/Google/Chrome/*cache*"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Google/Chrome/*LOCK*"));    // Chrome appears to lock various files under it's settings folder using files named 'LOCK' or 'lockfile'

                yield return(FilterGroups.CreateWildcardFilter(@"*/Google/Chrome/*Current*")); // 'Current Session' and 'Current Tabs' appear to be locked while running Chrome

                yield return(FilterGroups.CreateWildcardFilter(@"*/Google/Chrome/Safe Browsing*"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/iPhoto Library/iPod Photo Cache/"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Mozilla/Firefox/*cache*"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/cookies.sqlite-*"));     // Journal for database used to store Firefox cookies between sessions

                yield return(FilterGroups.CreateWildcardFilter(@"*/permissions.sqlite-*")); // Journal for database used to store Firefox site-specific permissions
            }

            if (group.HasFlag(FilterGroup.TemporaryFiles))
            {
                yield return(Library.Utility.TempFolder.SystemTempPath);
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Creates Linux filters
        /// </summary>
        /// <param name="group">The groups to create the filters for</param>
        /// <returns>Linux filters</returns>
        private static IEnumerable <string> CreateLinuxFilters(FilterGroup group)
        {
            if (group.HasFlag(FilterGroup.SystemFiles))
            {
                yield return(FilterGroups.CreateWildcardFilter(@"/dev/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/proc/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/selinux/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/sys/"));
            }
            if (group.HasFlag(FilterGroup.OperatingSystem))
            {
                yield return(FilterGroups.CreateWildcardFilter(@"/bin/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/boot/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/etc/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/initrd/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/sbin/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/var/"));
            }

            if (group.HasFlag(FilterGroup.TemporaryFiles))
            {
                yield return(FilterGroups.CreateWildcardFilter(@"*/lost+found/"));

                yield return(FilterGroups.CreateWildcardFilter(@"*~"));

                yield return(FilterGroups.CreateWildcardFilter(@"/tmp/"));
            }
            if (group.HasFlag(FilterGroup.CacheFiles))
            {
                string cacheHome = Environment.GetEnvironmentVariable("XDG_CACHE_HOME");
                if (cacheHome != null)
                {
                    yield return(FilterGroups.CreateWildcardFilter(cacheHome));
                }
                yield return(FilterGroups.CreateWildcardFilter(@"*/.cache/"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/.config/google-chrome/Default/Cookies"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/.config/google-chrome/Default/Cookies-journal"));
            }
            if (group.HasFlag(FilterGroup.Applications))
            {
                yield return(FilterGroups.CreateWildcardFilter(@"/lib/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/lib64/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/opt/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/usr/"));
            }
        }
Esempio n. 3
0
            /// <summary>
            /// Gets the regex that represents the given filter group
            /// </summary>
            /// <param name="filterGroupName">Filter group name</param>
            /// <returns>Group regex</returns>
            private static Regex GetFilterGroupRegex(string filterGroupName)
            {
                FilterGroup filterGroup = FilterGroups.ParseFilterList(filterGroupName, FilterGroup.None);
                Regex       result;

                if (FilterEntry.filterGroupRegexCache.TryGetValue(filterGroup, out result))
                {
                    return(result);
                }
                else
                {
                    // Get the filter strings for this filter group, and convert them to their regex forms
                    List <string> regexStrings = FilterGroups.GetFilterStrings(filterGroup)
                                                 .Select(filterString =>
                    {
                        if (filterString.StartsWith("[", StringComparison.Ordinal) && filterString.EndsWith("]", StringComparison.Ordinal))
                        {
                            return(filterString.Substring(1, filterString.Length - 2));
                        }
                        else if (filterString.StartsWith("@", StringComparison.Ordinal))
                        {
                            return(Utility.ConvertLiteralToRegExp(filterString.Substring(1)));
                        }
                        else
                        {
                            return(Utility.ConvertGlobbingToRegExp(filterString));
                        }
                    })
                                                 .ToList();

                    string regexString;
                    if (regexStrings.Count == 1)
                    {
                        regexString = regexStrings.Single();
                    }
                    else
                    {
                        // If there are multiple regex strings, then they need to be merged by wrapping each in parenthesis and ORing them together
                        regexString = "(" + string.Join(")|(", regexStrings) + ")";
                    }

                    result = new Regex(regexString, REGEXP_OPTIONS);

                    FilterEntry.filterGroupRegexCache[filterGroup] = result;

                    return(result);
                }
            }
Esempio n. 4
0
        /// <summary>
        /// Creates a filter for a special folder
        /// </summary>
        /// <param name="specialFolder">Special folder</param>
        /// <returns>Special folder filter</returns>
        private static string CreateSpecialFolderFilter(Environment.SpecialFolder specialFolder)
        {
            string folderPath = Environment.GetFolderPath(specialFolder);

            if (!string.IsNullOrEmpty(folderPath))
            {
                // Note that this also replaces alternate directory separators with regular ones
                string filter = FilterGroups.CreateWildcardFilter(folderPath);

                // Duplicati matches filters against folder paths exactly.
                // Meaning a filter for 'C:\Windows' won't match 'C:\Windows\'.
                // So this makes sure special folder filters have a trailing directory separator.
                // (Alternatively, this could append '*' to all folder filters.)
                return(Common.IO.Util.AppendDirSeparator(filter));
            }
            else
            {
                return(null);
            }
        }
Esempio n. 5
0
        private static IEnumerable <string> Expand(string filter)
        {
            if (string.IsNullOrWhiteSpace(filter))
            {
                return(null);
            }

            if (filter.Length < 2 || (filter.StartsWith("[", StringComparison.Ordinal) && filter.EndsWith("]", StringComparison.Ordinal)))
            {
                return(new string[] { filter });
            }

            if (filter.StartsWith("{", StringComparison.Ordinal) && filter.EndsWith("}", StringComparison.Ordinal))
            {
                string      groupName   = filter.Substring(1, filter.Length - 2);
                FilterGroup filterGroup = FilterGroups.ParseFilterList(groupName, FilterGroup.None);
                return((filterGroup == FilterGroup.None) ? null : FilterGroups.GetFilterStrings(filterGroup));
            }

            return(filter.Split(new char[] { System.IO.Path.PathSeparator }, StringSplitOptions.RemoveEmptyEntries));
        }
Esempio n. 6
0
        /// <summary>
        /// Creates OSX filters
        /// </summary>
        /// <param name="group">The groups to create the filters for</param>
        /// <returns>OSX filters</returns>
        private static IEnumerable <string> CreateOSXFilters(FilterGroup group)
        {
            if (group.HasFlag(FilterGroup.SystemFiles))
            {
                yield return(FilterGroups.CreateWildcardFilter(@"/.vol/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/dev/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/net/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/afs/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/automount/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/cores/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/Network/"));

                yield return(FilterGroups.CreateWildcardFilter(@"*.fseventsd"));

                yield return(FilterGroups.CreateWildcardFilter(@"*.dbfseventsd"));

                yield return(FilterGroups.CreateWildcardFilter(@"/private/Network/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/private/var/automount/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/private/var/db/dhcpclient/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/private/var/db/fseventsd/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/private/var/folders/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/private/var/run/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/private/var/spool/postfix/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/private/var/vm/"));

                foreach (var p in GetOSXExcludeFiles() ?? new string[0])
                {
                    yield return(p);
                }
            }

            if (group.HasFlag(FilterGroup.OperatingSystem))
            {
                yield return(FilterGroups.CreateWildcardFilter(@"/Previous Systems*"));

                yield return(FilterGroups.CreateWildcardFilter(@"/mach.sym"));

                yield return(FilterGroups.CreateWildcardFilter(@"/mach_kernel"));

                yield return(FilterGroups.CreateWildcardFilter(@"/bin/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/sbin/"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Library/Logs/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/Network/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/System/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/Volumes/"));
            }

            if (group.HasFlag(FilterGroup.CacheFiles))
            {
                yield return(FilterGroups.CreateWildcardFilter(@"*/Application Support/Google/Chrome/Default/Cookies"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Application Support/Google/Chrome/Default/Cookies-journal"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Library/Caches/"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Library/Calendars/*/Info.plist"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Library/Calendars/Calendar Cache"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Library/Cookies/com.apple.appstore.plist"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Library/Cookies/Cookies.binarycookies"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/backups.backupdb/"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/iP* Software Updates/"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/iPhoto Library/iPod Photo Cache*"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/iTunes/Album Artwork/Cache/"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Library/Application Support/SyncServices/"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Library/Mail/*/Info.plist"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Library/Mail/AvailableFeeds/"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Library/Mail/Envelope Index"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Library/Mirrors/"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Library/PubSub/Database/"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Library/PubSub/Downloads/"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Library/PubSub/Feeds/"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Library/Safari/HistoryIndex.sk"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Library/Safari/Icons.db"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Library/Safari/WebpageIcons.db"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Library/Saved Application State/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/System/Library/Extensions/Caches/"));

                yield return(FilterGroups.CreateWildcardFilter(@"*MobileBackups/"));

                yield return(FilterGroups.CreateWildcardFilter(@"*.hotfiles.btree*"));

                yield return(FilterGroups.CreateWildcardFilter(@"*.Spotlight-*/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/Desktop DB"));

                yield return(FilterGroups.CreateWildcardFilter(@"/Desktop DF"));
            }

            if (group.HasFlag(FilterGroup.TemporaryFiles))
            {
                yield return(FilterGroups.CreateWildcardFilter(@"/private/tmp/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/private/var/tmp/"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Microsoft User Data/Entourage Temp/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/tmp/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/var/"));

                yield return(FilterGroups.CreateWildcardFilter(@"*.Trash*"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Network Trash Folder/"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Trash/"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/lost+found/"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/VM Storage"));
            }

            if (group.HasFlag(FilterGroup.Applications))
            {
                yield return(FilterGroups.CreateWildcardFilter(@"/Applications/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/Library/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/usr/"));

                yield return(FilterGroups.CreateWildcardFilter(@"/opt/"));
            }
        }
Esempio n. 7
0
        /// <summary>
        /// Creates Windows filters
        /// </summary>
        /// <param name="group">The groups to create the filters for</param>
        /// <returns>Windows filters</returns>
        private static IEnumerable <string> CreateWindowsFilters(FilterGroup group)
        {
            if (group.HasFlag(FilterGroup.SystemFiles))
            {
                yield return(FilterGroups.CreateWildcardFilter(@"*/I386*"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Internet Explorer/"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Microsoft*/RecoveryStore*"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Microsoft*/Windows/*.edb"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Microsoft*/Windows/*.log"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Microsoft*/Windows/Cookies*"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/MSOCache*"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/NTUSER*"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/UsrClass.dat"));

                yield return(FilterGroups.CreateWildcardFilter(@"?:/hiberfil.sys"));

                yield return(FilterGroups.CreateWildcardFilter(@"?:/pagefile.sys"));

                yield return(FilterGroups.CreateWildcardFilter(@"?:/swapfile.sys"));

                yield return(FilterGroups.CreateWildcardFilter(@"?:/$Recycle.Bin/"));

                yield return(FilterGroups.CreateWildcardFilter(@"?:/Recycled/"));

                yield return(FilterGroups.CreateWildcardFilter(@"?:/Recycler/"));

                yield return(FilterGroups.CreateWildcardFilter(@"?:/System Volume Information/"));

                yield return(FilterGroups.CreateWildcardFilter(FilterGroups.CreateSpecialFolderFilter(Environment.SpecialFolder.Windows) + "Installer/"));

                foreach (var s in GetWindowsRegistryFilters() ?? new string[0])
                {
                    // If this path refers to the root of a drive, then prepend it with "?:" since that's how Duplicati's root path matching works.
                    if (s.StartsWith(@"\", StringComparison.Ordinal) || s.StartsWith("/", StringComparison.Ordinal))
                    {
                        yield return("?:" + s);
                    }
                    else
                    {
                        yield return(s);
                    }
                }
            }

            if (group.HasFlag(FilterGroup.OperatingSystem))
            {
                yield return(FilterGroups.CreateWildcardFilter(@"?:/Config.Msi*")); // https://github.com/duplicati/duplicati/issues/2886

                yield return(FilterGroups.CreateWildcardFilter(@"*/Recent/"));

                yield return(FilterGroups.CreateWildcardFilter(@"?:/autoexec.bat"));

                yield return(FilterGroups.CreateSpecialFolderFilter(Environment.SpecialFolder.System));

                yield return(FilterGroups.CreateSpecialFolderFilter(Environment.SpecialFolder.SystemX86));

                yield return(FilterGroups.CreateSpecialFolderFilter(Environment.SpecialFolder.Recent));

                var windir = FilterGroups.CreateSpecialFolderFilter(Environment.SpecialFolder.Windows);
                if (!string.IsNullOrWhiteSpace(windir))
                {
                    yield return(windir);

                    // Also exclude "C:\Windows.old\"
                    yield return(Common.IO.Util.AppendDirSeparator(windir.TrimEnd('\\', '/') + ".old"));
                }
            }

            if (group.HasFlag(FilterGroup.CacheFiles))
            {
                yield return(FilterGroups.CreateWildcardFilter(@"*/AppData/Local/AMD/DxCache/")); // Appears to be a shader cache folder for AMD video card drivers

                yield return(FilterGroups.CreateWildcardFilter(@"*/AppData/Local/Apple Computer/Mobile Sync/"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/AppData/Local/Comms/UnistoreDB/"));    // Looks like storage about music / pictures for universal store apps

                yield return(FilterGroups.CreateWildcardFilter(@"*/AppData/Local/ElevatedDiagnostics/")); // Seems to be used by sfc tool and Windows troubleshooting

                yield return(FilterGroups.CreateWildcardFilter(@"*/AppData/Local/Microsoft/Edge/User Data/Default/Cache"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/AppData/Local/Microsoft/VSCommon/*SQM*"));     // SQM appears to be 'service quality management', and it looks like these files report things about Visual Studio installation: https://stackoverflow.com/questions/23050561/what-permissions-policies-are-needed-to-support-loaduserprofile-true-for-new-app

                yield return(FilterGroups.CreateWildcardFilter(@"*/AppData/Local/Microsoft/Windows/Explorer/"));  // Stores icon and thumbnail caches

                yield return(FilterGroups.CreateWildcardFilter(@"*/AppData/Local/Microsoft/Windows/INetCache/")); //

                yield return(FilterGroups.CreateWildcardFilter(@"*/AppData/Local/Microsoft/Windows/UPPS/"));      // Not sure what this one is, but seems to be a common one to fail to backup: http://support.wdc.com/knowledgebase/answer.aspx?ID=17969&lang=en

                yield return(FilterGroups.CreateWildcardFilter(@"*/AppData/Local/Microsoft/Windows/WebCache*"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/AppData/Local/Microsoft/Windows Store/"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/AppData/Local/Packages/")); // https://superuser.com/questions/490925/explain-windows-8-windows-store-appdata-packages-and-what-to-backup

                yield return(FilterGroups.CreateWildcardFilter(@"*/Application Data/Apple Computer/Mobile Sync/"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Application Data/Application Data*"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Dropbox/Dropbox.exe.log")); // Dropbox log file, which may be kept open by Dropbox while it is running

                yield return(FilterGroups.CreateWildcardFilter(@"*/Dropbox/QuitReports/"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Google/Chrome/User Data/Default/Cache"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Google/Chrome/User Data/Default/Cookies"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Google/Chrome/User Data/Default/Cookies-journal"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Local Settings/History/"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/OneDrive/.849C9593-D756-4E56-8D6E-42412F2A707B")); // This looks like a hidden cache file for the OneDrive service: https://onedrive.uservoice.com/forums/262982-onedrive/suggestions/10059663-get-rid-of-undeleteable-849c9593-d756-4e56-8d6e

                yield return(FilterGroups.CreateWildcardFilter(@"*/Safari/Library/Caches/"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Temporary Internet Files/"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Thumbs.db"));

                yield return(FilterGroups.CreateSpecialFolderFilter(Environment.SpecialFolder.History));

                yield return(FilterGroups.CreateSpecialFolderFilter(Environment.SpecialFolder.InternetCache));

                yield return(FilterGroups.CreateSpecialFolderFilter(Environment.SpecialFolder.Cookies));
            }

            if (group.HasFlag(FilterGroup.TemporaryFiles))
            {
                yield return(FilterGroups.CreateWildcardFilter(@"*.tmp"));

                yield return(FilterGroups.CreateWildcardFilter(@"*.tmp/"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/AppData/Local/Temp*"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/AppData/Temp*"));

                yield return(FilterGroups.CreateWildcardFilter(@"*/Local Settings/Temp*"));

                yield return(FilterGroups.CreateWildcardFilter(FilterGroups.CreateSpecialFolderFilter(Environment.SpecialFolder.Windows) + "Temp/"));
            }

            if (group.HasFlag(FilterGroup.Applications))
            {
                yield return(FilterGroups.CreateSpecialFolderFilter(Environment.SpecialFolder.ProgramFiles));

                yield return(FilterGroups.CreateSpecialFolderFilter(Environment.SpecialFolder.ProgramFilesX86));

                yield return(FilterGroups.CreateSpecialFolderFilter(Environment.SpecialFolder.AdminTools));

                yield return(FilterGroups.CreateSpecialFolderFilter(Environment.SpecialFolder.CommonProgramFiles));

                yield return(FilterGroups.CreateSpecialFolderFilter(Environment.SpecialFolder.CommonProgramFilesX86));

                yield return(FilterGroups.CreateSpecialFolderFilter(Environment.SpecialFolder.CommonAdminTools));
            }
        }
Esempio n. 8
0
        /// <summary>
        /// Gets a string that describes the filter group options
        /// </summary>
        /// <returns>The option descriptions.</returns>
        /// <param name="indentation">The string indentation to use.</param>
        /// <param name="includevalues">If set to <c>true</c> include actual filter paths in the output.</param>
        public static string GetOptionDescriptions(int indentation, bool includevalues)
        {
            var defaultExclude       = FilterGroup.DefaultExcludes;
            var defaultExcludeValues = new List <string>();
            var defaultInclude       = FilterGroup.DefaultIncludes;
            var defaultIncludeValues = new List <string>();

            foreach (var e in Enum.GetValues(typeof(FilterGroup)))
            {
                var ed = (FilterGroup)e;
                if (defaultExclude.HasFlag(ed) && ed != defaultExclude && ed != FilterGroup.None)
                {
                    defaultExcludeValues.Add(e.ToString());
                }
                if (defaultInclude.HasFlag(ed) && ed != defaultInclude && ed != FilterGroup.None)
                {
                    defaultIncludeValues.Add(e.ToString());
                }
            }

            var ind = new string(' ', indentation);

            var sb = new System.Text.StringBuilder();

            sb.AppendLine(ind + LC.L("{0}: Selects no filters.", nameof(FilterGroup.None)));
            sb.AppendLine(ind + LC.L("{0}: A set of default exclude filters, currently evaluates to: {1}.", nameof(FilterGroup.DefaultExcludes), string.Join(",", defaultExcludeValues.DefaultIfEmpty(nameof(FilterGroup.None)))));
            sb.AppendLine(ind + LC.L("{0}: A set of default include filters, currently evaluates to: {1}.", nameof(FilterGroup.DefaultIncludes), string.Join(",", defaultIncludeValues.DefaultIfEmpty(nameof(FilterGroup.None)))));

            if (includevalues)
            {
                sb.AppendLine();
            }

            Action <FilterGroup, bool> appendAliasesAndValues = (filterGroup, lastLine) =>
            {
                if (includevalues)
                {
                    if (FilterGroups.GetAliases(filterGroup).Any())
                    {
                        sb.AppendLine(ind + LC.L(" Aliases: {0}", string.Join(",", FilterGroups.GetAliases(filterGroup).OrderBy(x => x, StringComparer.OrdinalIgnoreCase))));
                    }
                    foreach (var v in GetFilterStrings(filterGroup))
                    {
                        sb.AppendLine(ind + "  " + v);
                    }
                    if (!lastLine)
                    {
                        sb.AppendLine();
                    }
                }
            };

            sb.AppendLine(ind + LC.L("{0}: Files that are owned by the system or not suited to be backed up. This includes any operating system reported protected files. Most users should at least apply these filters.", nameof(FilterGroup.SystemFiles)));
            appendAliasesAndValues(FilterGroup.SystemFiles, false);
            sb.AppendLine(ind + LC.L("{0}: Files that belong to the operating system. These files are restored when the operating system is re-installed.", nameof(FilterGroup.OperatingSystem)));
            appendAliasesAndValues(FilterGroup.OperatingSystem, false);
            sb.AppendLine(ind + LC.L("{0}: Files and folders that are known to be storage of temporary data.", nameof(FilterGroup.TemporaryFiles)));
            appendAliasesAndValues(FilterGroup.TemporaryFiles, false);
            sb.AppendLine(ind + LC.L("{0}: Files and folders that are known cache locations for the operating system and various applications", nameof(FilterGroup.CacheFiles)));
            appendAliasesAndValues(FilterGroup.CacheFiles, false);
            sb.AppendLine(ind + LC.L("{0}: Installed programs and their libraries, but not their settings.", nameof(FilterGroup.Applications)));
            appendAliasesAndValues(FilterGroup.Applications, true);

            return(sb.ToString());
        }