public AppTransferor(AppData appData)
        {
            AppData  = appData;
            DestPath = default(string);
            SrcData  = new List <Tuple <string, string, string, bool> >();
            UserData = Tuple.Create(default(string), default(string));

            var downloadCollection = AppData.DownloadCollection;
            var packageVersion     = default(string);

            if (ActionGuid.IsUpdateInstance && AppData?.UpdateCollection?.SelectMany(x => x.Value).All(x => x?.Item1?.StartsWithEx("http") == true) == true)
            {
                var appIniDir  = Path.Combine(appData.InstallDir, "App", "AppInfo");
                var appIniPath = Path.Combine(appIniDir, "appinfo.ini");
                if (!File.Exists(appIniPath))
                {
                    appIniPath = Path.Combine(appIniDir, "plugininstaller.ini");
                }
                packageVersion = Ini.Read("Version", nameof(appData.PackageVersion), default(string), appIniPath);
                if (!string.IsNullOrEmpty(packageVersion) && AppData?.UpdateCollection?.ContainsKey(packageVersion) == true)
                {
                    downloadCollection = AppData.UpdateCollection;
                }
            }

            foreach (var pair in downloadCollection)
            {
                if (!pair.Key.EqualsEx(AppData.Settings.ArchiveLang) && (string.IsNullOrEmpty(packageVersion) || !pair.Key.EqualsEx(packageVersion)))
                {
                    continue;
                }

                foreach (var tuple in pair.Value)
                {
                    if (DestPath == default(string))
                    {
                        if (!DirectoryEx.Create(Settings.TransferDir))
                        {
                            continue;
                        }
                        var fileName = Path.GetFileName(tuple.Item1);
                        if (string.IsNullOrEmpty(fileName))
                        {
                            continue;
                        }
                        DestPath = PathEx.Combine(Settings.TransferDir, fileName);
                    }

                    var           shortHost = NetEx.GetShortHost(tuple.Item1);
                    var           redirect  = Settings.ForceTransferRedirection || !NetEx.IPv4IsAvalaible && !string.IsNullOrWhiteSpace(shortHost) && !shortHost.EqualsEx(AppSupplierHosts.Internal);
                    string        userAgent;
                    List <string> mirrors;
                    switch (shortHost)
                    {
                    case AppSupplierHosts.Internal:
                        userAgent = UserAgents.Internal;
                        mirrors   = AppSupply.GetMirrors(AppSuppliers.Internal);
                        break;

                    case AppSupplierHosts.PortableApps:
                        userAgent = UserAgents.Empty;
                        mirrors   = AppSupply.GetMirrors(AppSuppliers.PortableApps);
                        break;

                    case AppSupplierHosts.SourceForge:
                        userAgent = UserAgents.Default;
                        mirrors   = AppSupply.GetMirrors(AppSuppliers.SourceForge);
                        break;

                    default:
                        userAgent = UserAgents.Default;
                        var srcUrl = tuple.Item1;
                        if (AppData.ServerKey != default(byte[]))
                        {
                            foreach (var srv in Shareware.GetAddresses())
                            {
                                if (Shareware.FindAddressKey(srv) != AppData.ServerKey.Encode(BinaryToTextEncodings.Base85))
                                {
                                    continue;
                                }
                                if (!srcUrl.StartsWithEx("http://", "https://"))
                                {
                                    srcUrl = PathEx.AltCombine(srv, srcUrl);
                                }
                                UserData = Tuple.Create(Shareware.GetUser(srv), Shareware.GetPassword(srv));
                                break;
                            }
                        }
                        SrcData.Add(Tuple.Create(srcUrl, tuple.Item2, userAgent, false));
                        continue;
                    }

                    var sHost = NetEx.GetShortHost(tuple.Item1);
                    var fhost = tuple.Item1.Substring(0, tuple.Item1.IndexOf(sHost, StringComparison.OrdinalIgnoreCase) + sHost.Length);
                    foreach (var mirror in mirrors)
                    {
                        var srcUrl = tuple.Item1;
                        if (!fhost.EqualsEx(mirror))
                        {
                            srcUrl = tuple.Item1.Replace(fhost, mirror);
                        }
                        if (SrcData.Any(x => x.Item1.EqualsEx(srcUrl)))
                        {
                            continue;
                        }
                        if (redirect)
                        {
                            userAgent = UserAgents.Internal;
                            srcUrl    = CorePaths.RedirectUrl + srcUrl.Encode();
                        }
                        SrcData.Add(Tuple.Create(srcUrl, tuple.Item2, userAgent, false));
                        if (Log.DebugMode > 1)
                        {
                            Log.Write($"Transfer: '{srcUrl}' has been added.");
                        }
                    }
                }
                break;
            }
            Transfer = new NetEx.AsyncTransfer();
        }