#include #include #include #include #include //Import our code #include "decrypt.h" #include "fileReader.h" #include "utils/min.h" #define BUFFER_SIZE 0xffffUL #define ENCRYPTION_HEADER_LENGTH 12UL #define LOCAL_FILE_HEADER_MAGIC (uint32_t)0x04034b50 uint16_t getUint16(char* buffer) { return (uint16_t)buffer[0] | \ (uint16_t)buffer[1] << 8; } uint32_t getUint32(char* buffer) { return (uint32_t)buffer[0] | \ (uint32_t)buffer[1] << 8 | \ (uint32_t)buffer[2] << 16 | \ (uint32_t)buffer[3] << 24; } int main(int argc, unsigned char *argv[]) { if (argc != 4 && argc != 7) { fprintf(stderr, "Wrong number of arguments. Usage: patcher-installer [ ]"); exit(1); } //TODO: verify argv and assign it to variables char* archiveName = argv[1]; const unsigned long archiveOffset = atol(argv[2]); const unsigned long fileLength = atol(argv[3]); const bool isEncrypted = argc == 7; if (isEncrypted) { uint32_t key0 = atoi(argv[4]); uint32_t key1 = atoi(argv[5]); uint32_t key2 = atoi(argv[6]); //Initialize decryption (pass decryption keys) initDecryptor(key0, key1, key2); } //------------------------------------------------- //Initialize file reader initFileReader(archiveName, archiveOffset); //Skip local file header (30 bytes + additional length) char* fileHeader = getBytes(30UL); //Check that header is correct const uint32_t magic = getUint32(fileHeader); if (magic != LOCAL_FILE_HEADER_MAGIC) { fprintf(stderr, "Wrong magic in local file header, expected %#010x but found %#010x.", LOCAL_FILE_HEADER_MAGIC, magic); exit(1); } free(fileHeader); //Read additional length const unsigned long additionalLength = getUint16(fileHeader + 26) + getUint16(fileHeader + 28); char* additionalBytes = getBytes(additionalLength); free(additionalBytes); //If file is encrypted, skip 12-byte encryption header if (isEncrypted) { char* encrHeader = getBytes(ENCRYPTION_HEADER_LENGTH); decrypt(encrHeader, ENCRYPTION_HEADER_LENGTH); free(encrHeader); } //------------------------------------------------- //Read actual file unsigned long remainingBytes = fileLength; while (remainingBytes > 0) { const unsigned long chunkSize = min(BUFFER_SIZE, remainingBytes); char* chunk = getBytes(chunkSize); remainingBytes -= chunkSize; //Decrypt file if it is encrypted if (isEncrypted) { //TODO: For highest performance, we need to move if condition outside of while loop decrypt(chunk, chunkSize); } //Decompress file //TODO //Optionally perform xdelta3 //TODO //release memory //TODO: need to malloc once outside of while loop, and then reuse it instead of a new malloc() each loop free(chunk); } return 0; }