예제 #1
0
        public void calculateHashes(Dictionary <int, Content> allContents)
        {
            byte[] header = rawData;

            // Calculating offset for the hashes

            int cnt          = Utils.SwapEndianness(BitConverter.ToInt32(header, 0x10));
            int start_offset = 0x40 + cnt * 0x04;

            int offset = 0;

            // We have to make sure, that the list is ordered by index
            List <Content> contents = new List <Content>(allContents.Values);

            contents.Sort(delegate(Content c1, Content c2) { return(c1.index.CompareTo(c2.index)); });

            foreach (Content c in allContents.Values)
            {
                if (!c.isHashed() || !c.isEncrypted())
                {
                    continue;
                }

                // The encrypted content are splitted in 0x10000 chunk. For each 0x1000 chunk we need one entry in the h3
                int cnt_hashes = (int)(c.encryptedFileSize / 0x10000 / 0x1000) + 1;

                byte[] hash = Arrays.copyOfRange(header, start_offset + offset * 0x14, start_offset + (offset + cnt_hashes) * 0x14);

                // Checking the hash of the h3 file.
                if (!Arrays.Equals(HashUtil.hashSHA1(hash), c.SHA2Hash))
                {
                    log.TraceEvent(TraceEventType.Error, 0, "h3 incorrect from WUD");
                }

                addH3Hashes(c.index, hash);
                offset += cnt_hashes;
            }

            calculatedHashes = (true);
        }
예제 #2
0
        public static FileInfo compressWUDToWUX(WUDImage image, String outputFolder, String filename, bool overwrite)
        {
            if (image.isCompressed)
            {
                //log.info("Given image is already compressed");
                return(null);
            }

            if (image.getWUDFileSize() != WUDImage.WUD_FILESIZE)
            {
                //log.info("Given WUD has not the expected filesize");
                return(null);
            }

            String usedOutputFolder = outputFolder;

            if (usedOutputFolder == null)
            {
                usedOutputFolder = "";
            }
            Utils.createDir(usedOutputFolder);

            String filePath;

            if (usedOutputFolder == String.Empty)
            {
                filePath = filename;
            }
            else
            {
                filePath = usedOutputFolder + Path.DirectorySeparatorChar + filename;
            }

            FileInfo outputFile = new FileInfo(filePath);

            if (outputFile.Exists && !overwrite)
            {
                //log.info("Couldn't compress wud, target file already exists (" + outputFile.getAbsolutePath() + ")");
                return(null);
            }

            //log.info("Writing compressed file to: " + outputFile.getAbsolutePath());
            FileStream   fileStream = new FileStream(outputFile.FullName, FileMode.Create);
            BinaryWriter fileOutput = new BinaryWriter(fileStream);

            WUDImageCompressedInfo info = WUDImageCompressedInfo.getDefaultCompressedInfo();

            byte[] header = info.getHeaderAsBytes();
            //log.info("Writing header");
            fileOutput.Write(header);

            int sectorTableEntryCount = (int)((image.getWUDFileSize() + WUDImageCompressedInfo.SECTOR_SIZE - 1) / (long)WUDImageCompressedInfo.SECTOR_SIZE);

            long sectorTableStart = fileOutput.BaseStream.Position;
            long sectorTableEnd   = Utils.align(sectorTableEntryCount * 0x04, WUDImageCompressedInfo.SECTOR_SIZE);

            byte[] sectorTablePlaceHolder = new byte[(int)(sectorTableEnd - sectorTableStart)];

            fileOutput.Write(sectorTablePlaceHolder);

            Dictionary <ByteArrayWrapper, int> sectorHashes = new Dictionary <ByteArrayWrapper, int>();
            Dictionary <int, int> sectorMapping             = new Dictionary <int, int>();

            MemoryStream min = image.WUDDiscReader.readEncryptedToInputStream(0, image.getWUDFileSize());

            int bufferSize = WUDImageCompressedInfo.SECTOR_SIZE;

            byte[]          blockBuffer = new byte[bufferSize];
            ByteArrayBuffer overflow    = new ByteArrayBuffer(bufferSize);

            long written    = 0;
            int  curSector  = 0;
            int  realSector = 0;

            //log.info("Writing sectors");

            Int32 oldOffset = int.MinValue;

            min.Seek(0, SeekOrigin.Begin);
            do
            {
                //int read = StreamUtils.getChunkFromStream(in, blockBuffer, overflow, bufferSize);
                int read = min.Read(blockBuffer, 0, bufferSize);
                ByteArrayWrapper hash = new ByteArrayWrapper(HashUtil.hashSHA1(blockBuffer));

                if (!sectorHashes.TryGetValue(hash, out oldOffset))
                {
                    sectorMapping.Add(curSector, realSector);
                    sectorHashes.Add(hash, realSector);
                    fileOutput.Write(blockBuffer);
                    realSector++;
                }
                else
                {
                    sectorMapping.Add(curSector, oldOffset);
                    oldOffset = int.MinValue;
                }

                written += read;
                curSector++;
                if (curSector % 10 == 0)
                {
                    double readMB    = written / 1024.0 / 1024.0;
                    double writtenMB = ((long)realSector * (long)bufferSize) / 1024.0 / 1024.0;
                    double percent   = ((double)written / image.getWUDFileSize()) * 100;
                    double ratio     = 1 / (writtenMB / readMB);
                    //System.out.print(String.format(Locale.ROOT, "\rCompressing into .wux | Progress %.2f%% | Ratio: 1:%.2f | Read: %.2fMB | Written: %.2fMB\t", percent, ratio, readMB, writtenMB));
                }
            } while (written < image.getWUDFileSize());
            //System.out.println();
            //System.out.println("Sectors compressed.");
            //log.info("Writing sector table");
            fileOutput.BaseStream.Seek(sectorTableStart, SeekOrigin.Begin);
            ByteBuffer buffer = ByteBuffer.allocate(sectorTablePlaceHolder.Length);

            //buffer.order(ByteOrder.LITTLE_ENDIAN);
            foreach (var e in sectorMapping)
            {
                buffer.putInt(e.Value);
            }

            fileOutput.Write(buffer.array());
            fileOutput.Close();

            return(outputFile);
        }