private void ModDetails_Load(object sender, EventArgs e)
        {
            this.Text = "Mod Details - " + this._mod.Name;

            this.ModNameText.Text = this._mod.Name;
            this.AuthorText.Text = this._mod.Author;
            this.DescriptionText.Text = this._mod.Description;

            foreach (BundleRewriteItem item in this._mod.ItemQueue)
            {
                BundleRewriteItem newBri = new BundleRewriteItem();

                newBri.ReplacementFile = Path.GetFileName(this._mod.file)+"/"+item.ReplacementFile;

                String sourcefile = "";
                String path = StaticStorage.Known_Index.GetAny(item.BundlePath);
                String extension = StaticStorage.Known_Index.GetExtension(item.BundleExtension);

                if (!string.IsNullOrEmpty(path) && !string.IsNullOrEmpty(extension))
                {
                    if (item.IsLanguageSpecific)
                        sourcefile = path + "." + item.BundleLanguage + "." + extension;
                    else
                        sourcefile = path + "." + extension;

                    newBri.SourceFile = sourcefile;

                    _items.Add(newBri);
                }
            }

            this.ReplacementFilesGridView.DataSource = _items;
            this.ReplacementFilesGridView.Update();
        }
 private void ParseFileLine(string currentLine, int currentLineNumber)
 {
     ulong path, extension = 0;
     uint language = 0;
     string[] pieces = currentLine.Split(':');
     if (pieces.Length < 2)
         this.Error("File line didn't contain two pieces.", currentLineNumber);
     this.CheckFile(pieces[0].Trim(), out path, out language, out extension, currentLineNumber);
     if (!File.Exists(this.modScriptPath + "/" + pieces[1].Trim()))
         this.Error("Replacement file does not exist.", currentLineNumber);
     var item = new BundleRewriteItem
     {
         BundleExtension = extension,
         BundleLanguage = language,
         BundlePath = path,
         IsLanguageSpecific = language != 0 ? true : false,
         SourceFile = pieces[0].Trim(),
         ReplacementFile = this.modScriptPath + "/" + pieces[1].Trim()
     };
     this.newMod.ItemQueue.Add(item);
 }
 /// <summary>
 ///     The add bundle changes.
 /// </summary>
 /// <param name="ids">
 ///     The ids.
 /// </param>
 /// <param name="path">
 ///     The path.
 /// </param>
 /// <param name="extension">
 ///     The extension.
 /// </param>
 /// <param name="language">
 ///     The language.
 /// </param>
 /// <param name="languageSpecific">
 ///     The language_specific.
 /// </param>
 private void AddBundleChanges(
     HashSet<uint> ids,
     ulong path,
     ulong extension,
     uint language,
     bool languageSpecific,
     int replacementType)
 {
     var rewriteItem = new BundleRewriteItem
                           {
                               BundleExtension = extension,
                               BundlePath = path,
                               BundleLanguage = language,
                               IsLanguageSpecific = languageSpecific,
                               SourceFile = BundleFileName.Text.ToLower().Replace('\\', '/'),
                               ReplacementFile = this.ReplacementFileName.Text,
                               ReplacementType = replacementType
                           };
     this.newMod.ItemQueue.Add(rewriteItem);
     this.lastRewriteItem = rewriteItem;
     this.UndoLast.Enabled = true;
 }
        /// <summary>
        /// The apply mod.
        /// </summary>
        public void ApplyMod()
        {
            this.Done = false;
            using (this.Zip = new ZipFile(this._zipPath))
            {
                bool wasSuccessful = false;
                this._mod.ItemQueue.RemoveWhere(i => i.BundleExtension == 0xAB2664BF82E646UL);
                this._mod.ItemQueue.RemoveWhere(i => i.BundleExtension == 0xAB2664BF82E6460C);
                this._mod.ItemQueue.RemoveWhere(i => i.BundleExtension == 0x29104BC4AC649965);

                if (!this.LocateChangeIds())
                    return;

                HashSet<string> bundles = this.LocateBundlesToRewrite(out wasSuccessful);
                if (!wasSuccessful)
                    return;

                if (!this._patchAllBundles)
                    bundles.RemoveWhere(i => i.StartsWith("all_"));

                if (bundles.Count <= 0)
                {
                    this.Error = "Unable to locate any bundles with the requested items in them.\n"
                                 + "If the changed file(s) only exists within an all_x.bundle file you will need to enable the option to patch all_x.bundle files.\n"
                                 + "Refer to the patch description for if this is required.";
                    return;
                }

                this.SetTotalProgress("Backing up Bundles", -1);
                int currentBundle = 1;
                int bundleCount = bundles.Count;
                foreach (var bundle in bundles)
                {

                    this.SetBundleProgress(
                        string.Format("{0}/{1}", currentBundle, bundleCount),
                        (int)((currentBundle / (float)bundleCount) * 100.0f));

                    if (this._backupType == 1)
                        this.BackupEntries(this._mod, Path.Combine(this._assetFolder, bundle));
                    else
                    {
                        this.BackupFile(Path.Combine(this._assetFolder, bundle + "_h.bundle"));
                        this.BackupFile(Path.Combine(this._assetFolder, bundle + ".bundle"));
                    }
                    currentBundle += 1;

                }

                backupEntry.Name = this._mod.Name;
                backupEntry.Author = this._mod.Author;
                backupEntry.Description = this._mod.Description;
                backupEntry.BackupType = (this._backupType == 0) ? "Bundles" : "Bundle Entries";
                backupEntry.InstallDate = DateTime.Now;
                backupEntry.RewriteAll = this._patchAllBundles;
                HashSet<BundleRewriteItem> backupQueue = new HashSet<BundleRewriteItem>();
                foreach (BundleRewriteItem bri in this._mod.ItemQueue)
                {
                    BundleRewriteItem newbri = new BundleRewriteItem();
                    newbri.BundleExtension = bri.BundleExtension;
                    newbri.BundleLanguage = bri.BundleLanguage;
                    newbri.BundlePath = bri.BundlePath;
                    newbri.Ids = bri.Ids;
                    newbri.IsLanguageSpecific = bri.IsLanguageSpecific;

                    backupQueue.Add(newbri);
                }

                backupEntry.ItemQueue = backupQueue;
                allowBackup = true;

                currentBundle = 1;
                TotalElapsedTime.Start();
                foreach (var bundle in bundles)
                {
                    this.SetTotalProgress(
                        string.Format("Patching Bundle {0}/{1}", currentBundle, bundleCount),
                        (int)((currentBundle / (float)bundleCount) * 100.0f));
                    if (!this.PatchBundle(bundle))
                        return;

                    currentBundle += 1;
                }
                TotalElapsedTime.Stop();
            }

            this.SetTotalProgress("Done", 100);
            this.Done = true;
        }
        private void ConfigureReplacementButton_Click(object sender, EventArgs e)
        {
            /*
             * File Replacement
             * Patch Script
             * Strings Patch
             * Sound Bank Patch
             */

            ulong path, extension;
            uint language;

            switch(this.fileReplacementType_ComboBox.Text)
            {
                case ("File Replacement"):
                    return;
                case ("Strings Patch"):
                    if (!this.CheckBundleFileName(this.BundleFileName.Text.ToLower().Replace('\\', '/'), out path, out extension, out language))
                    {
                        return;
                    }
                    BundleRewriteItem tempBRI = new BundleRewriteItem(path, language, extension);
                    tempBRI.IsLanguageSpecific = (Path.GetFileName(this.BundleFileName.Text).Split('.').Length == 3);

                    BundleRewriter br = new BundleRewriter(StaticStorage.settings.AssetsFolder);
                    MemoryStream stringsStream = new MemoryStream();
                    br.RetrieveFile(tempBRI, out stringsStream);
                    DieselStrings ds = new DieselStrings(stringsStream);

                    ManageStrings msForm = new ManageStrings(ds);
                    msForm.ShowDialog(this);
                    /*
                    FileControl filecontrolForm = new FileControl();
                    filecontrolForm.filecontrolDictionary = filecontrolDictionary;
                    filecontrolForm.filecontrolSelectedDictionary = filecontrolSelectedDictionary;
                    filecontrolForm.ShowDialog(this);

                    filecontrolSelectedDictionary = filecontrolForm.filecontrolSelectedDictionary;
                    */
                    break;
                case ("Sound Bank Patch"):

                    if (!this.CheckBundleFileName(this.BundleFileName.Text.ToLower().Replace('\\', '/'), out path, out extension, out language))
                    {
                        return;
                    }
                    BundleRewriteItem soundtempBRI = new BundleRewriteItem(path, language, extension);
                    soundtempBRI.IsLanguageSpecific = (Path.GetFileName(this.BundleFileName.Text).Split('.').Length == 3);

                    BundleRewriter soundbr = new BundleRewriter(StaticStorage.settings.AssetsFolder);
                    MemoryStream soundStream = new MemoryStream();

                    soundbr.RetrieveFile(soundtempBRI, out soundStream);

                    SoundPatch spForm = new SoundPatch(Path.GetFileNameWithoutExtension(this.BundleFileName.Text.ToLower()), soundStream);
                    spForm.ShowDialog(this);

                    break;
                default:
                break;
            }
        }
        /// <summary>
        /// The apply changes.
        /// </summary>
        public void ApplyChanges(BundleMod[] toAddModsList, bool method)
        {
            this.Done = false;
            using (this.Zip = new ZipFile(this._zipPath))
            {
                bool wasSuccessful = false;
                this._mod.ItemQueue.RemoveWhere(i => i.BundleExtension == 0xAB2664BF82E646UL);
                this._mod.ItemQueue.RemoveWhere(i => i.BundleExtension == 0xAB2664BF82E6460C);
                this._mod.ItemQueue.RemoveWhere(i => i.BundleExtension == 0x29104BC4AC649965);

                if (!this.LocateChangeIds())
                    return;

                var toRemove = this._mod.ItemQueue.Where(p => p.toRemove);
                //var toReinstall = this._mod.ItemQueue.Where(p => p.toReinstall);
                var toInstall = this._mod.ItemQueue.Where(p => !p.toRemove);

                if (this._overrideFolder)
                {
                    this.SetTotalProgress("Utilizing Override Folder", -1);

                    HashSet<BundleEntryPath> toSharedFolder = new HashSet<BundleEntryPath>();
                    HashSet<BundleEntryPath> overrideApplied = new HashSet<BundleEntryPath>();
                    Dictionary<BundleEntryPath, HashSet<BundleRewriteItem>> bep_sorted = new Dictionary<BundleEntryPath, HashSet<BundleRewriteItem>>();

                    foreach (BundleRewriteItem bri in this._mod.ItemQueue)
                    {
                        if (bri.toRemove)
                            continue;

                        if (bep_sorted.ContainsKey(bri.getBundleEntryPath()))
                        {
                            if (this._overrideFolderShared && !toSharedFolder.Contains(bri.getBundleEntryPath()))
                                toSharedFolder.Add(bri.getBundleEntryPath());
                            bep_sorted[bri.getBundleEntryPath()].Add(bri);
                        }
                        else
                        {
                            HashSet<BundleRewriteItem> newbrihs = new HashSet<BundleRewriteItem>();
                            newbrihs.Add(bri);
                            bep_sorted.Add(bri.getBundleEntryPath(), newbrihs);
                        }
                    }

                    HashSet<BundleRewriteItem> reducedItemQueue = new HashSet<BundleRewriteItem>();
                    int override_count = 1;
                    foreach (BundleRewriteItem bri in this._mod.ItemQueue)
                    {
                        this.SetBundleProgress(
                            string.Format("Processing {0}/{1}", override_count, this._mod.ItemQueue.Count),
                            (int)((override_count / (float)this._mod.ItemQueue.Count) * 100.0f));

                        if (bri.isOverrideable()
                            //&& !bri.ReplacementFile.EndsWith(".script")
                            )
                        {

                            if (!string.IsNullOrEmpty(StaticStorage.Known_Index.GetPath(bri.BundlePath)) &&
                                !string.IsNullOrEmpty(StaticStorage.Known_Index.GetExtension(bri.BundleExtension))
                                )
                            {
                                string extrname = "";
                                extrname += StaticStorage.Known_Index.GetPath(bri.BundlePath);
                                extrname += "." + StaticStorage.Known_Index.GetExtension(bri.BundleExtension);

                                string modName = bri.getEscapedName();

                                if (bri.toRemove)
                                {
                                    if (!toSharedFolder.Contains(bri.getBundleEntryPath()) && File.Exists(Path.Combine(this._assetFolder, "mod_overrides", "Bundle_Modder_Shared", extrname)))
                                        File.Delete(Path.Combine(this._assetFolder, "mod_overrides", "Bundle_Modder_Shared", extrname));
                                    else if (File.Exists(Path.Combine(this._assetFolder, "mod_overrides", modName, extrname)))
                                        File.Delete(Path.Combine(this._assetFolder, "mod_overrides", modName, extrname));

                                    DeleteEmptyDirs(Path.Combine(this._assetFolder, "mod_overrides", modName));
                                }
                                else
                                {
                                    if (bri.toReinstall)
                                    {
                                        if (File.Exists(Path.Combine(this._assetFolder, "mod_overrides", modName, extrname)))
                                            File.Delete(Path.Combine(this._assetFolder, "mod_overrides", modName, extrname));
                                    }

                                    String path;
                                    if (this._overrideFolderShared && toSharedFolder.Contains(bri.getBundleEntryPath()))
                                        path = Path.Combine(this._assetFolder, "mod_overrides", "Bundle_Modder_Shared", extrname);
                                    else
                                        path = Path.Combine(this._assetFolder, "mod_overrides", modName, extrname);

                                    if (!Directory.Exists(Path.GetDirectoryName(path)))
                                        Directory.CreateDirectory(Path.GetDirectoryName(path));

                                    HashSet<BundleRewriteItem> bep_items = new HashSet<BundleRewriteItem>();
                                    if (bep_sorted.ContainsKey(bri.getBundleEntryPath()))
                                        bep_items = bep_sorted[bri.getBundleEntryPath()];

                                    var outOverride = new FileStream(
                                                    path,
                                                    FileMode.Create,
                                                    FileAccess.ReadWrite);

                                    int runningcount = 0;
                                    foreach (var item in bep_items)
                                    {
                                        if (item.SourceFile != null)
                                        {
                                            if(this.Zip == null)
                                                this.Zip = new ZipFile(item.SourceFile);

                                            if (!this.Zip.Name.Equals(item.SourceFile))
                                            {
                                                this.Zip.Dispose();
                                                this.Zip = new ZipFile(item.SourceFile);
                                            }
                                        }
                                        else
                                            continue;

                                        ZipEntry zip_entry = this.Zip[item.ReplacementFile];
                                        if (zip_entry != null)
                                        {
                                            if (zip_entry.UsesEncryption)
                                            {
                                                zip_entry.Password = "******";
                                                //zip_entry.Encryption = EncryptionAlgorithm.WinZipAes256;
                                            }

                                            MemoryStream zipEntryData = new MemoryStream();

                                            if (item.ReplacementFile.EndsWith(".script"))
                                            {
                                                MemoryStream scriptData = new MemoryStream();
                                                zip_entry.Extract(scriptData);
                                                scriptData.Seek(0, SeekOrigin.Begin);
                                                MemoryStream bundleData = new MemoryStream();

                                                if (RetrieveFile(item, out bundleData))
                                                {
                                                    if (runningcount > 0)
                                                    {
                                                        bundleData.SetLength(0);
                                                        outOverride.Seek(0, SeekOrigin.Begin);
                                                        outOverride.CopyTo(bundleData);
                                                    }

                                                    StreamReader scriptStream = new StreamReader(scriptData);

                                                    List<BundleRewriteScriptAction> scriptActions = ParseScriptActions(ref scriptStream, zip_entry.FileName);
                                                    scriptData.Close();
                                                    scriptStream.Close();

                                                    //apply script functions here
                                                    bundleData.Seek(0, SeekOrigin.Begin);

                                                    List<byte> entryBytes = bundleData.ToArray().ToList();

                                                    outOverride.Seek(0, SeekOrigin.Begin);
                                                    ApplyScriptActions(ref entryBytes, ref scriptActions);

                                                    foreach (byte b in entryBytes)
                                                        outOverride.WriteByte(b);

                                                }
                                                else
                                                {
                                                    reducedItemQueue.Add(item);
                                                }
                                            }
                                            else
                                            {
                                                outOverride.Position = 0L;
                                                zipEntryData.Position = 0L;
                                                zip_entry.Extract(zipEntryData);
                                                zipEntryData.Position = 0L;
                                                zipEntryData.CopyTo(outOverride, this.bufferSize);
                                                //foreach (byte b in zipEntryData.ToArray().ToList())
                                                //    outOverride.WriteByte(b);
                                            }

                                            outOverride.Flush();

                                        }
                                        runningcount++;
                                    }

                                    outOverride.Close();
                                }
                            }
                            else
                            {
                                reducedItemQueue.Add(bri);
                            }

                        }
                        else
                        {
                            if (this._overrideFolderDummies)
                            {
                                string modName = bri.ModName;
                                modName = Path.GetInvalidFileNameChars().Aggregate(modName, (current, c) => current.Replace(c.ToString(), "_"));

                                if (bri.toRemove)
                                {
                                    if (Directory.Exists(Path.Combine(this._assetFolder, "mod_overrides", modName)))
                                    {
                                        //Directory.Delete(Path.Combine(this._assetFolder, "mod_overrides", modName), true);
                                        DeleteDirectory(Path.Combine(this._assetFolder, "mod_overrides", modName));
                                    }
                                }
                                else
                                {
                                    if (!Directory.Exists(Path.Combine(this._assetFolder, "mod_overrides", modName)))
                                        Directory.CreateDirectory(Path.Combine(this._assetFolder, "mod_overrides", modName));
                                }
                            }

                            reducedItemQueue.Add(bri);
                        }
                        override_count++;
                    }

                    this.SetBundleProgress("Done", 100);
                    this._mod.ItemQueue = reducedItemQueue;
                }

                HashSet<string> bundles = this.LocateBundlesToRewrite(out wasSuccessful);
                if (!wasSuccessful)
                    return;

                if (!this._patchAllBundles)
                    bundles.RemoveWhere(i => i.StartsWith("all_"));

                if (bundles.Count <= 0 && !this._overrideFolder)
                {
                    this.Error = "Unable to locate any bundles with the requested items in them.\n"
                                 + "If the changed file(s) only exists within an all_x.bundle file you will need to enable the option to patch all_x.bundle files.\n"
                                 + "Refer to the patch description for if this is required.";
                    return;
                }

                this.SetTotalProgress("Backing up Bundles", -1);
                this.CurrentBundlesCount = 1;
                this.TotalBundlesCount = bundles.Count;
                foreach (var bundle in bundles)
                {

                    this.SetBundleProgress(
                        string.Format("Backing up Bundle {0}/{1}", this.CurrentBundlesCount, this.TotalBundlesCount),
                        (int)((this.CurrentBundlesCount / (float)this.TotalBundlesCount) * 100.0f));

                    if (this._backupType == 1)
                    {
                        this.BackupEntries(this._mod, Path.Combine(this._assetFolder, bundle));
                    }
                    else
                    {
                        this.BackupFile(Path.Combine(this._assetFolder, bundle + "_h.bundle"));
                        this.BackupFile(Path.Combine(this._assetFolder, bundle + ".bundle"));
                    }
                    this.CurrentBundlesCount += 1;

                }

                foreach (BundleMod bm in toAddModsList)
                {
                    BackupEntry multibackupEntry = new BackupEntry();
                    multibackupEntry.Name = bm.Name;
                    multibackupEntry.Author = bm.Author;
                    multibackupEntry.Description = bm.Description;
                    multibackupEntry.BackupType = (this._backupType == 0) ? "Bundles" : "Bundle Entries";
                    multibackupEntry.InstallDate = DateTime.Now;
                    multibackupEntry.RewriteAll = this._patchAllBundles;
                    HashSet<BundleRewriteItem> backupQueue = new HashSet<BundleRewriteItem>();

                    foreach (BundleRewriteItem bri in bm.ItemQueue)
                    {
                        BundleRewriteItem newbri = new BundleRewriteItem();
                        newbri.BundleExtension = bri.BundleExtension;
                        newbri.BundleLanguage = bri.BundleLanguage;
                        newbri.BundlePath = bri.BundlePath;
                        newbri.Ids = bri.Ids;
                        newbri.IsLanguageSpecific = bri.IsLanguageSpecific;
                        if (this._backupType == 0)
                            newbri.ReplacementFile = bri.ReplacementFile;
                        else
                            newbri.ReplacementFile = bri.BundlePath.ToString("x") + '.' + bri.BundleLanguage.ToString("x") + '.' + bri.BundleExtension.ToString("x");
                        newbri.SourceFile = bri.SourceFile;

                        backupQueue.Add(newbri);
                    }
                    multibackupEntry.ItemQueue = backupQueue;
                    backupEntries.Add(multibackupEntry);
                }
                allowBackup = true;

                foreach (var rewriteItem in this._mod.ItemQueue)
                {
                    foreach (var id in rewriteItem.Ids)
                    {
                        if (this._rewriteItems.ContainsKey(id))
                        {
                            if (rewriteItem.toRemove)
                                this._rewriteItems[id].toRestore = true;

                            if (rewriteItem.ReplacementFile.EndsWith(".script"))
                            {
                                this._rewriteItems[id].BundleRewriteItem_queue.Add(rewriteItem);
                            }
                            else
                            {
                                if (rewriteItem.priority)
                                {
                                    this._rewriteItems[id].priorityBundleRewriteItem = rewriteItem;
                                }
                                else
                                {
                                    //Don't add... it's not part of priority
                                    this._rewriteItems[id].BundleRewriteItem_queue.Add(rewriteItem);
                                }
                            }
                        }
                        else
                        {
                            BundleRewriteEntryID breid = new BundleRewriteEntryID();

                            if (rewriteItem.toRemove)
                                breid.toRestore = true;

                            if (rewriteItem.ReplacementFile.EndsWith(".script"))
                            {
                                breid.BundleRewriteItem_queue.Add(rewriteItem);
                            }
                            else
                            {
                                if (rewriteItem.priority)
                                {
                                    breid.priorityBundleRewriteItem = rewriteItem;
                                }
                                else
                                {
                                    //Don't add, it's not part of priority
                                    breid.BundleRewriteItem_queue.Add(rewriteItem);
                                }
                            }

                            this._rewriteItems.Add(id, breid);
                        }
                    }
                }

                this.CurrentBundlesCount = 1;
                TotalElapsedTime.Start();
                SpeedElapsedTime.Start();

                foreach (var bundle in bundles)
                {
                    CurrentBundle = bundle;
                    this.SetTotalProgress(
                        string.Format("Patching Bundle {0}/{1}", this.CurrentBundlesCount, this.TotalBundlesCount),
                        (int)((this.CurrentBundlesCount / (float)this.TotalBundlesCount) * 100.0f));
                    if (!this.PatchBundle(bundle))
                        return;

                    this.CurrentBundlesCount += 1;
                }
                TotalElapsedTime.Stop();
                SpeedElapsedTime.Stop();
            }
            this.Zip.Dispose();
            this.SetTotalProgress("Done", 100);
            this.Done = true;
        }
        /// <summary>
        /// The write zip entry.
        /// </summary>
        /// <param name="output">
        /// The output.
        /// </param>
        /// <param name="rewriteItem">
        /// Replacement parameters in form of BundleRewriteItem
        /// </param>
        /// <returns>
        /// How many bytes were written to the stream.
        /// </returns>
        private int WriteZipEntry(BundleEntry bundleEntry, Stream input, Stream output, BundleRewriteItem rewriteItem)
        {
            if (rewriteItem.SourceFile != null)
            {
                if(this.Zip == null)
                    this.Zip = new ZipFile(rewriteItem.SourceFile);
                else if (!this.Zip.Name.Equals(rewriteItem.SourceFile))
                {
                    this.Zip.Dispose();
                    this.Zip = new ZipFile(rewriteItem.SourceFile);
                }
            }

            int extractedLength = 0;

            ZipEntry zip_entry = this.Zip[rewriteItem.ReplacementFile];
            if (zip_entry != null)
            {
                if (zip_entry.UsesEncryption)
                {
                    zip_entry.Password = "******";
                    //zip_entry.Encryption = EncryptionAlgorithm.WinZipAes256;
                }

                var br = new BinaryReader(input);
                var bw = new BinaryWriter(output);
                var data = new MemoryStream();
                zip_entry.Extract(data);
                data.Seek(0, SeekOrigin.Begin);

                if (zip_entry.FileName.EndsWith(".script"))
                {
                    StreamReader scriptStream = new StreamReader(data);

                    List<BundleRewriteScriptAction> scriptActions = ParseScriptActions(ref scriptStream, zip_entry.FileName);
                    data.Close();
                    scriptStream.Close();

                    //apply script functions here
                    if (input != output)
                        input.Seek(bundleEntry.Address, SeekOrigin.Begin);
                    else
                        input.Seek(0, SeekOrigin.Begin);
                    long entryLength = bundleEntry.Length == -1 ? input.Length - input.Position : bundleEntry.Length;

                    List<byte> entryBytes = br.ReadBytes((int)entryLength).ToList();

                    output.Seek(0, SeekOrigin.Begin);
                    if (!ApplyScriptActions(ref entryBytes, ref scriptActions))
                    {
                        bw.Write(br.ReadBytes((int)entryLength));
                        return (int)(entryLength);
                    }

                    bw.Write(entryBytes.ToArray());
                    return (int)entryBytes.ToArray().Length;
                }

                output.Seek(0, SeekOrigin.Begin);

                zip_entry.Extract(output);
                extractedLength = (int)zip_entry.UncompressedSize;

                data.Close();
            }

            return extractedLength;
        }
        private Dictionary<string, string> RetrieveStrings(BundleRewriteItem filepath)
        {
            this.Done = false;

            this._mod.ItemQueue.Clear();
            this._mod.ItemQueue.Add(filepath);

            if (!this.LocateChangeIds())
                return null;

            bool wasSuccessful;
            HashSet<string> bundles = this.LocateBundlesToRewrite(out wasSuccessful);
            if (!wasSuccessful)
                return null;

            if (bundles.Count <= 0)
            {
                this.Error = "Unable to locate any bundles with the requested items in them.\n"
                                + "If the changed file(s) only exists within an all_x.bundle file you will need to enable the option to patch all_x.bundle files.\n"
                                + "Refer to the patch description for if this is required.";
                return null;
            }

            int currentBundle = 1;
            int bundleCount = bundles.Count;

            MemoryStream file_data = new MemoryStream();

            foreach (var bundle in bundles)
            {
                this.SetTotalProgress(
                    string.Format("Reading Bundle {0}/{1}", currentBundle, bundleCount),
                    (int)((currentBundle / (float)bundleCount) * 100.0f));
                if (!this.RetrieveFile(bundle, out file_data))
                    return null;

                if (file_data.Length > 0)
                    break;

                currentBundle += 1;
            }

            if (file_data.Length == 0)
                return null;

            //Extract strings here...
            Dictionary<string, string> return_dictionary = new Dictionary<string, string>();

            this.SetTotalProgress("Done", 100);
            this.Done = true;

            return return_dictionary;
        }
        /// <summary>
        /// The backup bundle entry.
        /// </summary>
        /// <param name="bundlePath">
        /// The bundle path.
        /// </param>
        private void BackupEntries(BundleMod mod, string bundlePath)
        {
            string backupFolder = Path.Combine(this._assetFolder, "asset_backups") + "\\";
            Directory.CreateDirectory(backupFolder);

            var header = new BundleHeader();
            if (!header.Load(bundlePath))
            {
                this.Error = "Failed to parse bundle header: " + bundlePath;
            }

            var bundleFS = new FileStream(bundlePath + ".bundle", FileMode.Open, FileAccess.Read);
            var bundleBR = new BinaryReader(bundleFS);

            foreach (BundleEntry entry in header.Entries)
            {
                BundleRewriteItem rewriteEntryItem;
                BundleRewriteItem backupRewriteItem = new BundleRewriteItem();
                if (mod.ItemQueue.Any(rewriteItem => rewriteItem.Ids.Contains(entry.Id)))
                {
                    NameEntry ne = StaticStorage.Index.Id2Name(entry.Id);
                    rewriteEntryItem = mod.ItemQueue.First(rewriteItem => rewriteItem.Ids.Contains(entry.Id));

                    if (!File.Exists(backupFolder + ne.ToString()))
                    {
                        using (FileStream exportFS = new FileStream(backupFolder + ne.ToString(), FileMode.CreateNew, FileAccess.Write))
                        {
                            using (BinaryWriter exportBW = new BinaryWriter(exportFS))
                            {
                                long entryLength = entry.Length == -1 ? bundleFS.Length - bundleFS.Position : entry.Length;
                                bundleFS.Seek(entry.Address, SeekOrigin.Begin);
                                exportBW.Write(bundleBR.ReadBytes((int)entryLength));
                            }
                        }
                    }
                }
            }

            bundleBR.Close();
            bundleFS.Close();
        }
        /// <summary>
        /// The retrieve file from bundle.
        /// </summary>
        /// <param name="bundleId">
        /// The bundle id.
        /// </param>
        /// <param name="data">
        /// The file data.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public bool RetrieveFile(BundleRewriteItem item, out MemoryStream data)
        {
            data = new MemoryStream();

            if (item.Ids == null)
            {
                item.Ids = StaticStorage.Index.Entry2Id(
                        item.BundlePath,
                        item.BundleExtension,
                        item.BundleLanguage,
                        item.IsLanguageSpecific);
            }

            string bundleId = "";
            foreach (string file in Directory.EnumerateFiles(this._assetFolder, "*_h.bundle"))
            {
                string bundlePath = file.Replace("_h.bundle", string.Empty);
                var header = new BundleHeader();
                if (!header.Load(bundlePath))
                {
                    this.Error = "Failed to parse bundle header: " + bundlePath;
                    return false;
                }

                foreach (BundleEntry entry in header.Entries)
                {
                    if (item.Ids.Contains(entry.Id) && entry.Length > 0)
                    {
                        bundleId = Path.GetFileNameWithoutExtension(bundlePath);

                        var inBundle = new FileStream(Path.Combine(this._assetFolder, bundleId + ".bundle"), FileMode.Open, FileAccess.Read);
                        var inBundleBinary = new BinaryReader(inBundle);

                        inBundle.Seek(entry.Address, SeekOrigin.Begin);
                        long readLength = entry.Length == -1 ? inBundle.Length - inBundle.Position : entry.Length;
                        data.Write(inBundleBinary.ReadBytes((int)readLength), 0, (int)readLength);

                        data.Position = 0L;
                        inBundleBinary.Close();
                        inBundle.Close();

                        return true;
                    }
                }
            }

            return false;
        }