Ejemplo n.º 1
0
            public int Compare(Type x, Type y)
            {
                ToolAttribute xT = x.GetCustomAttribute <ToolAttribute>();
                ToolAttribute yT = y.GetCustomAttribute <ToolAttribute>();

                return(string.Compare(xT.Keyword, yT.Keyword, StringComparison.InvariantCultureIgnoreCase));
            }
Ejemplo n.º 2
0
        private static void Main()
        {
            Console.OutputEncoding = Encoding.UTF8;

            Files        = new Dictionary <ulong, PackageRecord>();
            TrackedFiles = new Dictionary <ushort, HashSet <ulong> >();

            #region Tool Detection
            HashSet <Type> tools = new HashSet <Type>();
            {
                Assembly    asm   = typeof(ITool).Assembly;
                Type        t     = typeof(ITool);
                List <Type> types = asm.GetTypes().Where(tt => tt != t && t.IsAssignableFrom(tt)).ToList();
                foreach (Type tt in types)
                {
                    ToolAttribute attrib = tt.GetCustomAttribute <ToolAttribute>();
                    if (tt.IsInterface || attrib == null)
                    {
                        continue;
                    }
                    tools.Add(tt);

                    if (attrib.TrackTypes == null)
                    {
                        continue;
                    }
                    foreach (ushort type in attrib.TrackTypes)
                    {
                        if (!TrackedFiles.ContainsKey(type))
                        {
                            TrackedFiles[type] = new HashSet <ulong>();
                        }
                    }
                }
            }
            #endregion

            Flags = FlagParser.Parse <ToolFlags>(() => PrintHelp(tools));
            if (Flags == null)
            {
                return;
            }

            Logger.EXIT = !Flags.GracefulExit;

            ITool     targetTool      = null;
            ICLIFlags targetToolFlags = null;

            #region Tool Activation

            foreach (Type type in tools)
            {
                ToolAttribute attrib = type.GetCustomAttribute <ToolAttribute>();

                if (!string.Equals(attrib.Keyword, Flags.Mode, StringComparison.InvariantCultureIgnoreCase))
                {
                    continue;
                }
                targetTool = Activator.CreateInstance(type) as ITool;

                if (attrib.CustomFlags != null)
                {
                    Type flags = attrib.CustomFlags;
                    if (typeof(ICLIFlags).IsAssignableFrom(flags))
                    {
                        targetToolFlags = typeof(FlagParser).GetMethod("Parse", new Type[] { }).MakeGenericMethod(flags).Invoke(null, null) as ICLIFlags;
                    }
                }
                break;
            }

            #endregion

            if (targetTool == null)
            {
                FlagParser.Help <ToolFlags>(false);
                PrintHelp(tools);
                if (Debugger.IsAttached)
                {
                    Debugger.Break();
                }
                return;
            }

            #region Initialize CASC
            Log("{0} v{1}", Assembly.GetExecutingAssembly().GetName().Name, Util.GetVersion());
            Log("Initializing CASC...");
            Log("Set language to {0}", Flags.Language);
            CDNIndexHandler.Cache.Enabled   = Flags.UseCache;
            CDNIndexHandler.Cache.CacheData = Flags.CacheData;
            CDNIndexHandler.Cache.Validate  = Flags.ValidateCache;
            // ngdp:us:pro
            // http:us:pro:us.patch.battle.net:1119
            if (Flags.OverwatchDirectory.ToLowerInvariant().Substring(0, 5) == "ngdp:")
            {
                string   cdn     = Flags.OverwatchDirectory.Substring(5, 4);
                string[] parts   = Flags.OverwatchDirectory.Substring(5).Split(':');
                string   region  = "us";
                string   product = "pro";
                if (parts.Length > 1)
                {
                    region = parts[1];
                }
                if (parts.Length > 2)
                {
                    product = parts[2];
                }
                if (cdn == "bnet")
                {
                    Config = CASCConfig.LoadOnlineStorageConfig(product, region);
                }
                else
                {
                    if (cdn == "http")
                    {
                        string host = string.Join(":", parts.Skip(3));
                        Config = CASCConfig.LoadOnlineStorageConfig(host, product, region, true, true, true);
                    }
                }
            }
            else
            {
                Config = CASCConfig.LoadLocalStorageConfig(Flags.OverwatchDirectory, !Flags.SkipKeys, false);
            }
            Config.Languages = new HashSet <string>(new[] { Flags.Language });
            #endregion

            foreach (Dictionary <string, string> build in Config.BuildInfo)
            {
                if (!build.ContainsKey("Tags"))
                {
                    continue;
                }
                if (build["Tags"].Contains("XX?"))
                {
                    IsPTR = true;
                }
                // us ptr region is known as XX, so just look for it in the tags.
                // this should work... untested for Asia
            }

            BuildVersion = uint.Parse(Config.BuildName.Split('.').Last());

            if (Flags.SkipKeys)
            {
                Log("Disabling Key auto-detection...");
            }

            Log("Using Overwatch Version {0}", Config.BuildName);
            CASC = CASCHandler.OpenStorage(Config);
            Root = CASC.Root as OwRootHandler;
            if (Root == null)
            {
                ErrorLog("Not a valid overwatch installation");
                return;
            }

            // Fail when trying to extract data from a specified language with 2 or less files found.
            if (!Root.APMFiles.Any())
            {
                ErrorLog("Could not find the files for language {0}. Please confirm that you have that language installed, and are using the names from the target language.", Flags.Language);
                if (!Flags.GracefulExit)
                {
                    return;
                }
            }

            Log("Mapping...");
            TrackedFiles[0x90] = new HashSet <ulong>();
            IO.MapCMF();
            IO.LoadGUIDTable();
            Sound.WwiseBank.GetReady();

            #region Key Detection
            if (!Flags.SkipKeys)
            {
                Log("Adding Encryption Keys...");

                foreach (ulong key in TrackedFiles[0x90])
                {
                    if (!ValidKey(key))
                    {
                        continue;
                    }
                    using (Stream stream = IO.OpenFile(Files[key])) {
                        if (stream == null)
                        {
                            continue;
                        }

                        STUEncryptionKey encryptionKey = GetInstance <STUEncryptionKey>(key);
                        if (encryptionKey != null && encryptionKey.LongKey != 0 && !KeyService.keys.ContainsKey(encryptionKey.LongRevKey))
                        {
                            KeyService.keys.Add(encryptionKey.LongRevKey, encryptionKey.KeyValue);
                            Log("Added Encryption Key {0}, Value: {1}", encryptionKey.KeyNameProper, encryptionKey.Key);
                        }
                    }
                }
            }
            #endregion

            Log("Tooling...");
            targetTool.Parse(targetToolFlags);
            if (Debugger.IsAttached)
            {
                Debugger.Break();
            }
        }
Ejemplo n.º 3
0
        private static void PrintHelp(IEnumerable <Type> eTools)
        {
            Log();
            Log("Modes:");
            Log("  {0, -23} | {1, -40}", "mode", "description");
            Log("".PadLeft(94, '-'));
            List <Type> tools = new List <Type>(eTools);

            tools.Sort(new ToolComparer());
            foreach (Type t in tools)
            {
                ToolAttribute attrib = t.GetCustomAttribute <ToolAttribute>();
                if (attrib.IsSensitive && !Debugger.IsAttached)
                {
                    continue;
                }
                string desc = attrib.Description;
                if (attrib.Description == null)
                {
                    desc = "";
                }
                Log("  {0, -23} | {1}", attrib.Keyword, desc);
            }

            Dictionary <Type, List <Type> > sortedTools = new Dictionary <Type, List <Type> >();

            foreach (Type t in tools)
            {
                ToolAttribute attrib = t.GetCustomAttribute <ToolAttribute>();
                if (attrib.Keyword == null)
                {
                    continue;
                }
                if (!attrib.Keyword.Contains("-"))
                {
                    continue;
                }
                if (!typeof(ICLIFlags).IsAssignableFrom(attrib.CustomFlags))
                {
                    continue;
                }

                if (!sortedTools.ContainsKey(attrib.CustomFlags))
                {
                    sortedTools[attrib.CustomFlags] = new List <Type>();
                }

                sortedTools[attrib.CustomFlags].Add(t);
            }


            foreach (KeyValuePair <Type, List <Type> > toolType in sortedTools.OrderBy(x => x.Key.Name.Length).OrderBy(x => x.Key.Name))
            {
                Type flags = toolType.Key;
                Log();

                string child = flags.Name;

                if (flags.BaseType != flags && flags.BaseType != typeof(Object) && !flags.BaseType.IsAbstract && !flags.BaseType.IsInterface)
                {
                    child = $"{child} based on {flags.BaseType.Name}";
                }

                if (toolType.Value.Count > 1)
                {
                    Log("Flags for {0}* ({1})", FindCommonSubstring(toolType.Value.Select(x => x.GetCustomAttribute <ToolAttribute>().Keyword).Where(x => x != null)), child);
                }
                else
                {
                    Log("Flags for {0} ({1})", toolType.Value.First().GetCustomAttribute <ToolAttribute>().Keyword, child);
                }
                typeof(FlagParser).GetMethod("FullHelp").MakeGenericMethod(flags).Invoke(null, new object[] { null, true });
            }
        }
Ejemplo n.º 4
0
        private static void Main()
        {
            InitTankSettings();

            HookConsole();

            var tools = GetTools();

        #if DEBUG
            FlagParser.CheckCollisions(typeof(ToolFlags), (flag, duplicate) => { Logger.Error("Flag", $"The flag \"{flag}\" from {duplicate} is a duplicate!"); });
        #endif

            FlagParser.LoadArgs();

            Logger.Info("Core", $"{Assembly.GetExecutingAssembly().GetName().Name} v{Util.GetVersion(typeof(Program).Assembly)}");

            Logger.Info("Core", $"CommandLine: [{string.Join(", ", FlagParser.AppArgs.Select(x => $"\"{x}\""))}]");

            Flags = FlagParser.Parse <ToolFlags>(full => PrintHelp(full, tools));
            if (Flags == null)
            {
                return;
            }

            Logger.Info("Core", $"CommandLineFile: {FlagParser.ArgFilePath}");

            if (Flags.SaveArgs)
            {
                FlagParser.AppArgs = FlagParser.AppArgs.Where(x => !x.StartsWith("--arg"))
                                     .ToArray();
                FlagParser.SaveArgs(Flags.OverwatchDirectory);
            }
            else if (Flags.ResetArgs || Flags.DeleteArgs)
            {
                FlagParser.ResetArgs();
                if (Flags.DeleteArgs)
                {
                    FlagParser.DeleteArgs();
                }

                Logger.Info("Core", $"CommandLineNew: [{string.Join(", ", FlagParser.AppArgs.Select(x => $"\"{x}\""))}]");
                Flags = FlagParser.Parse <ToolFlags>(full => PrintHelp(full, tools));
                if (Flags == null)
                {
                    return;
                }
            }

            if (string.IsNullOrWhiteSpace(Flags.OverwatchDirectory) || string.IsNullOrWhiteSpace(Flags.Mode) || Flags.Help)
            {
                PrintHelp(false, tools);
                return;
            }

            ITool         targetTool           = null;
            ICLIFlags     targetToolFlags      = null;
            ToolAttribute targetToolAttributes = null;

            #region Tool Activation

            foreach (var type in tools)
            {
                var attribute = type.GetCustomAttribute <ToolAttribute>();

                if (!string.Equals(attribute.Keyword, Flags.Mode, StringComparison.InvariantCultureIgnoreCase))
                {
                    continue;
                }
                targetTool           = Activator.CreateInstance(type) as ITool;
                targetToolAttributes = attribute;

                if (attribute.CustomFlags != null)
                {
                    var flags = attribute.CustomFlags;
                    if (typeof(ICLIFlags).IsAssignableFrom(flags))
                    {
                        targetToolFlags = typeof(FlagParser).GetMethod(nameof(FlagParser.Parse), new Type[] { })
                                          ?.MakeGenericMethod(flags)
                                          .Invoke(null, null) as ICLIFlags;
                    }
                }

                break;
            }

            if (targetToolFlags == null)
            {
                return;
            }

            #endregion

            if (targetTool == null)
            {
                FlagParser.Help <ToolFlags>(false, new Dictionary <string, string>());
                PrintHelp(false, tools);
                return;
            }

            if (!targetToolAttributes.UtilNoArchiveNeeded)
            {
                InitStorage();

                //foreach (KeyValuePair<ushort, HashSet<ulong>> type in TrackedFiles.OrderBy(x => x.Key)) {
                //    //Console.Out.WriteLine($"Found type: {type.Key:X4} ({type.Value.Count} files)");
                //    Console.Out.WriteLine($"Found type: {type.Key:X4}");
                //}

                InitKeys();
                InitMisc();
            }

            var stopwatch = new Stopwatch();
            Logger.Info("Core", "Tooling...");
            stopwatch.Start();
            targetTool.Parse(targetToolFlags);
            stopwatch.Stop();

            Logger.Success("Core", $"Execution finished in {stopwatch.Elapsed} seconds");

            ShutdownMisc();
        }
Ejemplo n.º 5
0
        private static void PrintHelp(IEnumerable <Type> eTools)
        {
            Log();
            Log("Modes:");
            Log("  {0, -23} | {1, -40}", "mode", "description");
            Log("".PadLeft(94, '-'));
            List <Type> tools = new List <Type>(eTools);

            tools.Sort(new ToolComparer());
            foreach (Type t in tools)
            {
                ToolAttribute attrib = t.GetCustomAttribute <ToolAttribute>();
                if (attrib.IsSensitive && !Debugger.IsAttached)
                {
                    continue;
                }
                string desc = attrib.Description;
                if (attrib.Description == null)
                {
                    desc = "";
                }
                Log("  {0, -23} | {1}", attrib.Keyword, desc);
            }

            Dictionary <string, List <Type> > sortedTools = new Dictionary <string, List <Type> >();

            foreach (Type t in tools)
            {
                ToolAttribute attrib = t.GetCustomAttribute <ToolAttribute>();
                if (attrib.Keyword == null)
                {
                    continue;
                }
                if (!attrib.Keyword.Contains("-"))
                {
                    continue;
                }

                string result = attrib.Keyword.Split('-').First();

                if (!sortedTools.ContainsKey(result))
                {
                    sortedTools[result] = new List <Type>();
                }
                sortedTools[result].Add(t);
            }

            foreach (KeyValuePair <string, List <Type> > toolType in sortedTools)
            {
                Type          firstTool = toolType.Value.FirstOrDefault();
                ToolAttribute attrib    = firstTool?.GetCustomAttribute <ToolAttribute>();
                if (attrib?.CustomFlags == null)
                {
                    continue;
                }
                Type flags = attrib.CustomFlags;
                if (!typeof(ICLIFlags).IsAssignableFrom(attrib.CustomFlags))
                {
                    continue;
                }
                Log();
                Log("Flags for {0}-*", toolType.Key);
                typeof(FlagParser).GetMethod("FullHelp").MakeGenericMethod(flags).Invoke(null, new object[] { null, true });
            }
        }
Ejemplo n.º 6
0
        private static void Main()
        {
            AppDomain.CurrentDomain.UnhandledException += ExceptionHandler;
            Process.GetCurrentProcess().EnableRaisingEvents = true;
            AppDomain.CurrentDomain.ProcessExit += (sender, @event) => Console.ForegroundColor = ConsoleColor.Gray;
            Console.CancelKeyPress += (sender, @event) => Console.ForegroundColor = ConsoleColor.Gray;
            Console.OutputEncoding  = Encoding.UTF8;

            Files        = new Dictionary <ulong, ApplicationPackageManifest.Types.PackageRecord>();
            TrackedFiles = new Dictionary <ushort, HashSet <ulong> >();

            #region Tool Detection
            HashSet <Type> tools = new HashSet <Type>();
            {
                Assembly    asm   = typeof(ITool).Assembly;
                Type        t     = typeof(ITool);
                List <Type> types = asm.GetTypes().Where(tt => tt != t && t.IsAssignableFrom(tt)).ToList();
                foreach (Type tt in types)
                {
                    ToolAttribute attrib = tt.GetCustomAttribute <ToolAttribute>();
                    if (tt.IsInterface || attrib == null)
                    {
                        continue;
                    }
                    tools.Add(tt);

                    if (attrib.TrackTypes == null)
                    {
                        continue;
                    }
                    foreach (ushort type in attrib.TrackTypes)
                    {
                        if (!TrackedFiles.ContainsKey(type))
                        {
                            TrackedFiles[type] = new HashSet <ulong>();
                        }
                    }
                }
            }
            #endregion

            Flags = FlagParser.Parse <ToolFlags>(() => PrintHelp(tools));
            if (Flags == null)
            {
                return;
            }

            //Logger.EXIT = !Flags.GracefulExit;

            ITool     targetTool      = null;
            ICLIFlags targetToolFlags = null;

            #region Tool Activation

            foreach (Type type in tools)
            {
                ToolAttribute attrib = type.GetCustomAttribute <ToolAttribute>();

                if (!string.Equals(attrib.Keyword, Flags.Mode, StringComparison.InvariantCultureIgnoreCase))
                {
                    continue;
                }
                targetTool = Activator.CreateInstance(type) as ITool;

                if (attrib.CustomFlags != null)
                {
                    Type flags = attrib.CustomFlags;
                    if (typeof(ICLIFlags).IsAssignableFrom(flags))
                    {
                        targetToolFlags = typeof(FlagParser).GetMethod(nameof(FlagParser.Parse), new Type[] { }).MakeGenericMethod(flags).Invoke(null, null) as ICLIFlags;
                    }
                }
                break;
            }

            #endregion

            if (targetTool == null)
            {
                FlagParser.Help <ToolFlags>(false);
                PrintHelp(tools);
                if (Debugger.IsAttached)
                {
                    Debugger.Break();
                }
                return;
            }

            TankLib.Helpers.Logger.Info("Core", $"{Assembly.GetExecutingAssembly().GetName().Name} v{TankLib.Util.GetVersion(typeof(Program).Assembly)}");
            TankLib.Helpers.Logger.Info("Core", $"CommandLine: [{string.Join(", ", Environment.GetCommandLineArgs().Skip(1).Select(x => $"\"{x}\""))}]");

            #region Initialize CASC
            if (Flags.Language != null)
            {
                TankLib.Helpers.Logger.Info("CASC", $"Set language to {Flags.Language}");
            }
            if (Flags.SpeechLanguage != null)
            {
                TankLib.Helpers.Logger.Info("CASC", $"Set speech language to {Flags.SpeechLanguage}");
            }

            CASCHandler.Cache.CacheAPM     = Flags.UseCache;
            CASCHandler.Cache.CacheCDN     = Flags.UseCache;
            CASCHandler.Cache.CacheCDNData = Flags.CacheData;
            Config = CASCConfig.LoadFromString(Flags.OverwatchDirectory, Flags.SkipKeys);
            Config.SpeechLanguage = Flags.SpeechLanguage ?? Flags.Language ?? Config.SpeechLanguage;
            Config.TextLanguage   = Flags.Language ?? Config.TextLanguage;

            if (Config != null)
            {
                if (Flags.Language != null && !Config.InstallData.Settings.Languages.Select(x => x.Language).Contains(Flags.Language))
                {
                    TankLib.Helpers.Logger.Warn("Core", "Battle.Net Agent reports that language {0} is not installed.", Flags.Language);
                }

                if (Config.InstallData.Uid != "prometheus")
                {
                    TankLib.Helpers.Logger.Warn("Core", $"The branch \"{Config.InstallData.Uid}\" is not supported!. This might result in failure to load. Proceed with caution.");
                }
            }
            #endregion


            BuildVersion = uint.Parse(Config.BuildVersion.Split('.').Last());

            if (BuildVersion < 39028)
            {
                TankLib.Helpers.Logger.Error("Core", "DataTool doesn't support Overwatch versions below 1.14. Please use OverTool");
            }
            else if (BuildVersion < 39241)
            {
                TankLib.Helpers.Logger.Error("Core", "DataTool doesn't support this 1.14 release as it uses unmangeled hashes");
            }
            else if (BuildVersion < 49154)
            {
                TankLib.Helpers.Logger.Error("Core", "This version of DataTool doesn't properly support versions below 1.26. Please downgrade DataTool.");
            }

            TankLib.Helpers.Logger.Info("Core", $"Using Overwatch Version {Config.BuildVersion}");
            TankLib.Helpers.Logger.Info("CASC", "Initializing...");
            CASC = CASCHandler.Open(Config);
            Root = CASC.RootHandler;
            //if (Root== null) {
            //    ErrorLog("Not a valid overwatch installation");
            //    return;
            //}

            if (Config.InstallData != null)
            {
            }

            // Fail when trying to extract data from a specified language with 2 or less files found.
            if (!Root.APMFiles.Any())
            {
                TankLib.Helpers.Logger.Error("Core", "Unable to load APM files for language {0}. Please confirm that you have that language installed.", Flags.Language);
                return;
            }

            TankLib.Helpers.Logger.Info("Core", "Mapping storage");
            TrackedFiles[0x90] = new HashSet <ulong>();
            IO.MapCMF();
            IO.LoadGUIDTable();
            Sound.WwiseBank.GetReady();

            //foreach (KeyValuePair<ushort, HashSet<ulong>> type in TrackedFiles.OrderBy(x => x.Key)) {
            //    //Console.Out.WriteLine($"Found type: {type.Key:X4} ({type.Value.Count} files)");
            //    Console.Out.WriteLine($"Found type: {type.Key:X4}");
            //}

            #region Key Detection
            if (!Flags.SkipKeys)
            {
                TankLib.Helpers.Logger.Info("Core", "Checking ResourceKeys");

                foreach (ulong key in TrackedFiles[0x90])
                {
                    if (!ValidKey(key))
                    {
                        continue;
                    }
                    using (Stream stream = IO.OpenFile(Files[key])) {
                        if (stream == null)
                        {
                            continue;
                        }

                        STUResourceKey resourceKey = GetInstance <STUResourceKey>(key);
                        if (resourceKey == null || resourceKey.GetKeyID() == 0 || TACTKeyService.Keys.ContainsKey(resourceKey.GetReverseKeyID()))
                        {
                            continue;
                        }
                        TACTKeyService.Keys.Add(resourceKey.GetReverseKeyID(), resourceKey.m_key);
                        TankLib.Helpers.Logger.Info("Core", $"Added ResourceKey {resourceKey.GetKeyIDString()}, Value: {resourceKey.GetKeyValueString()}");
                    }
                }
            }
            #endregion

            Stopwatch stopwatch = new Stopwatch();
            TankLib.Helpers.Logger.Info("Core", "Tooling...");
            var dbPath = Flags.ScratchDBPath;
            if (Flags.Deduplicate)
            {
                TankLib.Helpers.Logger.Warn("ScratchDB", "Will attempt to deduplicate files if extracting...");
                if (!string.IsNullOrWhiteSpace(Flags.ScratchDBPath))
                {
                    TankLib.Helpers.Logger.Warn("ScratchDB", "Loading deduplication database...");
                    if (!File.Exists(dbPath))
                    {
                        dbPath = Path.Combine(Path.GetFullPath(Flags.ScratchDBPath), "Scratch.db");
                    }
                    SaveLogic.Combo.ScratchDBInstance.Load(dbPath);
                }
            }
            stopwatch.Start();
            targetTool.Parse(targetToolFlags);
            stopwatch.Stop();

            TankLib.Helpers.Logger.Success("Core", $"Execution finished in {stopwatch.Elapsed} seconds");

            if (Flags.Deduplicate && !string.IsNullOrWhiteSpace(dbPath))
            {
                TankLib.Helpers.Logger.Warn("ScratchDB", "Saving deduplication database...");
                SaveLogic.Combo.ScratchDBInstance.Save(dbPath);
            }

            if (Debugger.IsAttached)
            {
                Debugger.Break();
            }
        }