internal DirMapping(CryptExecutionContext ctx, DirectoryInfo src, DirectoryInfo dest, XElement xml = null) { this.CONTEXT = ctx.Clone(); this.DESTINATION = dest; this.SOURCE = src; this.XML = xml; switch (this.CONTEXT.Mode) { case RunningMode.Decrypt: this.TASK = new Task(this.TaskAction_Decrypt); break; case RunningMode.Encrypt: this.TASK = new Task(this.TaskAction_Encrypt); break; } }
internal static Task CreateEncryptionTask(CryptExecutionContext orgCtx, DirectoryInfo src, DirectoryInfo dest) { var ctxClone = orgCtx.Clone(); ctxClone.Source = src; ctxClone.Destination = dest; return(new Task((state) => { var ctx = (CryptExecutionContext)state; ctx.Destination.CreateDirectoryDeep(); var metaFile = new FileInfo(Path.Combine(ctx.Destination.FullName, AppGlobals.FILENAME_META)); var metaXmlDoc = new XDocument(new XDeclaration("1.0", Encoding.UTF8.WebName, "yes")); metaXmlDoc.Add(new XElement("dir")); metaXmlDoc.Root.SetAttributeValue("name", ctx.Source.Name); // encrypt files FileMapping[] fileMappings; { ulong index = 1; fileMappings = ctx.Source .GetFiles() .Randomize(_RANDOM) .Select(file => new FileMapping(ctx, file, new FileInfo(Path.Combine(ctx.Destination.FullName, string.Format("{0}.bin", index++))))) .ToArray(); foreach (var fm in fileMappings) { fm.TASK.Start(); } TaskHelper.WaitAll(fileMappings.Select(m => m.TASK)); } // handle sub directories DirMapping[] dirMappings; { ulong index = 1; dirMappings = ctx.Source .GetDirectories() .Randomize(_RANDOM) .Select(dir => new DirMapping(ctx, dir, new DirectoryInfo(Path.Combine(ctx.Destination.FullName, (index++).ToString())))) .ToArray(); foreach (var dm in dirMappings) { dm.TASK.Start(); } TaskHelper.WaitAll(dirMappings.Select(m => m.TASK)); } if (dirMappings.Length > 0) { var dirsElement = new XElement("dirs"); foreach (var dm in dirMappings.Randomize(_RANDOM)) { var newDirElement = new XElement("dir"); newDirElement.SetAttributeValue("name", dm.SOURCE.Name); newDirElement.SetAttributeValue("alias", dm.DESTINATION.Name); newDirElement.SetAttributeValue("lastWrite", dm.SOURCE.LastWriteTimeUtc.Ticks); newDirElement.SetAttributeValue("created", dm.SOURCE.CreationTimeUtc.Ticks); dirsElement.Add(newDirElement); } metaXmlDoc.Root.Add(dirsElement); } if (fileMappings.Length > 0) { var filesElement = new XElement("files"); foreach (var fm in fileMappings.Randomize(_RANDOM)) { var newFileElement = new XElement("file"); newFileElement.SetAttributeValue("name", fm.SOURCE.Name); newFileElement.SetAttributeValue("alias", fm.DESTINATION.Name); newFileElement.SetAttributeValue("len", fm.SOURCE.Length); newFileElement.SetAttributeValue("pwd", Convert.ToBase64String(fm.PASSWORD)); newFileElement.SetAttributeValue("lastWrite", fm.SOURCE.LastWriteTimeUtc.Ticks); newFileElement.SetAttributeValue("created", fm.SOURCE.CreationTimeUtc.Ticks); filesElement.Add(newFileElement); } metaXmlDoc.Root.Add(filesElement); } using (var srcStream = new MemoryStream()) { metaXmlDoc.Save(srcStream); srcStream.Position = 0; using (var destStream = new FileStream(metaFile.FullName, FileMode.CreateNew, FileAccess.ReadWrite)) { EncryptionHelper.EncryptStream(srcStream, destStream, ctx.Password, ctx.Salt); } } FileSystemHelper.TrySetTimestampsUtc(metaFile, ctx.StartTime); }, ctxClone)); }
internal static Task CreateDecryptionTask(CryptExecutionContext orgCtx, DirectoryInfo src, DirectoryInfo dest, XElement xml) { var ctxClone = orgCtx.Clone(); ctxClone.Source = src; ctxClone.Destination = dest; return(new Task((state) => { var ctx = (CryptExecutionContext)state; ctx.Destination.CreateDirectoryDeep(); var metaFile = CollectionHelper.SingleOrDefault(ctx.Source.GetFiles(), f => AppGlobals.FILENAME_META == f.Name.ToLower().Trim()); if (metaFile != null) { XDocument metaXmlDoc; using (var srcStream = metaFile.OpenRead()) { using (var temp = new MemoryStream()) { DecryptionHelper.DecryptStream(srcStream, temp, ctx.Password, ctx.Salt); temp.Position = 0; metaXmlDoc = XDocument.Load(temp); } } // files { var fileMappings = metaXmlDoc.XPathSelectElements("//dir/files/file") .Select(fe => { return new FileMapping(ctx: ctx, src: new FileInfo(Path.Combine(ctx.Source.FullName, fe.Attribute("alias").Value.Trim())), dest: new FileInfo(Path.Combine(ctx.Destination.FullName, fe.Attribute("name").Value.Trim())), xml: fe); }).ToArray(); foreach (var fm in fileMappings) { fm.TASK.Start(); } TaskHelper.WaitAll(fileMappings.Select(fm => fm.TASK)); } // directories { var dirMappings = metaXmlDoc.XPathSelectElements("//dir/dirs/dir") .Select(de => { return new DirMapping(ctx: ctx, src: new DirectoryInfo(Path.Combine(ctx.Source.FullName, de.Attribute("alias").Value.Trim())), dest: new DirectoryInfo(Path.Combine(ctx.Destination.FullName, de.Attribute("name").Value.Trim())), xml: de); }).ToArray(); foreach (var dm in dirMappings) { dm.TASK.Start(); } TaskHelper.WaitAll(dirMappings.Select(dm => dm.TASK)); } if (xml != null) { FileSystemHelper.TrySetCreationTimeUtc(ctx.Destination, new DateTimeOffset(ticks: long.Parse(xml.Attribute("created").Value.Trim()), offset: TimeSpan.Zero)); FileSystemHelper.TrySetLastWriteTimeUtc(ctx.Destination, new DateTimeOffset(ticks: long.Parse(xml.Attribute("lastWrite").Value.Trim()), offset: TimeSpan.Zero)); } } else { //TODO show warning } }, ctxClone)); }