Exemple #1
0
        public IReadOnlyList <FileDiff> compare(IReadOnlyList <FreezeFile> local, IReadOnlyList <FreezeFile> provider)
        {
            List <FileDiff> files = new List <FileDiff>();

            maxTasks = IOUtils.DefaultTasks(maxTasks);

            var dels =
                from pf in provider
                where local.Where((x) => string.Compare(x.path, pf.path, true) == 0).Any() == false
                select new FileDiff {
                local = null, remote = pf, type = DiffType.deleted
            };

            files.AddRange(dels);

            var creates =
                from lf in local
                where provider.Where((x) => string.Compare(x.path, lf.path, true) == 0).Any() == false
                select new FileDiff {
                local = lf, remote = null, type = DiffType.created
            };

            files.AddRange(creates);

            IEnumerable <FileDiff> updates = null;

            if (usehash)
            {
                var lst =
                    from lf in local
                    join pf in provider on lf.path equals pf.path
                    select new FileDiff {
                    local = lf, remote = pf
                };

                byte[] keyfile;
                {
                    var kt  = new MemoryStream();
                    var fs  = new FileStream(privateKey, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                    var len = BUCommon.IOUtils.WriteStream(fs, kt).Result;
                    fs.Close();
                    fs.Dispose();
                    fs = null;

                    keyfile = kt.ToArray();
                }

                var tasks = Parallel.ForEach(lst
                                             , new ParallelOptions {
                    MaxDegreeOfParallelism = maxTasks
                }
                                             , () =>
                {
                    var sr  = new StreamReader(new MemoryStream(keyfile, 0, keyfile.Length, false, false));
                    var rsa = KeyLoader.LoadRSAKey(sr);

                    var fe1 = new FileEncrypt(rsa);
                    sr      = null;
                    return(new DiffProcessor.TLocalData {
                        fe = fe1, auth = null
                    });
                }
                                             , (x, pls, tl) =>
                {
                    if (string.IsNullOrWhiteSpace(x.remote.enchash))
                    {
                        x.type = x.local.modified > x.remote.uploaded ? DiffType.updated : DiffType.same;
                    }
                    else
                    {
                        x.type      = DiffType.same;
                        var fstream = x.local.readStream(pathRoot);
                        var hash    = tl.fe.hashContents("SHA1", fstream);

                        var bytes = Convert.FromBase64String(x.remote.enchash);
                        var rhash = tl.fe.decBytes(bytes);
                        for (int i = 0; i < hash.raw.Length; ++i)
                        {
                            if (hash.raw[i] != rhash[i])
                            {
                                x.type = DiffType.updated; break;
                            }
                        }
                    }

                    return(tl);
                }
                                             , (tl) => { tl.fe = null; }
                                             );
            }
            else
            {
                updates =
                    from lf in local
                    join pf in provider on lf.path equals pf.path
                    where lf.modified > pf.uploaded
                    select new FileDiff {
                    local = lf, remote = pf, type = DiffType.updated
                };
            }

            files.AddRange(updates);

            return(files);
        }
        public void run()
        {
            byte[] keyfile;
            {
                var kt  = new MemoryStream();
                var fs  = new FileStream(encKey, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                var len = BUCommon.IOUtils.WriteStream(fs, kt).Result;
                fs.Close();
                fs.Dispose();
                fs = null;

                keyfile = kt.ToArray();
            }

            if (maxTasks <= 0 || maxTasks > 100)
            {
                maxTasks = 0;
            }
            if (noAction)
            {
                maxTasks = 1;
                runType  = RunType.none;
            }

            var service = account.service;
            var cache   = service.fileCache;

            var tasks = Parallel.ForEach(_diffs
                                         , new ParallelOptions {
                MaxDegreeOfParallelism = maxTasks
            }
                                         , () =>
            {
                var sr  = new StreamReader(new MemoryStream(keyfile, 0, keyfile.Length, false, false));
                var rsa = KeyLoader.LoadRSAKey(sr);

                var fe1   = new FileEncrypt(rsa);
                sr        = null;
                object td = null;
                if (!noAction)
                {
                    td = service.threadStart();
                }
                return(new TLocalData {
                    fe = fe1, auth = td
                });
            }
                                         , (x, pls, tl) =>
            {
                progressHandler?.Invoke(x);

                string path = string.Empty;

                FileStream filestrm = null;
                try {
                    switch (runType)
                    {
                    case RunType.upload:
                        {
                            path = x.local.path.Replace('/', Path.DirectorySeparatorChar);
                            path = Path.Combine(root, path);

                            switch (x.type)
                            {
                            case DiffType.deleted:
                                {
                                    service.delete(x.remote);
                                    lock (cache) { cache.delete(x.remote); }
                                    break;
                                }

                            case DiffType.created:
                            case DiffType.updated:
                                {
                                    filestrm = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
                                    var hash = tl.fe.hashContents(filestrm);
                                    /* since we're reading anyways, populate the file hash. */
                                    x.local.localHash = hash;

                                    var memstrm = tl.fe.encrypt(filestrm);
                                    memstrm.Seek(0, System.IO.SeekOrigin.Begin);
                                    x.local.localHash = tl.fe.hashContents("SHA1", memstrm);
                                    memstrm.Seek(0, System.IO.SeekOrigin.Begin);

                                    byte[] buf = tl.fe.encBytes(x.local.localHash.raw);
                                    var b64    = Convert.ToBase64String(buf);
                                    var ff     = service.uploadFile(tl.auth, container, x.local, memstrm, b64);
                                    memstrm.Dispose();
                                    memstrm = null;

                                    if (ff == null)
                                    {
                                        errorHandler?.Invoke(x, new Exception("Failed to proces!"));
                                    }
                                    else
                                    {
                                        ff.localHash = x.local.localHash;
                                        lock (cache)
                                        {
                                            cache.add(x.local);
                                            cache.add(ff);
                                        }
                                    }
                                    break;
                                }
                            }
                            break;
                        }

                    case RunType.download:
                        {
                            if (x.type == DiffType.created || x.type == DiffType.updated)
                            {
                                /* this really needs to check to see if we need to download it.
                                 * that will make it resumeable.
                                 */
                                path = Path.Combine(root, x.remote.path.Replace('/', Path.DirectorySeparatorChar));

                                {
                                    /* need to make sure the download directory parts exist before we download and save the file. */
                                    var pathfname = Path.GetFileName(path);
                                    var pathpart  = path.Substring(0, path.Length - pathfname.Length);
                                    System.IO.Directory.CreateDirectory(pathpart);
                                }

                                var strm = service.downloadFile(tl.auth, x.remote);
                                filestrm = new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite | FileShare.Delete);
                                tl.fe.decrypt(strm, filestrm);
                                strm.Dispose();
                                strm = null;

                                var hash = tl.fe.hashContents(filestrm);

                                x.remote.localHash = hash;
                                lock (cache) { cache.add(x.remote); }

                                filestrm.Close();
                                filestrm.Dispose();
                                filestrm = null;
                            }

                            break;
                        }

                    case RunType.none: { break; }
                    }
                }
                catch (Exception e)
                {
                    errorHandler?.Invoke(x, e);
                    pls.Stop();
                    throw new ArgumentException(string.Format("Error processing file diff item. {0} - {1}", x.type
                                                              , (x.local != null ? x.local.path : x.remote.path))
                                                , e);
                }
                return(tl);
            }
                                         , x => { if (!noAction)
                                                  {
                                                      service.threadStop(x.auth);
                                                  }
                                         }
                                         );

            _diffs.Clear();
        }