Exemplo n.º 1
0
            private async Task FetchTheItemAsync(DataSourceFetche fetch, FileDetails details, DataSourceFetchItem.DataSourceFetchItemTypes dataSourceFetchItemType, DataSourceFetchItem parentFetchItem, Func <FileDetails, Task <string> > fetchAsync)
            {
                string tfn  = null;
                var    item = new DataSourceFetchItem
                {
                    DataSourceFetch           = fetch,
                    DataSourceFetchItemType   = dataSourceFetchItemType,
                    ParentDataSourceFetchItem = parentFetchItem,
                    Size = details.Size,
                    Name = details.Name,
                };

                item.DataSourceFetchItemProperties.LastModifiedAtUtc = details.LastModifiedAtUtc;
                item.DataSourceFetchItemProperties.ContentMD5        = details.ContentMD5;
                item.DataSourceFetchItemProperties.ETag = details.ETag;
                try
                {
                    Trace.WriteLine($"Checking {details.FullName} size={details.Size} LastWriteTimeUtc={details.LastModifiedAtUtc}");
                    var sameDataSourceReplicatedDataSourceFetchItem = FindEvidenceItems(details.CreateEvidence()).FirstOrDefault();
                    if (sameDataSourceReplicatedDataSourceFetchItem != null)
                    {
                        item.DataSourceFetchItemType = DataSourceFetchItem.DataSourceFetchItemTypes.Duplicate;
                        item.SameDataSourceReplicatedDataSourceFetchItem = sameDataSourceReplicatedDataSourceFetchItem;
                        return;
                    }
                    //                      Logger.LogInformation("Downloading", file.FullName, file.Length, tfn);
                    tfn = await fetchAsync(details);

                    using (var st = File.OpenRead(tfn))
                    {
                        item.Size = st.Length;
                        using (var muxer = new StreamMuxer(st, true))
                        {
                            var p = new BlobStorageServices.FileProperties
                            {
                                LastModifiedAtUtc = details.LastModifiedAtUtc
                            };
                            p.Metadata[BlobStorageServices.MetaKeyNames.SourcePath]     = details.Folder;
                            p.Metadata[BlobStorageServices.MetaKeyNames.SourceFullName] = details.FullName;
                            var urns = new List <string>();
                            Parallel.ForEach(
                                new[]
                            {
                                Hash.CommonHashAlgorithmNames.Md5,
                                Hash.CommonHashAlgorithmNames.Sha1,
                                Hash.CommonHashAlgorithmNames.Sha512,
                            },
                                hashAlgName =>
                            {
                                var urn = Hash.Compute(muxer.OpenRead(), hashAlgName).Urn;
                                if (urn == null)
                                {
                                    return;                  //yes... in some cases this somehow happens...
                                }
                                urns.Add(urn);
                            });
                            if (urns.Count > 0)
                            {
                                p.Metadata[BlobStorageServices.MetaKeyNames.Urns] = CSV.FormatLine(urns, false);
                                sameDataSourceReplicatedDataSourceFetchItem       = FindEvidenceItems(urns).FirstOrDefault();
                                if (sameDataSourceReplicatedDataSourceFetchItem != null)
                                {
                                    item.DataSourceFetchItemType = DataSourceFetchItem.DataSourceFetchItemTypes.Duplicate;
                                    item.SameDataSourceReplicatedDataSourceFetchItem = sameDataSourceReplicatedDataSourceFetchItem;
                                    return;
                                }
                            }
                            var res = await BlobStorageServices.StoreStreamAsync(
                                Runner.BlobConfig,
                                BlobStorageServices.ContainerNames.Secure,
                                $"{BlobRootPath}{details.Folder.Substring(1)}{details.Name}",
                                muxer.OpenRead(),
                                p,
                                amt => Trace.WriteLine($"Uploading {amt}/{muxer.Length}")
                                );

                            item.DataSourceFetchItemProperties = new DataSourceFetchItemProperties();
                            item.DataSourceFetchItemProperties.Set(p);
                            item.Url = res.Uri.ToString();
                            PopulateEvidence(item);
                        }
                    }
                }
                catch (Exception ex)
                {
                    item.DataSourceFetchItemType             = DataSourceFetchItem.DataSourceFetchItemTypes.Errored;
                    item.DataSourceFetchItemProperties.Error = new ExceptionError(ex);
                    Trace.WriteLine(ex);
                }
                finally
                {
                    if (item != null)
                    {
                        await GdbLocker.GoAsync(async() => {
                            Gdb.DataSourceFetchItems.Add(item);
                            await Gdb.SaveChangesAsync();
                        });
                    }
                }
                var ext = Path.GetExtension(details.Name).ToLower();

                if (ext == ".pgp" || details.Name.ToLower().Contains(".pgp."))
                {
                    var name = details.Name;
                    if (name.ToLower().EndsWith(".pgp"))
                    {
                        name = name.Left(name.Length - 4);
                    }
                    else if (name.ToLower().EndsWith(".pgp.asc"))
                    {
                        name = name.Left(name.Length - 8);
                    }
                    else if (name.ToLower().Contains(".pgp."))
                    {
                        name = new Regex(@"\.pgp\.", RegexOptions.IgnoreCase).Replace(name, ".");
                    }
                    await FetchTheItemAsync(
                        fetch,
                        new FileDetails(details, name),
                        DataSourceFetchItem.DataSourceFetchItemTypes.Decrypted,
                        item,
                        async _ =>
                    {
                        var utfp = Path.GetTempFileName();
                        using (var st = File.OpenRead(tfn))
                        {
                            await Runner.DecryptAsync(st, utfp);
                        }
                        return(utfp);
                    }
                        );
                }
                else if (
                    MimeType.Application.Zip.DoesExtensionMatch(details.Name) &&
                    DS.DataSourceSettings.DecompressItems &&
                    dataSourceFetchItemType != DataSourceFetchItem.DataSourceFetchItemTypes.UnpackedRecompressedSingleton)
                {
                    var relUnzipFolder = Path.GetFileNameWithoutExtension(details.Name);
                    var unzipFolder    = Path.Combine(Path.GetDirectoryName(tfn), relUnzipFolder);
                    using (var st = File.OpenRead(tfn))
                    {
                        using (var za = new ZipArchive(st, ZipArchiveMode.Read))
                        {
                            if (za.Entries.Count < 2)
                            {
                                return;
                            }
                        }
                    }
                    ZipFile.ExtractToDirectory(tfn, unzipFolder);
                    await TaskWhenAllOneAtATime(
                        Directory.GetFiles(unzipFolder, "*.*", SearchOption.AllDirectories).ConvertAll(
                            unzipped =>
                    {
                        string rezipped = unzipped;
                        bool isRezipped = false;
                        if (!MimeType.Application.Zip.DoesExtensionMatch(unzipped))
                        {
                            rezipped = unzipped + MimeType.Application.Zip.PrimaryFileExtension;
                            using (var st = File.Create(rezipped))
                            {
                                using (var za = new ZipArchive(st, ZipArchiveMode.Create))
                                {
                                    za.CreateEntryFromFile(unzipped, Path.GetFileName(unzipped));
                                }
                                isRezipped = true;
                            }
                        }
                        return(FetchTheItemAsync(
                                   fetch,
                                   new FileDetails(new FileInfo(rezipped), Path.Combine(details.Folder, relUnzipFolder)),
                                   isRezipped ? DataSourceFetchItem.DataSourceFetchItemTypes.UnpackedRecompressedSingleton : DataSourceFetchItem.DataSourceFetchItemTypes.Unpacked,
                                   item,
                                   _ => Task.FromResult(rezipped)
                                   ));
                    }));

                    Stuff.Noop();
                }
            }