Esempio n. 1
0
size_t Gft::Leanify(size_t size_leanified /*= 0*/) {
  // header
  uint32_t header_size;
  if (size_ < 0x14 || size_ <= (header_size = *(uint32_t*)(fp_ + 0x10))) {
    std::cerr << "Not a valid GFT file." << std::endl;
    return Format::Leanify(size_leanified);
  }

  // move header
  if (size_leanified) {
    memmove(fp_ - size_leanified, fp_, header_size);
    fp_ -= size_leanified;
  }

  return header_size + LeanifyFile(fp_ + size_leanified + header_size, size_ - header_size, size_leanified);
}
Esempio n. 2
0
int ProcessFile(const wchar_t *file_path)
{
    char mbs[MAX_PATH] = { 0 };
    WideCharToMultiByte(CP_ACP, 0, file_path, -1, mbs, sizeof(mbs) - 1, nullptr, nullptr);
    std::cout << "Processing: " << mbs << std::endl;
    std::string filename(mbs);
#else
// written like this in order to be callback funtion of ftw()
int ProcessFile(const char file_path[], const struct stat *sb = nullptr, int typeflag = FTW_F)
{
    if (typeflag != FTW_F)
    {
        return 0;
    }
    std::cout << "Processing: " << file_path << std::endl;
    std::string filename(file_path);
#endif // _WIN32


    File input_file(file_path);

    if (input_file.IsOK())
    {
        size_t original_size = input_file.GetSize();

        size_t new_size = LeanifyFile(input_file.GetFilePionter(), original_size, 0, filename);

        PrintSize(original_size);
        std::cout << " -> ";
        PrintSize(new_size);
        std::cout << "\tLeanified: ";
        PrintSize(original_size - new_size);

        std::cout << " (" << 100 - 100.0 * new_size / original_size << "%)" << std::endl;

        input_file.UnMapFile(new_size);
    }

    return 0;
}


void PauseIfNotTerminal()
{
    // pause if Leanify is not started in terminal
    // so that user can see the output instead of just a flash of a black box
#ifdef _WIN32
    if (is_pause)
    {
        system("pause");
    }
#endif // _WIN32
}



void PrintInfo()
{
    std::cerr << "Leanify\t" << VERSION_STR << std::endl << std::endl;
    std::cerr <<
        "Usage: leanify [options] paths\n"
        "  -i, --iteration <iteration>   More iterations produce better result, but\n"
        "                                  use more time, default is 15.\n"
        "  -d, --max_depth <max depth>   Maximum recursive depth, unlimited by default.\n"
        "                                  Set to 1 will disable recursive minifying.\n"
        "  -f, --fastmode                Fast mode, no recompression.\n"
        "  -q, --quiet                   No output to stdout.\n"
        "  -v, --verbose                 Verbose output.\n"
        "  --keep-exif                   Do not remove Exif.\n";
    PauseIfNotTerminal();
}
Esempio n. 3
0
size_t Rdb::Leanify(size_t size_leanified /*= 0*/)
{
    if (size <= 0x20)
    {
        std::cerr << "Not a valid RDB file." << std::endl;
        return Format::Leanify(size_leanified);
    }

    depth++;
    char *p_read;
    size_t rdb_size_leanified = 0;

    // header
    p_read = fp;
    fp -= size_leanified;

    // total number of files including directory
    uint32_t file_num = *(uint32_t *)(p_read + 0x10);

    uint64_t index_offset = *(uint64_t *)(p_read + 0x14);

    uint64_t content_offset = index_offset + *(uint64_t *)(p_read + 0x1C);

    // move header and indexes
    if (size_leanified)
    {
        memmove(fp, p_read, (size_t)content_offset);
    }

    char *p_index = fp + index_offset;
    p_read += content_offset;


    for (uint32_t i = 0; i < file_num; i++)
    {
        // index
        wchar_t *file_name = (wchar_t *)p_index;

        // note that on Linux wchar_t is 4 bytes instead of 2
        // so I can't use wcslen
        // p_index += (wcslen(file_name) + 1) * 2;
        while (*(uint16_t *)p_index)
        {
            p_index += 2;
        }
        p_index += 2;

        uint64_t file_size = *(uint64_t *)(p_index + 8);

        *(uint64_t *)p_index -= rdb_size_leanified;

        // skip directories
        if (!file_size)
        {
            p_index += 16;
            continue;
        }

        if (depth <= max_depth)
        {
            // output filename
            for (int i = 1; i < depth; i++)
            {
                std::cout << "-> ";
            }

            char mbs[256] = { 0 };
            UTF16toMBS(file_name, p_index - (char *)file_name, mbs, sizeof(mbs));
            std::cout << mbs << std::endl;

            // Leanify inner file
            size_t new_size = LeanifyFile(p_read, (size_t)file_size, rdb_size_leanified + size_leanified, std::string(mbs));
            if (new_size != file_size)
            {
                // update the size in index
                *(uint64_t *)(p_index + 8) = new_size;
                rdb_size_leanified += (size_t)file_size - new_size;
            }
        }
        else
        {
            memmove(p_read - rdb_size_leanified - size_leanified, p_read, (size_t)file_size);
        }

        p_read += file_size;

        p_index += 16;
    }
    size = p_read - fp - size_leanified - rdb_size_leanified;
    depth--;
    return size;
}
Esempio n. 4
0
size_t Gz::Leanify(size_t size_leanified /*= 0*/)
{
    // written according to this specification
    // http://www.gzip.org/zlib/rfc-gzip.html

    if (size <= 18)
    {
        std::cerr << "Not a valid GZ file." << std::endl;
        return Format::Leanify(size_leanified);
    }

    depth++;
    char flags = *(fp + 3);
    // set the flags to 0, remove all unnecessary section
    *(fp + 3 - size_leanified) = 0;

    char *p_read = fp + 10;
    char *p_write = p_read - size_leanified;

    *(p_write - 2) = 2;     // XFL

    if (flags & (1 << 2))   // FEXTRA
    {
        p_read += *(uint16_t *)p_read + 2;
    }

    std::string filename;
    if (flags & (1 << 3))   // FNAME
    {
        for (int i = 1; i < depth; i++)
        {
            std::cout << "-> ";
        }
        std::cout << p_read << std::endl;
        filename = std::string(p_read);
        while (p_read < fp + size && *p_read++)
        {
            // skip string
        }
    }

    if (flags & (1 << 4))   // FCOMMENT
    {
        while (p_read < fp + size && *p_read++)
        {
            // skip string
        }
    }

    if (flags & (1 << 1))   // FHCRC
    {
        p_read += 2;
    }

    if (p_read >= fp + size)
    {
        return Format::Leanify(size_leanified);
    }

    if (size_leanified)
    {
        memmove(fp - size_leanified, fp, 10);
    }

    if (is_fast)
    {
        memmove(p_write, p_read, fp + size - p_read);
        return size - (p_read - p_write);
    }

    uint32_t uncompressed_size = *(uint32_t *)(fp + size - 4);
    uint32_t crc = *(uint32_t *)(fp + size - 8);
    size_t original_size = fp + size - 8 - p_read;

    size_t s = 0;
    unsigned char *buffer = (unsigned char *)tinfl_decompress_mem_to_heap(p_read, original_size, &s, 0);

    if (!buffer ||
        s != uncompressed_size ||
        crc != mz_crc32(0, buffer, uncompressed_size))
    {
        std::cerr << "GZ corrupted!" << std::endl;
        mz_free(buffer);
        memmove(p_write, p_read, original_size + 8);
        return size - (p_read - p_write);
    }

    uncompressed_size = LeanifyFile(buffer, uncompressed_size, 0, filename);

    ZopfliOptions options;
    ZopfliInitOptions(&options);
    options.numiterations = iterations;

    unsigned char bp = 0, *out = NULL;
    size_t outsize = 0;
    ZopfliDeflate(&options, 2, 1, buffer, uncompressed_size, &bp, &out, &outsize);


    if (outsize < original_size)
    {
        memcpy(p_write, out, outsize);
        p_write += outsize;
        *(uint32_t *)p_write = mz_crc32(0, buffer, uncompressed_size);
        *(uint32_t *)(p_write + 4) = uncompressed_size;
    }
    else
    {
        memmove(p_write, p_read, original_size + 8);
        p_write += original_size;
    }
    mz_free(buffer);
    delete[] out;
    depth--;
    fp -= size_leanified;
    return p_write + 8 - fp;
}