Example #1
0
        public static int Run(List<string> args, Dictionary<string, string> options, Library.Utility.IFilter filter)
        {
            if (args.Count >= 1 && !string.Equals("help", args[0]))
            {
                Console.WriteLine("Unsupported command: {0}", args[0]);
                Console.WriteLine();
                return 100;
            }

            Console.Write(new System.IO.StreamReader(System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(System.Reflection.Assembly.GetExecutingAssembly().GetName().Name + "." + RESOURCE_NAME)).ReadToEnd());

            return 0;
        }
Example #2
0
        public static int RealMain(string[] _args)
        {
            try
            {
                var args = new List<string>(_args);
                var tmpparsed = Library.Utility.FilterCollector.ExtractOptions(args);
                var options = tmpparsed.Item1;
                var filter = tmpparsed.Item2;

                if (!options.ContainsKey("auth_password") && !string.IsNullOrEmpty(System.Environment.GetEnvironmentVariable("AUTH_PASSWORD")))
                    options["auth_password"] = System.Environment.GetEnvironmentVariable("AUTH_PASSWORD");

                if (!options.ContainsKey("auth_username") && !string.IsNullOrEmpty(System.Environment.GetEnvironmentVariable("AUTH_USERNAME")))
                    options["auth_username"] = System.Environment.GetEnvironmentVariable("AUTH_USERNAME");

                if (options.ContainsKey("tempdir") && !string.IsNullOrEmpty(options["tempdir"]))
                    Library.Utility.TempFolder.SystemTempPath = options["tempdir"];

                var actions = new Dictionary<string, CommandRunner>(StringComparer.InvariantCultureIgnoreCase);
                actions["download"] = Download.Run;
                actions["index"] = Index.Run;
                actions["list"] = List.Run;
                actions["restore"] = Restore.Run;
                actions["help"] = Help.Run;

                CommandRunner command;

                actions.TryGetValue(args.FirstOrDefault(), out command);

                command = command ?? actions["help"];

                return command(args, options, filter);
            }
            catch(Exception ex)
            {
                Console.WriteLine("Program crashed: {0}{1}", Environment.NewLine, ex.ToString());
                return 200;
            }
        }
Example #3
0
        public static int Run(List<string> args, Dictionary<string, string> options, Library.Utility.IFilter filter)
        {
            if (args.Count != 2 && args.Count != 3)
            {
                Console.WriteLine("Invalid argument count ({0} expected 2 or 3): {1}{2}", args.Count, Environment.NewLine, string.Join(Environment.NewLine, args));
                return 100;
            }

            var folder = Path.GetFullPath(args[1]);

            if (!Directory.Exists(folder))
            {
                Console.WriteLine("Folder not found: {0}", folder);
                return 100;
            }

            Directory.SetCurrentDirectory(folder);

            if (args.Count == 2)
            {
                var times = ParseListFiles(folder);
                foreach(var v in times.Zip(Enumerable.Range(0, times.Length), (a,b) => new KeyValuePair<int, DateTime>(b, a.Key)))
                    Console.WriteLine("{0}: {1}", v.Key, v.Value.ToLocalTime());
            }
            else
            {
                var file = SelectListFile(args[2], folder);

                var p = Library.Main.Volumes.VolumeBase.ParseFilename(file);

                Library.Main.Volumes.VolumeReaderBase.UpdateOptionsFromManifest(p.CompressionModule, file, new Duplicati.Library.Main.Options(options));

                foreach(var f in EnumerateFilesInDList(file, filter, options))
                    Console.WriteLine("{0} ({1})", f.Path, Library.Utility.Utility.FormatSizeString(f.Size));
            }

            return 0;
        }
Example #4
0
        public static int RealMain(string[] _args)
        {
            try
            {
                var args = new List<string>(_args);
                var tmpparsed = Library.Utility.FilterCollector.ExtractOptions(args);
                var options = tmpparsed.Item1;
                var filter = tmpparsed.Item2;

                if (!options.ContainsKey("auth_password") && !string.IsNullOrEmpty(System.Environment.GetEnvironmentVariable("AUTH_PASSWORD")))
                    options["auth_password"] = System.Environment.GetEnvironmentVariable("AUTH_PASSWORD");

                if (!options.ContainsKey("auth_username") && !string.IsNullOrEmpty(System.Environment.GetEnvironmentVariable("AUTH_USERNAME")))
                    options["auth_username"] = System.Environment.GetEnvironmentVariable("AUTH_USERNAME");

                if (options.ContainsKey("tempdir") && !string.IsNullOrEmpty(options["tempdir"]))
                    Library.Utility.TempFolder.SetSystemTempPath(options["tempdir"]);

                bool isHelp = args.Count == 0 || (args.Count >= 1 && string.Equals(args[0], "help", StringComparison.InvariantCultureIgnoreCase));
                if (!isHelp && ((options.ContainsKey("parameters-file") && !string.IsNullOrEmpty("parameters-file")) || (options.ContainsKey("parameter-file") && !string.IsNullOrEmpty("parameter-file")) || (options.ContainsKey("parameterfile") && !string.IsNullOrEmpty("parameterfile"))))
                {
                    string filename;
                    if (options.ContainsKey("parameters-file") && !string.IsNullOrEmpty("parameters-file"))
                    {
                        filename = options["parameters-file"];
                        options.Remove("parameters-file");
                    }
                    else if (options.ContainsKey("parameter-file") && !string.IsNullOrEmpty("parameter-file"))
                    {
                        filename = options["parameter-file"];
                        options.Remove("parameter-file");
                    }
                    else
                    {
                        filename = options["parameterfile"];
                        options.Remove("parameterfile");
                    }

                    if (!ReadOptionsFromFile(filename, ref filter, args, options))
                        return 100;
                }

                var actions = new Dictionary<string, CommandRunner>(StringComparer.InvariantCultureIgnoreCase);
                actions["download"] = Download.Run;
                actions["recompress"] = Recompress.Run;
                actions["index"] = Index.Run;
                actions["list"] = List.Run;
                actions["restore"] = Restore.Run;
                actions["help"] = Help.Run;

                CommandRunner command;

                actions.TryGetValue(args.FirstOrDefault() ?? "", out command);

                command = command ?? actions["help"];

                return command(args, options, filter);
            }
            catch(Exception ex)
            {
                Console.WriteLine("Program crashed: {0}{1}", Environment.NewLine, ex.ToString());
                return 200;
            }
        }
Example #5
0
        private static bool ReadOptionsFromFile(string filename, ref Library.Utility.IFilter filter, List<string> cargs, Dictionary<string, string> options)
        {
            try
            {
                List<string> fargs = new List<string>(Library.Utility.Utility.ReadFileWithDefaultEncoding(Library.Utility.Utility.ExpandEnvironmentVariables(filename)).Replace("\r\n", "\n").Replace("\r", "\n").Split(new String[] { "\n" }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()));
                var tmpparsed = Library.Utility.FilterCollector.ExtractOptions(fargs);

                var opt = tmpparsed.Item1;
                var newfilter = tmpparsed.Item2;

                // If the user specifies parameters-file, all filters must be in the file.
                // Allowing to specify some filters on the command line could result in wrong filter ordering
                if (!filter.Empty && !newfilter.Empty)
                    throw new Exception("Filters cannot be specified on the commandline if filters are also present in the parameter file");

                if (!newfilter.Empty)
                    filter = newfilter;

                foreach(KeyValuePair<String, String> keyvalue in opt)
                    options[keyvalue.Key] = keyvalue.Value;

                cargs.AddRange(
                    from c in fargs
                    where !string.IsNullOrWhiteSpace(c) && !c.StartsWith("#") && !c.StartsWith("!") && !c.StartsWith("REM ", StringComparison.InvariantCultureIgnoreCase)
                    select c
                );

                return true;
            }
            catch (Exception e)
            {
                Console.WriteLine(@"Unable to read the parameters file ""{0}"", reason: {1}", filename, e.Message);
                return false;
            }
        }
Example #6
0
            public void Dispose()
            {
                foreach(var v in m_lookup.Values)
                    try { v.Dispose(); }
                    catch { }

                m_lookup = null;
                m_mru = null;
            }
Example #7
0
        public static int Run(List<string> args, Dictionary<string, string> options, Library.Utility.IFilter filter)
        {
            if (args.Count != 2 && args.Count != 3)
            {
                Console.WriteLine("Invalid argument count ({0} expected 2 or 3): {1}{2}", args.Count, Environment.NewLine, string.Join(Environment.NewLine, args));
                return 100;
            }

            var folder = Path.GetFullPath(args[1]);

            if (!Directory.Exists(folder))
            {
                Console.WriteLine("Folder not found: {0}", folder);
                return 100;
            }

            Directory.SetCurrentDirectory(folder);

            string targetpath;
            options.TryGetValue("targetpath", out targetpath);

            string ixfile;
            options.TryGetValue("indexfile", out ixfile);
            if (string.IsNullOrWhiteSpace(ixfile))
                ixfile = "index.txt";

            ixfile = Path.GetFullPath(ixfile);
            if (!File.Exists(ixfile))
            {
                Console.WriteLine("Index file not found, perhaps you need to run the index command?");
                return 100;
            }

            Console.Write("Sorting index file ...");
            Index.SortFile(ixfile, ixfile);
            Console.WriteLine(" done!");

            string filelist;
            if (args.Count == 2)
            {
                var time = List.ParseListFiles(folder).First();
                filelist = time.Value;

                Console.WriteLine("Using set 0 with timestamp {0}", time.Key.ToLocalTime());
            }
            else
            {
                filelist = List.SelectListFile(args[2], folder);
            }

            Library.Main.Volumes.VolumeReaderBase.UpdateOptionsFromManifest(Path.GetExtension(filelist).Trim('.'), filelist, new Duplicati.Library.Main.Options(options));

            string blocksize_str;
            options.TryGetValue("blocksize", out blocksize_str);
            string blockhash_str;
            options.TryGetValue("block-hash-algorithm", out blockhash_str);
            string filehash_str;
            options.TryGetValue("block-hash-algorithm", out filehash_str);

            long blocksize = string.IsNullOrWhiteSpace(blocksize_str) ? 0 : Library.Utility.Sizeparser.ParseSize(blocksize_str);

            if (blocksize <= 0)
            {
                Console.WriteLine("Invalid blocksize: {0}, try setting --blocksize manually");
                return 100;
            }

            var blockhasher = string.IsNullOrWhiteSpace(blockhash_str) ? null : System.Security.Cryptography.HashAlgorithm.Create(blockhash_str);
            var filehasher = string.IsNullOrWhiteSpace(filehash_str) ? null : System.Security.Cryptography.HashAlgorithm.Create(filehash_str);

            if (blockhasher == null)
                throw new Exception(string.Format("Block hash algorithm not valid: {0}", blockhash_str));
            if (filehasher == null)
                throw new Exception(string.Format("File hash algorithm not valid: {0}", filehash_str));

            var hashesprblock = blocksize / (blockhasher.HashSize / 8);

            using(var mru = new CompressedFileMRUCache(options))
            {
                Console.WriteLine("Building lookup table for file hashes");
                var lookup = new HashLookupHelper(ixfile, mru, (int)blocksize, blockhasher.HashSize / 8);

                var filecount = 0L;
                string largestprefix = null;
                string[] largestprefixparts = null;

                if (!string.IsNullOrWhiteSpace(targetpath))
                    Console.WriteLine("Computing restore path");
                
                foreach(var f in List.EnumerateFilesInDList(filelist, filter, options))
                {
                    if (largestprefix == null)
                    {
                        largestprefix = f.Path;
                        largestprefixparts = largestprefix.Split(new char[] { Path.DirectorySeparatorChar });
                    }
                    else if (largestprefix.Length > 1)
                    {
                        var parts = f.Path.Split(new char[] { Path.DirectorySeparatorChar });

                        var ni = 0;
                        for(; ni < Math.Min(parts.Length, largestprefixparts.Length); ni++)
                            if (!Library.Utility.Utility.ClientFilenameStringComparer.Equals(parts[ni], largestprefixparts[ni]))
                                break;

                        if (ni != largestprefixparts.Length)
                        {
                            if (ni == 0)
                            {
                                largestprefixparts = new string[0];
                                largestprefix = string.Empty;
                            }
                            else
                            {
                                Array.Resize(ref largestprefixparts, ni - 1);
                                largestprefix = string.Join(Path.DirectorySeparatorChar.ToString(), largestprefixparts);
                            }
                        }
                    }
                    filecount++;
                }

                Console.WriteLine("Restoring {0} files to {1}", filecount, string.IsNullOrWhiteSpace(targetpath) ? "original position" : targetpath);

                if (Library.Utility.Utility.IsClientLinux || largestprefix.Length > 0)
                    largestprefix = Library.Utility.Utility.AppendDirSeparator(largestprefix);

                if (!string.IsNullOrEmpty(largestprefix))
                    Console.WriteLine("Removing common prefix {0} from files", largestprefix);

                var i = 0L;
                var errors = 0L;
                foreach(var f in List.EnumerateFilesInDList(filelist, filter, options))
                {
                    try
                    {
                        var targetfile = MapToRestorePath(f.Path, largestprefix, targetpath);
                        if (!Directory.Exists(Path.GetDirectoryName(targetfile)))
                            Directory.CreateDirectory(Path.GetDirectoryName(targetfile));
                            
                        Console.Write("{0}: {1} ({2})", i, targetfile, Library.Utility.Utility.FormatSizeString(f.Size));

                        using(var tf = new Library.Utility.TempFile())
                        {
                            using(var sw = File.OpenWrite(tf))
                            {
                                if (f.BlocklistHashes == null)
                                {
                                    lookup.WriteHash(sw, f.Hash);
                                }
                                else
                                {
                                    var blhi = 0L;
                                    foreach(var blh in f.BlocklistHashes)
                                    {
                                        Console.Write(" {0}", blhi);
                                        var blockhashoffset = blhi * hashesprblock * blocksize;

                                        try
                                        {
                                            var bi = 0;
                                            foreach(var h in lookup.ReadBlocklistHashes(blh))
                                            {
                                                try
                                                {
                                                    sw.Position = blockhashoffset + (bi * blocksize);
                                                    lookup.WriteHash(sw, h);
                                                }
                                                catch(Exception ex)
                                                {
                                                    Console.WriteLine("Failed to read hash: {0}{1}{2}", h, Environment.NewLine, ex.ToString());
                                                }

                                                bi++;
                                            }
                                        }
                                        catch (Exception ex)
                                        {
                                            Console.WriteLine("Failed to read Blocklist hash: {0}{1}{2}", blh, Environment.NewLine, ex.ToString());
                                        }

                                        blhi++;
                                    }
                                }
                            }
                                
                            string fh;
                            using(var fs = File.OpenRead(tf))
                                fh = Convert.ToBase64String(filehasher.ComputeHash(fs));

                            if (fh == f.Hash)
                            {
                                Console.WriteLine(" done!");
                                File.Copy(tf, targetfile, true);
                            }
                            else
                            {
                                Console.Write(" - Restored file hash mismatch");
                                if (File.Exists(targetfile))
                                    Console.WriteLine(" - not overwriting existing file: {0}", targetfile);
                                else
                                    Console.WriteLine(" - restoring file in damaged condition");


                            }
                        }

                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(" error: {0}", ex.ToString());
                        errors++;
                    }
                    i++;
                }
            }

            return 0;
        }
Example #8
0
        public static int Run(List<string> args, Dictionary<string, string> options, Library.Utility.IFilter filter)
        {
            if (args.Count != 3)
            {
                Console.WriteLine("Invalid argument count ({0} expected 3): {1}{2}", args.Count, Environment.NewLine, string.Join(Environment.NewLine, args));
                return 100;
            }

            using(var backend = Library.DynamicLoader.BackendLoader.GetBackend(args[1], options))
            {
                if (backend == null)
                {
                    Console.WriteLine("Backend not found: {0}{1}Backends supported: {2}", args[1], Environment.NewLine, string.Join(", ", Library.DynamicLoader.BackendLoader.Keys));
                    return 100;
                }

                var targetfolder = Path.GetFullPath(args[2]);

                if (!Directory.Exists(args[2]))
                {
                    Console.WriteLine("Creating target folder: {0}", targetfolder);
                    Directory.CreateDirectory(targetfolder);
                }

                Console.WriteLine("Listing files on backend: {0} ...", backend.ProtocolKey);

                var lst = backend.List();

                Console.WriteLine("Found {0} files", lst.Count);

                var i = 0;
                var downloaded = 0;
                var errors = 0;
                var needspass = 0;
                string passphrase;
                options.TryGetValue("passphrase", out passphrase);

                foreach(var file in lst)
                {
                    try
                    {
                        Console.Write("{0}: {1}", i, file.Name);
                        var p = Duplicati.Library.Main.Volumes.VolumeBase.ParseFilename(file);
                        if (p == null)
                        {
                            Console.WriteLine(" - Not a Duplicati file, ignoring");
                            continue;
                        }

                        var local = Path.Combine(targetfolder, file.Name);
                        if (p.EncryptionModule != null)
                        {
                            if (string.IsNullOrWhiteSpace(passphrase))
                            {
                                needspass++;
                                Console.WriteLine(" - No passphrase supplied, skipping");
                                continue;
                            }

                            local = local.Substring(0, local.Length - p.EncryptionModule.Length - 1);
                        }

                        if (p.FileType != Duplicati.Library.Main.RemoteVolumeType.Blocks && p.FileType != Duplicati.Library.Main.RemoteVolumeType.Files)
                        {
                            Console.WriteLine(" - Filetype {0}, skipping", p.FileType);
                            continue;
                        }

                        if (File.Exists(local))
                        {
                            Console.WriteLine(" - Already exists, skipping");
                            continue;
                        }

                        Console.Write(" - downloading ({0})...", Library.Utility.Utility.FormatSizeString(file.Size));

                        using(var tf = new Library.Utility.TempFile())
                        {
                            backend.Get(file.Name, tf);

                            if (p.EncryptionModule != null)
                            {
                                Console.Write(" - decrypting ...");
                                using(var m = Library.DynamicLoader.EncryptionLoader.GetModule(p.EncryptionModule, passphrase, options))
                                using(var tf2 = new Library.Utility.TempFile())
                                {
                                    m.Decrypt(tf, tf2);
                                    File.Copy(tf2, local);
                                }
                            }
                            else
                                File.Copy(tf, local);
                        }

                        Console.WriteLine(" done!");

                    }
                    catch(Exception ex)
                    {
                        Console.WriteLine(" error: {0}", ex.ToString());
                        errors++;
                    }

                    i++;
                }

                if (needspass > 0 && downloaded == 0)
                {
                    Console.WriteLine("No files downloaded, try adding --passphrase to decrypt files");
                    return 100;
                }

                Console.WriteLine("Download complete, of {0} remote files, {1} were downloaded with {2} errors", lst.Count, downloaded, errors);
                if (needspass > 0)
                    Console.WriteLine("Additonally {0} remote files were skipped because of encryption, supply --passphrase to download those");

                if (errors > 0)
                    return 200;
                else
                    return 0;

            }
        }
Example #9
0
        public static int Run(List<string> args, Dictionary<string, string> options, Library.Utility.IFilter filter)
        {
            if (args.Count != 2)
            {
                Console.WriteLine("Invalid argument count ({0} expected 2): {1}{2}", args.Count, Environment.NewLine, string.Join(Environment.NewLine, args));
                return 100;
            }

            var folder = Path.GetFullPath(args[1]);

            if (!Directory.Exists(folder))
            {
                Console.WriteLine("Folder not found: {0}", folder);
                return 100;
            }

            Directory.SetCurrentDirectory(folder);

            string ixfile;
            options.TryGetValue("indexfile", out ixfile);
            if (string.IsNullOrWhiteSpace(ixfile))
                ixfile = "index.txt";

            ixfile = Path.GetFullPath(ixfile);
            if (!File.Exists(ixfile))
            {
                using(File.Create(ixfile))
                {
                }
            }
            else
            {
                Console.WriteLine("Sorting existing index file");
                SortFile(ixfile, ixfile);
            }

            var filecount = Directory.EnumerateFiles(folder).Count();

            Console.WriteLine("Processing {0} files", filecount);

            var i = 0;
            var errors = 0;
            var totalblocks = 0L;
            var files = 0;
            foreach(var file in Directory.EnumerateFiles(folder))
            {
                Console.Write("{0}: {1}", i, file);

                try
                {
                    var p = Duplicati.Library.Main.Volumes.VolumeBase.ParseFilename(file);
                    if (p == null)
                    {
                        Console.WriteLine(" - Not a Duplicati file, ignoring");
                        continue;
                    }

                    if (p.FileType != Duplicati.Library.Main.RemoteVolumeType.Blocks)
                    {
                        Console.WriteLine(" - Filetype {0}, skipping", p.FileType);
                        continue;
                    }

                    if (!string.IsNullOrWhiteSpace(p.EncryptionModule))
                    {
                        Console.WriteLine(" - Encrypted, skipping");
                        continue;
                    }

                    var filekey = Path.GetFileName(file);

                    var blocks = 0;
                    using(var cp = Library.DynamicLoader.CompressionLoader.GetModule(p.CompressionModule, file, options))
                    using(var tf = new Library.Utility.TempFile())
                    {
                        using(var sw = new StreamWriter(tf))
                            foreach(var f in cp.ListFiles(null))
                            {
                                sw.WriteLine("{0}, {1}", Library.Utility.Utility.Base64UrlToBase64Plain(f), filekey);
                                blocks++;
                            }

                        files++;
                        totalblocks += blocks;

                        Console.Write(" {0} hashes found, sorting ...", blocks);

                        SortFile(tf, tf);

                        Console.WriteLine(" done!");

                        Console.Write("Merging {0} hashes ...", totalblocks);

                        MergeFiles(ixfile, tf, ixfile);

                        Console.WriteLine(" done!");
                    }
                }
                catch(Exception ex)
                {
                    Console.WriteLine(" error: {0}", ex.ToString());
                    errors++;
                }

                i++;
            }

            Console.WriteLine("Processed {0} files and found {1} hashes", files, totalblocks);
            if (errors > 0)
                Console.WriteLine("Experienced {0} errors", errors);

            return 0;
        }
Example #10
0
        public static int Run(List<string> args, Dictionary<string, string> options, Library.Utility.IFilter filter)
        {
            if (args.Count != 4)
            {
                Console.WriteLine("Invalid argument count ({0} expected 4): {1}{2}", args.Count, Environment.NewLine, string.Join(Environment.NewLine, args));
                return 100;
            }

            string target_compr_module = args[1];

            if (!Library.DynamicLoader.CompressionLoader.Keys.Contains(target_compr_module))
            {
                Console.WriteLine("Target compression module not found: {0}{1}Modules supported: {2}", args[1], Environment.NewLine, string.Join(", ", Library.DynamicLoader.CompressionLoader.Keys));
                return 100;
            }

            var m_Options = new Options(options);

            using (var backend = Library.DynamicLoader.BackendLoader.GetBackend(args[2], options))
            {
                if (backend == null)
                {
                    Console.WriteLine("Backend not found: {0}{1}Backends supported: {2}", args[2], Environment.NewLine, string.Join(", ", Library.DynamicLoader.BackendLoader.Keys));
                    return 100;
                }

                var targetfolder = Path.GetFullPath(args[3]);

                if (!Directory.Exists(args[3]))
                {
                    Console.WriteLine("Creating target folder: {0}", targetfolder);
                    Directory.CreateDirectory(targetfolder);
                }

                Console.WriteLine("Listing files on backend: {0} ...", backend.ProtocolKey);

                var rawlist = backend.List();

                Console.WriteLine("Found {0} files", rawlist.Count);

                var i = 0;
                var downloaded = 0;
                var errors = 0;
                var needspass = 0;

                var remotefiles =
                    (from x in rawlist
                     let n = VolumeBase.ParseFilename(x)
                     where n != null && n.Prefix == m_Options.Prefix
                     select n).ToArray(); //ToArray() ensures that we do not remote-request it multiple times

                if (remotefiles.Length == 0)
                {
                    if (rawlist.Count == 0)
                        Console.WriteLine("No files were found at the remote location, perhaps the target url is incorrect?");
                    else
                    {
                        var tmp =
                            (from x in rawlist
                             let n = VolumeBase.ParseFilename(x)
                             where
                                 n != null
                             select n.Prefix).ToArray();

                        var types = tmp.Distinct().ToArray();
                        if (tmp.Length == 0)
                            Console.WriteLine("Found {0} files at the remote storage, but none that could be parsed", rawlist.Count);
                        else if (types.Length == 1)
                            Console.WriteLine("Found {0} parse-able files with the prefix {1}, did you forget to set the backup-prefix?", tmp.Length, types[0]);
                        else
                            Console.WriteLine("Found {0} parse-able files (of {1} files) with different prefixes: {2}, did you forget to set the backup-prefix?", tmp.Length, rawlist.Count, string.Join(", ", types));
                    }

                    return 100;
                }

                bool reencrypt = Library.Utility.Utility.ParseBoolOption(options, "reencrypt");
                bool reupload = Library.Utility.Utility.ParseBoolOption(options, "reupload");

                foreach (var entry in remotefiles)
                {
                    try
                    {
                        Console.Write("{0}: {1}", i, entry.File.Name);

                        var local = Path.Combine(targetfolder, entry.File.Name);
                        if (entry.EncryptionModule != null)
                        {
                            if (string.IsNullOrWhiteSpace(m_Options.Passphrase))
                            {
                                needspass++;
                                Console.WriteLine(" - No passphrase supplied, skipping");
                                continue;
                            }

                            local = local.Substring(0, local.Length - entry.EncryptionModule.Length - 1);
                        }

                        if (entry.CompressionModule == target_compr_module)
                        {
                            Console.WriteLine(" - compression types are same");
                            continue;
                        }

                        string localNew;

                        if (entry.CompressionModule != null)
                        {
                            localNew = local.Substring(0, local.Length - entry.CompressionModule.Length - 1) + "." + target_compr_module;

                            if (File.Exists(localNew))
                            {
                                Console.WriteLine(" - target file already exist");
                                continue;
                            }
                        }
                        else
                        {
                            Console.WriteLine(" - cannot detect compression type");
                            continue;
                        }

                        if (File.Exists(local))
                            File.Delete(local);

                        Console.Write(" - downloading ({0})...", Library.Utility.Utility.FormatSizeString(entry.File.Size));

                        DateTime originLastWriteTime;
                        FileInfo destinationFileInfo;

                        using (var tf = new Library.Utility.TempFile())
                        {
                            backend.Get(entry.File.Name, tf);
                            originLastWriteTime = new FileInfo(tf).LastWriteTime;
                            downloaded++;

                            if (entry.EncryptionModule != null)
                            {
                                Console.Write(" decrypting ...");
                                using (var m = Library.DynamicLoader.EncryptionLoader.GetModule(entry.EncryptionModule, m_Options.Passphrase, options))
                                using (var tf2 = new Library.Utility.TempFile())
                                {
                                    m.Decrypt(tf, tf2);
                                    File.Copy(tf2, local);
                                    File.Delete(tf2);
                                }
                            }
                            else
                                File.Copy(tf, local);

                            File.Delete(tf);
                            destinationFileInfo = new FileInfo(local);
                            destinationFileInfo.LastWriteTime = originLastWriteTime;
                        }

                        if (entry.CompressionModule != null)
                        {
                            Console.Write(" recompressing ...");

                            using (var cmOld = Library.DynamicLoader.CompressionLoader.GetModule(entry.CompressionModule, local, options))
                            using (var cmNew = Library.DynamicLoader.CompressionLoader.GetModule(target_compr_module, localNew, options))
                                foreach (var cmfile in cmOld.ListFiles(""))
                                {
                                    string cmfileNew = cmfile;

                                    if (entry.FileType == RemoteVolumeType.Index)
                                    {
                                        var cmFileVolume = Library.Main.Volumes.VolumeBase.ParseFilename(cmfileNew);
                                        if (cmFileVolume != null)
                                        {
                                            cmfileNew = cmfileNew.Replace("." + cmFileVolume.CompressionModule, "." + target_compr_module);
                                            if(!reencrypt)
                                                cmfileNew = cmfileNew.Replace("." + cmFileVolume.EncryptionModule, "");
                                        }
                                    }

                                    using (var sourceStream = cmOld.OpenRead(cmfile))
                                        using (var cs = cmNew.CreateFile(cmfileNew, Duplicati.Library.Interface.CompressionHint.Compressible, cmOld.GetLastWriteTime(cmfile)))
                                            Library.Utility.Utility.CopyStream(sourceStream, cs);
                                }

                            File.Delete(local);
                            destinationFileInfo = new FileInfo(localNew);
                            destinationFileInfo.LastWriteTime = originLastWriteTime;
                        }

                        if (reencrypt && entry.EncryptionModule != null)
                        {
                            Console.Write(" reencrypting ...");
                            using (var m = Library.DynamicLoader.EncryptionLoader.GetModule(entry.EncryptionModule, m_Options.Passphrase, options))
                            {
                                m.Encrypt(localNew, localNew + "." + m.FilenameExtension);
                                File.Delete(localNew);
                                localNew = localNew + "." + m.FilenameExtension;
                            }

                            destinationFileInfo = new FileInfo(localNew);
                            destinationFileInfo.LastWriteTime = originLastWriteTime;
                        }

                        if (reupload)
                        {
                            backend.Put((new FileInfo(localNew)).Name, localNew);
                            backend.Delete(entry.File.Name);
                            File.Delete(localNew);
                        }

                        Console.WriteLine(" done!");

                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(" error: {0}", ex.ToString());
                        errors++;
                    }

                    i++;
                }

                if (reupload)
                {
                    var remoteverificationfileexist = rawlist.Any(x => x.Name == (m_Options.Prefix + "-verification.json"));

                    if (remoteverificationfileexist)
                    {
                        Console.WriteLine("Found verification file {0} - deleting", m_Options.Prefix + "-verification.json");
                        backend.Delete(m_Options.Prefix + "-verification.json");
                    }
                }

                if (needspass > 0 && downloaded == 0)
                {
                    Console.WriteLine("No files downloaded, try adding --passphrase to decrypt files");
                    return 100;
                }

                Console.WriteLine("Download complete, of {0} remote files, {1} were downloaded with {2} errors", remotefiles.Count(), downloaded, errors);
                if (needspass > 0)
                    Console.WriteLine("Additonally {0} remote files were skipped because of encryption, supply --passphrase to download those");

                if (errors > 0)
                {
                    Console.WriteLine("There were errors during recompress of remote backend files!");
                    return 200;
                }

                return 0;
            }
        }