aboutsummaryrefslogtreecommitdiff
path: root/contrib/extractor/libmpq/common.cpp
diff options
context:
space:
mode:
authormegamage <none@none>2009-02-12 17:09:15 -0600
committermegamage <none@none>2009-02-12 17:09:15 -0600
commit6aee5fcbe7473a3cbac12b7e8482a7b98bef8be3 (patch)
tree91ec91d5c19eba9c2fe0e84b1c9dc7047a3de80e /contrib/extractor/libmpq/common.cpp
parent2d2f433b4de1c35b22aaf07854fc0ee11fcb350d (diff)
parentf385747164c3fb278c92ef46fbd6c3da6590bbf0 (diff)
*Merge.
--HG-- branch : trunk
Diffstat (limited to 'contrib/extractor/libmpq/common.cpp')
-rw-r--r--contrib/extractor/libmpq/common.cpp1356
1 files changed, 678 insertions, 678 deletions
diff --git a/contrib/extractor/libmpq/common.cpp b/contrib/extractor/libmpq/common.cpp
index 7b902087540..7376a500870 100644
--- a/contrib/extractor/libmpq/common.cpp
+++ b/contrib/extractor/libmpq/common.cpp
@@ -34,19 +34,19 @@
* This function decrypts a MPQ block.
*/
int libmpq_decrypt_block(mpq_archive *mpq_a, unsigned int *block, unsigned int length, unsigned int seed1) {
- unsigned int seed2 = 0xEEEEEEEE;
- unsigned int ch;
-
- /* Round to unsigned int's */
- length >>= 2;
- while (length-- > 0) {
- seed2 += mpq_a->buf[0x400 + (seed1 & 0xFF)];
- ch = *block ^ (seed1 + seed2);
- seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B);
- seed2 = ch + seed2 + (seed2 << 5) + 3;
- *block++ = ch;
- }
- return LIBMPQ_TOOLS_SUCCESS;
+ unsigned int seed2 = 0xEEEEEEEE;
+ unsigned int ch;
+
+ /* Round to unsigned int's */
+ length >>= 2;
+ while (length-- > 0) {
+ seed2 += mpq_a->buf[0x400 + (seed1 & 0xFF)];
+ ch = *block ^ (seed1 + seed2);
+ seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B);
+ seed2 = ch + seed2 + (seed2 << 5) + 3;
+ *block++ = ch;
+ }
+ return LIBMPQ_TOOLS_SUCCESS;
}
/*
@@ -54,164 +54,164 @@ int libmpq_decrypt_block(mpq_archive *mpq_a, unsigned int *block, unsigned int l
* file informations.
*/
int libmpq_decrypt_hashtable(mpq_archive *mpq_a, unsigned char *pbKey) {
- unsigned int seed1 = 0x7FED7FED;
- unsigned int seed2 = 0xEEEEEEEE;
- unsigned int ch; /* One key character */
- unsigned int *pdwTable = (unsigned int *)(mpq_a->hashtable);
- unsigned int length = mpq_a->header->hashtablesize * 4;
-
- /* Prepare seeds */
- while (*pbKey != 0) {
- ch = toupper(*pbKey++);
- seed1 = mpq_a->buf[0x300 + ch] ^ (seed1 + seed2);
- seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
- }
-
- /* Decrypt it */
- seed2 = 0xEEEEEEEE;
- while (length-- > 0) {
- seed2 += mpq_a->buf[0x400 + (seed1 & 0xFF)];
- ch = *pdwTable ^ (seed1 + seed2);
- seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B);
- seed2 = ch + seed2 + (seed2 << 5) + 3;
- *pdwTable++ = ch;
- }
- return LIBMPQ_TOOLS_SUCCESS;
+ unsigned int seed1 = 0x7FED7FED;
+ unsigned int seed2 = 0xEEEEEEEE;
+ unsigned int ch; /* One key character */
+ unsigned int *pdwTable = (unsigned int *)(mpq_a->hashtable);
+ unsigned int length = mpq_a->header->hashtablesize * 4;
+
+ /* Prepare seeds */
+ while (*pbKey != 0) {
+ ch = toupper(*pbKey++);
+ seed1 = mpq_a->buf[0x300 + ch] ^ (seed1 + seed2);
+ seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
+ }
+
+ /* Decrypt it */
+ seed2 = 0xEEEEEEEE;
+ while (length-- > 0) {
+ seed2 += mpq_a->buf[0x400 + (seed1 & 0xFF)];
+ ch = *pdwTable ^ (seed1 + seed2);
+ seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B);
+ seed2 = ch + seed2 + (seed2 << 5) + 3;
+ *pdwTable++ = ch;
+ }
+ return LIBMPQ_TOOLS_SUCCESS;
}
/*
* This function decrypts the blocktable.
*/
int libmpq_decrypt_blocktable(mpq_archive *mpq_a, unsigned char *pbKey) {
- unsigned int seed1 = 0x7FED7FED;
- unsigned int seed2 = 0xEEEEEEEE;
- unsigned int ch; /* One key character */
- unsigned int *pdwTable = (unsigned int *)(mpq_a->blocktable);
- unsigned int length = mpq_a->header->blocktablesize * 4;
-
- /* Prepare seeds */
- while(*pbKey != 0) {
- ch = toupper(*pbKey++);
- seed1 = mpq_a->buf[0x300 + ch] ^ (seed1 + seed2);
- seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
- }
-
- /* Decrypt it */
- seed2 = 0xEEEEEEEE;
- while(length-- > 0) {
- seed2 += mpq_a->buf[0x400 + (seed1 & 0xFF)];
- ch = *pdwTable ^ (seed1 + seed2);
- seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B);
- seed2 = ch + seed2 + (seed2 << 5) + 3;
- *pdwTable++ = ch;
- }
- return LIBMPQ_TOOLS_SUCCESS;
+ unsigned int seed1 = 0x7FED7FED;
+ unsigned int seed2 = 0xEEEEEEEE;
+ unsigned int ch; /* One key character */
+ unsigned int *pdwTable = (unsigned int *)(mpq_a->blocktable);
+ unsigned int length = mpq_a->header->blocktablesize * 4;
+
+ /* Prepare seeds */
+ while(*pbKey != 0) {
+ ch = toupper(*pbKey++);
+ seed1 = mpq_a->buf[0x300 + ch] ^ (seed1 + seed2);
+ seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
+ }
+
+ /* Decrypt it */
+ seed2 = 0xEEEEEEEE;
+ while(length-- > 0) {
+ seed2 += mpq_a->buf[0x400 + (seed1 & 0xFF)];
+ ch = *pdwTable ^ (seed1 + seed2);
+ seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B);
+ seed2 = ch + seed2 + (seed2 << 5) + 3;
+ *pdwTable++ = ch;
+ }
+ return LIBMPQ_TOOLS_SUCCESS;
}
int libmpq_read_listfile(mpq_archive *mpq_a, FILE *fp) {
- int mpq_size;
- int mpq_ht_size;
- int mpq_bt_size;
- int mpq_blocksize;
- int mpq_files;
- int mpq_csize;
- int mpq_fsize;
- int entries;
- char listdb_version[10];
- char libmpq_version[10];
- int listdb_temp_version = 0;
- int libmpq_temp_version = 0;
-
- /* first check header and version */
- if (libmpq_conf_get_value(fp, "LIBMPQ_VERSION", mpq_a->mpq_l->mpq_version, LIBMPQ_CONF_TYPE_CHAR, sizeof(mpq_a->mpq_l->mpq_version))) {
- return LIBMPQ_CONF_EFILE_CORRUPT;
- } else {
-
- /* copy to temp buffer for removing . characters */
- sprintf(listdb_version, (char *)mpq_a->mpq_l->mpq_version);
-
- /* remove . characters from listfile version */
- libmpq_conf_delete_char(listdb_version, ".");
-
- /* get libmpq version */
- sprintf(libmpq_version, "%i%i%i",LIBMPQ_MAJOR_VERSION, LIBMPQ_MINOR_VERSION, LIBMPQ_PATCH_VERSION);
-
- /* convert to number */
- listdb_temp_version = atoi(listdb_version);
- libmpq_temp_version = atoi(libmpq_version);
-
- /* check if installed libmpq version is valid for listfile version */
- if ((libmpq_temp_version < listdb_temp_version) || (libmpq_temp_version == 0) || (listdb_temp_version == 0)) {
- return LIBMPQ_CONF_EFILE_VERSION;
- }
- }
-
- /* check listfile header, the following entries must be set */
- if (libmpq_conf_get_value(fp, "MPQ_SIZE", &mpq_size, LIBMPQ_CONF_TYPE_INT, 0)) {
- return LIBMPQ_CONF_EFILE_CORRUPT;
- }
- if (libmpq_conf_get_value(fp, "MPQ_HASHTABLE_SIZE", &mpq_ht_size, LIBMPQ_CONF_TYPE_INT, 0)) {
- return LIBMPQ_CONF_EFILE_CORRUPT;
- }
- if (libmpq_conf_get_value(fp, "MPQ_BLOCKTABLE_SIZE", &mpq_bt_size, LIBMPQ_CONF_TYPE_INT, 0)) {
- return LIBMPQ_CONF_EFILE_CORRUPT;
- }
- if (libmpq_conf_get_value(fp, "MPQ_BLOCKSIZE", &mpq_blocksize, LIBMPQ_CONF_TYPE_INT, 0)) {
- return LIBMPQ_CONF_EFILE_CORRUPT;
- }
- if (libmpq_conf_get_value(fp, "MPQ_FILES", &mpq_files, LIBMPQ_CONF_TYPE_INT, 0)) {
- return LIBMPQ_CONF_EFILE_CORRUPT;
- }
- if (libmpq_conf_get_value(fp, "MPQ_COMPRESSED_SIZE", &mpq_csize, LIBMPQ_CONF_TYPE_INT, 0)) {
- return LIBMPQ_CONF_EFILE_CORRUPT;
- }
- if (libmpq_conf_get_value(fp, "MPQ_UNCOMPRESSED_SIZE", &mpq_fsize, LIBMPQ_CONF_TYPE_INT, 0)) {
- return LIBMPQ_CONF_EFILE_CORRUPT;
- }
- if (libmpq_conf_get_value(fp, "MPQ_NAME", mpq_a->mpq_l->mpq_name, LIBMPQ_CONF_TYPE_CHAR, PATH_MAX)) {
- return LIBMPQ_CONF_EFILE_CORRUPT;
- }
- if (libmpq_conf_get_value(fp, "MPQ_TYPE", mpq_a->mpq_l->mpq_type, LIBMPQ_CONF_TYPE_CHAR, sizeof(mpq_a->mpq_l->mpq_type))) {
- return LIBMPQ_CONF_EFILE_CORRUPT;
- }
-
- /* these are optional parameters, if they are empty we set the struct members empty */
- libmpq_conf_get_value(fp, "MPQ_GAME", mpq_a->mpq_l->mpq_game, LIBMPQ_CONF_TYPE_CHAR, sizeof(mpq_a->mpq_l->mpq_game));
- libmpq_conf_get_value(fp, "MPQ_GAME_VERSION", mpq_a->mpq_l->mpq_game_version, LIBMPQ_CONF_TYPE_CHAR, sizeof(mpq_a->mpq_l->mpq_game_version));
-
- /* check if we found a valid listfile for the given archive */
- if (mpq_a->header->hashtablesize == mpq_ht_size && mpq_a->header->blocktablesize == mpq_bt_size && mpq_a->blocksize == mpq_blocksize && libmpq_archive_info(mpq_a, LIBMPQ_MPQ_ARCHIVE_SIZE) == mpq_size && libmpq_archive_info(mpq_a, LIBMPQ_MPQ_NUMFILES) == mpq_files && libmpq_archive_info(mpq_a, LIBMPQ_MPQ_COMPRESSED_SIZE) == mpq_csize && libmpq_archive_info(mpq_a, LIBMPQ_MPQ_UNCOMPRESSED_SIZE) == mpq_fsize) {
-
- /* check if the filelist is correct */
- if (!libmpq_conf_get_array(fp, "FILE_NAMES", (char ***)&mpq_a->mpq_l->mpq_files, &entries)) {
-
- /* we have a corrupt filelist, so return */
- return LIBMPQ_CONF_EFILE_LIST_CORRUPT;
- } else {
-
- /* now check if filelist entries matches number of files in the archive. */
- if (entries != libmpq_archive_info(mpq_a, LIBMPQ_MPQ_NUMFILES)) {
- libmpq_free_listfile((char **)mpq_a->mpq_l->mpq_files);
- mpq_a->mpq_l->mpq_files = NULL;
- return LIBMPQ_CONF_EFILE_LIST_CORRUPT;
- }
- }
- }
-
- return LIBMPQ_TOOLS_SUCCESS;
+ int mpq_size;
+ int mpq_ht_size;
+ int mpq_bt_size;
+ int mpq_blocksize;
+ int mpq_files;
+ int mpq_csize;
+ int mpq_fsize;
+ int entries;
+ char listdb_version[10];
+ char libmpq_version[10];
+ int listdb_temp_version = 0;
+ int libmpq_temp_version = 0;
+
+ /* first check header and version */
+ if (libmpq_conf_get_value(fp, "LIBMPQ_VERSION", mpq_a->mpq_l->mpq_version, LIBMPQ_CONF_TYPE_CHAR, sizeof(mpq_a->mpq_l->mpq_version))) {
+ return LIBMPQ_CONF_EFILE_CORRUPT;
+ } else {
+
+ /* copy to temp buffer for removing . characters */
+ sprintf(listdb_version, (char *)mpq_a->mpq_l->mpq_version);
+
+ /* remove . characters from listfile version */
+ libmpq_conf_delete_char(listdb_version, ".");
+
+ /* get libmpq version */
+ sprintf(libmpq_version, "%i%i%i",LIBMPQ_MAJOR_VERSION, LIBMPQ_MINOR_VERSION, LIBMPQ_PATCH_VERSION);
+
+ /* convert to number */
+ listdb_temp_version = atoi(listdb_version);
+ libmpq_temp_version = atoi(libmpq_version);
+
+ /* check if installed libmpq version is valid for listfile version */
+ if ((libmpq_temp_version < listdb_temp_version) || (libmpq_temp_version == 0) || (listdb_temp_version == 0)) {
+ return LIBMPQ_CONF_EFILE_VERSION;
+ }
+ }
+
+ /* check listfile header, the following entries must be set */
+ if (libmpq_conf_get_value(fp, "MPQ_SIZE", &mpq_size, LIBMPQ_CONF_TYPE_INT, 0)) {
+ return LIBMPQ_CONF_EFILE_CORRUPT;
+ }
+ if (libmpq_conf_get_value(fp, "MPQ_HASHTABLE_SIZE", &mpq_ht_size, LIBMPQ_CONF_TYPE_INT, 0)) {
+ return LIBMPQ_CONF_EFILE_CORRUPT;
+ }
+ if (libmpq_conf_get_value(fp, "MPQ_BLOCKTABLE_SIZE", &mpq_bt_size, LIBMPQ_CONF_TYPE_INT, 0)) {
+ return LIBMPQ_CONF_EFILE_CORRUPT;
+ }
+ if (libmpq_conf_get_value(fp, "MPQ_BLOCKSIZE", &mpq_blocksize, LIBMPQ_CONF_TYPE_INT, 0)) {
+ return LIBMPQ_CONF_EFILE_CORRUPT;
+ }
+ if (libmpq_conf_get_value(fp, "MPQ_FILES", &mpq_files, LIBMPQ_CONF_TYPE_INT, 0)) {
+ return LIBMPQ_CONF_EFILE_CORRUPT;
+ }
+ if (libmpq_conf_get_value(fp, "MPQ_COMPRESSED_SIZE", &mpq_csize, LIBMPQ_CONF_TYPE_INT, 0)) {
+ return LIBMPQ_CONF_EFILE_CORRUPT;
+ }
+ if (libmpq_conf_get_value(fp, "MPQ_UNCOMPRESSED_SIZE", &mpq_fsize, LIBMPQ_CONF_TYPE_INT, 0)) {
+ return LIBMPQ_CONF_EFILE_CORRUPT;
+ }
+ if (libmpq_conf_get_value(fp, "MPQ_NAME", mpq_a->mpq_l->mpq_name, LIBMPQ_CONF_TYPE_CHAR, PATH_MAX)) {
+ return LIBMPQ_CONF_EFILE_CORRUPT;
+ }
+ if (libmpq_conf_get_value(fp, "MPQ_TYPE", mpq_a->mpq_l->mpq_type, LIBMPQ_CONF_TYPE_CHAR, sizeof(mpq_a->mpq_l->mpq_type))) {
+ return LIBMPQ_CONF_EFILE_CORRUPT;
+ }
+
+ /* these are optional parameters, if they are empty we set the struct members empty */
+ libmpq_conf_get_value(fp, "MPQ_GAME", mpq_a->mpq_l->mpq_game, LIBMPQ_CONF_TYPE_CHAR, sizeof(mpq_a->mpq_l->mpq_game));
+ libmpq_conf_get_value(fp, "MPQ_GAME_VERSION", mpq_a->mpq_l->mpq_game_version, LIBMPQ_CONF_TYPE_CHAR, sizeof(mpq_a->mpq_l->mpq_game_version));
+
+ /* check if we found a valid listfile for the given archive */
+ if (mpq_a->header->hashtablesize == mpq_ht_size && mpq_a->header->blocktablesize == mpq_bt_size && mpq_a->blocksize == mpq_blocksize && libmpq_archive_info(mpq_a, LIBMPQ_MPQ_ARCHIVE_SIZE) == mpq_size && libmpq_archive_info(mpq_a, LIBMPQ_MPQ_NUMFILES) == mpq_files && libmpq_archive_info(mpq_a, LIBMPQ_MPQ_COMPRESSED_SIZE) == mpq_csize && libmpq_archive_info(mpq_a, LIBMPQ_MPQ_UNCOMPRESSED_SIZE) == mpq_fsize) {
+
+ /* check if the filelist is correct */
+ if (!libmpq_conf_get_array(fp, "FILE_NAMES", (char ***)&mpq_a->mpq_l->mpq_files, &entries)) {
+
+ /* we have a corrupt filelist, so return */
+ return LIBMPQ_CONF_EFILE_LIST_CORRUPT;
+ } else {
+
+ /* now check if filelist entries matches number of files in the archive. */
+ if (entries != libmpq_archive_info(mpq_a, LIBMPQ_MPQ_NUMFILES)) {
+ libmpq_free_listfile((char **)mpq_a->mpq_l->mpq_files);
+ mpq_a->mpq_l->mpq_files = NULL;
+ return LIBMPQ_CONF_EFILE_LIST_CORRUPT;
+ }
+ }
+ }
+
+ return LIBMPQ_TOOLS_SUCCESS;
}
/*
* This function frees up the space reserved by libmpq_get_listfile()
*/
int libmpq_free_listfile(char **filelist) {
- int i = 0;
- while (filelist[i]) {
- free(filelist[i++]);
- }
- free(filelist);
+ int i = 0;
+ while (filelist[i]) {
+ free(filelist[i++]);
+ }
+ free(filelist);
- return LIBMPQ_TOOLS_SUCCESS;
+ return LIBMPQ_TOOLS_SUCCESS;
}
/*
@@ -220,84 +220,84 @@ int libmpq_free_listfile(char **filelist) {
* array.
*/
/*int libmpq_detect_listfile_rec(char path[PATH_MAX], char ***filelist, int *fl_count, int *fl_size) {
- char nextpath[PATH_MAX];
- DIR *dp = opendir(path);
- FILE *fp;
- struct dirent *entry;
- struct stat statbuf;
- char buf[LIBMPQ_CONF_BUFSIZE];
-
- if (dp == NULL) {
- return LIBMPQ_CONF_EOPEN_DIR;
- } else {
- while ((entry = readdir(dp)) != NULL) {
- if (strncmp(entry->d_name, ".", 1) == 0 || strncmp(entry->d_name, "..", 2) == 0) {
- continue;
- }
- if (strnlen(path, PATH_MAX) + strnlen(entry->d_name, PATH_MAX) + 2 > sizeof nextpath) {
- continue;
- }
-
- snprintf(nextpath, PATH_MAX, "%s/%s", path, entry->d_name);
-
- // check if file extension matches listdb file extension
- if (strncmp(&entry->d_name[strlen(entry->d_name) - strlen(LIBMPQ_CONF_EXT)], LIBMPQ_CONF_EXT, strlen(LIBMPQ_CONF_EXT)) == 0) {
-
- // check if it is really a listdb file
- if ((fp = fopen(nextpath, "r")) != NULL ) {
- while (fgets(buf, LIBMPQ_CONF_BUFSIZE, fp) != NULL) {
- char *line;
-
- buf[strlen(buf) - 1] = '\0';
-
- // skip whitespace
- for (line = buf; isspace(*line); line++) {
- continue;
- }
-
- // skip empty line
- if (line[0] == '\0') {
- continue;
- }
-
- // skip comments
- if (line[0] == '#') {
- continue;
- }
-
- //search for listdb header; dirty but works :)
- if (!strncasecmp(line, LIBMPQ_CONF_HEADER, strlen(LIBMPQ_CONF_HEADER))) {
-
- // set the next filelist entry to a copy of the file path
- (*filelist)[(*fl_count)++] = strdup(nextpath);
-
- // increase the array size
- if ((*fl_count) == (*fl_size)) {
- (*filelist) = realloc((*filelist), ((*fl_size) + LIBMPQ_CONF_FL_INCREMENT) * sizeof(char *));
- (*fl_size) += LIBMPQ_CONF_FL_INCREMENT;
- }
-
- // header found so we could stop reading the file.
- break;
- }
- }
- fclose(fp);
- }
- }
-
- if (stat(nextpath, &statbuf) < 0) {
- continue;
- }
-
- // if entry ia a subdirectory, read it
- if (S_ISDIR(statbuf.st_mode)) {
- libmpq_detect_listfile_rec(nextpath, filelist, fl_count, fl_size);
- }
- }
- closedir(dp);
- }
-
- return LIBMPQ_TOOLS_SUCCESS;
+ char nextpath[PATH_MAX];
+ DIR *dp = opendir(path);
+ FILE *fp;
+ struct dirent *entry;
+ struct stat statbuf;
+ char buf[LIBMPQ_CONF_BUFSIZE];
+
+ if (dp == NULL) {
+ return LIBMPQ_CONF_EOPEN_DIR;
+ } else {
+ while ((entry = readdir(dp)) != NULL) {
+ if (strncmp(entry->d_name, ".", 1) == 0 || strncmp(entry->d_name, "..", 2) == 0) {
+ continue;
+ }
+ if (strnlen(path, PATH_MAX) + strnlen(entry->d_name, PATH_MAX) + 2 > sizeof nextpath) {
+ continue;
+ }
+
+ snprintf(nextpath, PATH_MAX, "%s/%s", path, entry->d_name);
+
+ // check if file extension matches listdb file extension
+ if (strncmp(&entry->d_name[strlen(entry->d_name) - strlen(LIBMPQ_CONF_EXT)], LIBMPQ_CONF_EXT, strlen(LIBMPQ_CONF_EXT)) == 0) {
+
+ // check if it is really a listdb file
+ if ((fp = fopen(nextpath, "r")) != NULL ) {
+ while (fgets(buf, LIBMPQ_CONF_BUFSIZE, fp) != NULL) {
+ char *line;
+
+ buf[strlen(buf) - 1] = '\0';
+
+ // skip whitespace
+ for (line = buf; isspace(*line); line++) {
+ continue;
+ }
+
+ // skip empty line
+ if (line[0] == '\0') {
+ continue;
+ }
+
+ // skip comments
+ if (line[0] == '#') {
+ continue;
+ }
+
+ //search for listdb header; dirty but works :)
+ if (!strncasecmp(line, LIBMPQ_CONF_HEADER, strlen(LIBMPQ_CONF_HEADER))) {
+
+ // set the next filelist entry to a copy of the file path
+ (*filelist)[(*fl_count)++] = strdup(nextpath);
+
+ // increase the array size
+ if ((*fl_count) == (*fl_size)) {
+ (*filelist) = realloc((*filelist), ((*fl_size) + LIBMPQ_CONF_FL_INCREMENT) * sizeof(char *));
+ (*fl_size) += LIBMPQ_CONF_FL_INCREMENT;
+ }
+
+ // header found so we could stop reading the file.
+ break;
+ }
+ }
+ fclose(fp);
+ }
+ }
+
+ if (stat(nextpath, &statbuf) < 0) {
+ continue;
+ }
+
+ // if entry ia a subdirectory, read it
+ if (S_ISDIR(statbuf.st_mode)) {
+ libmpq_detect_listfile_rec(nextpath, filelist, fl_count, fl_size);
+ }
+ }
+ closedir(dp);
+ }
+
+ return LIBMPQ_TOOLS_SUCCESS;
}
*/
@@ -309,69 +309,69 @@ int libmpq_free_listfile(char **filelist) {
* we can find the decryption key.
*/
int libmpq_detect_fileseed(mpq_archive *mpq_a, unsigned int *block, unsigned int decrypted) {
- unsigned int saveseed1;
- unsigned int temp = *block ^ decrypted; /* temp = seed1 + seed2 */
- int i = 0;
- temp -= 0xEEEEEEEE; /* temp = seed1 + mpq_a->buf[0x400 + (seed1 & 0xFF)] */
-
- for (i = 0; i < 0x100; i++) { /* Try all 255 possibilities */
- unsigned int seed1;
- unsigned int seed2 = 0xEEEEEEEE;
- unsigned int ch;
-
- /* Try the first unsigned int's (We exactly know the value) */
- seed1 = temp - mpq_a->buf[0x400 + i];
- seed2 += mpq_a->buf[0x400 + (seed1 & 0xFF)];
- ch = block[0] ^ (seed1 + seed2);
-
- if (ch != decrypted) {
- continue;
- }
-
- /* Add 1 because we are decrypting block positions */
- saveseed1 = seed1 + 1;
-
- /*
- * If OK, continue and test the second value. We don't know exactly the value,
- * but we know that the second one has lower 16 bits set to zero
- * (no compressed block is larger than 0xFFFF bytes)
- */
- seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B);
- seed2 = ch + seed2 + (seed2 << 5) + 3;
- seed2 += mpq_a->buf[0x400 + (seed1 & 0xFF)];
- ch = block[1] ^ (seed1 + seed2);
- if ((ch & 0xFFFF0000) == 0) {
- return saveseed1;
- }
- }
- return LIBMPQ_TOOLS_SUCCESS;
+ unsigned int saveseed1;
+ unsigned int temp = *block ^ decrypted; /* temp = seed1 + seed2 */
+ int i = 0;
+ temp -= 0xEEEEEEEE; /* temp = seed1 + mpq_a->buf[0x400 + (seed1 & 0xFF)] */
+
+ for (i = 0; i < 0x100; i++) { /* Try all 255 possibilities */
+ unsigned int seed1;
+ unsigned int seed2 = 0xEEEEEEEE;
+ unsigned int ch;
+
+ /* Try the first unsigned int's (We exactly know the value) */
+ seed1 = temp - mpq_a->buf[0x400 + i];
+ seed2 += mpq_a->buf[0x400 + (seed1 & 0xFF)];
+ ch = block[0] ^ (seed1 + seed2);
+
+ if (ch != decrypted) {
+ continue;
+ }
+
+ /* Add 1 because we are decrypting block positions */
+ saveseed1 = seed1 + 1;
+
+ /*
+ * If OK, continue and test the second value. We don't know exactly the value,
+ * but we know that the second one has lower 16 bits set to zero
+ * (no compressed block is larger than 0xFFFF bytes)
+ */
+ seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B);
+ seed2 = ch + seed2 + (seed2 << 5) + 3;
+ seed2 += mpq_a->buf[0x400 + (seed1 & 0xFF)];
+ ch = block[1] ^ (seed1 + seed2);
+ if ((ch & 0xFFFF0000) == 0) {
+ return saveseed1;
+ }
+ }
+ return LIBMPQ_TOOLS_SUCCESS;
}
/*
* This function initialize the decryption buffer
*/
int libmpq_init_buffer(mpq_archive *mpq_a) {
- unsigned int seed = 0x00100001;
- unsigned int index1 = 0;
- unsigned int index2 = 0;
- int i;
-
- memset(mpq_a->buf, 0, sizeof(mpq_a->buf));
-
- /* Initialize the decryption buffer. */
- for (index1 = 0; index1 < 0x100; index1++) {
- for(index2 = index1, i = 0; i < 5; i++, index2 += 0x100) {
- unsigned int temp1, temp2;
- seed = (seed * 125 + 3) % 0x2AAAAB;
- temp1 = (seed & 0xFFFF) << 0x10;
-
- seed = (seed * 125 + 3) % 0x2AAAAB;
- temp2 = (seed & 0xFFFF);
-
- mpq_a->buf[index2] = (temp1 | temp2);
- }
- }
- return LIBMPQ_TOOLS_SUCCESS;
+ unsigned int seed = 0x00100001;
+ unsigned int index1 = 0;
+ unsigned int index2 = 0;
+ int i;
+
+ memset(mpq_a->buf, 0, sizeof(mpq_a->buf));
+
+ /* Initialize the decryption buffer. */
+ for (index1 = 0; index1 < 0x100; index1++) {
+ for(index2 = index1, i = 0; i < 5; i++, index2 += 0x100) {
+ unsigned int temp1, temp2;
+ seed = (seed * 125 + 3) % 0x2AAAAB;
+ temp1 = (seed & 0xFFFF) << 0x10;
+
+ seed = (seed * 125 + 3) % 0x2AAAAB;
+ temp2 = (seed & 0xFFFF);
+
+ mpq_a->buf[index2] = (temp1 | temp2);
+ }
+ }
+ return LIBMPQ_TOOLS_SUCCESS;
}
/*
@@ -380,52 +380,52 @@ int libmpq_init_buffer(mpq_archive *mpq_a) {
* be decrypted for later use.
*/
int libmpq_read_hashtable(mpq_archive *mpq_a) {
- unsigned int bytes = 0;
- int rb = 0;
-
- /*
- * Allocate memory. Note that the block table should be as large as the
- * hash table. (for later file additions)
- */
- mpq_a->hashtable = (mpq_hash *)malloc(sizeof(mpq_hash) * mpq_a->header->hashtablesize);
-
- if (!mpq_a->hashtable) {
- return LIBMPQ_EALLOCMEM;
- }
-
- /* Read the hash table into the buffer */
- bytes = mpq_a->header->hashtablesize * sizeof(mpq_hash);
-
- #ifdef WIN32
- _lseeki64(mpq_a->fd, mpq_a->header->hashtablepos, SEEK_SET);
- #else
- lseek64(mpq_a->fd, mpq_a->header->hashtablepos, SEEK_SET);
- #endif
-
- rb = _read(mpq_a->fd, mpq_a->hashtable, bytes);
- if (rb != bytes) {
- return LIBMPQ_EFILE_CORRUPT;
- }
-
- /* Decrypt hash table and check if it is correctly decrypted */
- mpq_hash *mpq_h_end = mpq_a->hashtable + mpq_a->header->hashtablesize;
- mpq_hash *mpq_h = NULL;
-
- libmpq_decrypt_hashtable(mpq_a, (unsigned char *)"(hash table)");
-
- /* Check hash table if is correctly decrypted */
- for (mpq_h = mpq_a->hashtable; mpq_h < mpq_h_end; mpq_h++) {
- if (mpq_h->locale != 0xFFFFFFFF && (mpq_h->locale & 0xFFFF0000) != 0) {
- return LIBMPQ_EFILE_FORMAT;
- }
-
- /* Remember the highest block table entry */
- if (mpq_h->blockindex < LIBMPQ_HASH_ENTRY_DELETED && mpq_h->blockindex > 0) {
- mpq_a->maxblockindex = mpq_h->blockindex;
- }
- }
-
- return LIBMPQ_TOOLS_SUCCESS;
+ unsigned int bytes = 0;
+ int rb = 0;
+
+ /*
+ * Allocate memory. Note that the block table should be as large as the
+ * hash table. (for later file additions)
+ */
+ mpq_a->hashtable = (mpq_hash *)malloc(sizeof(mpq_hash) * mpq_a->header->hashtablesize);
+
+ if (!mpq_a->hashtable) {
+ return LIBMPQ_EALLOCMEM;
+ }
+
+ /* Read the hash table into the buffer */
+ bytes = mpq_a->header->hashtablesize * sizeof(mpq_hash);
+
+ #ifdef WIN32
+ _lseeki64(mpq_a->fd, mpq_a->header->hashtablepos, SEEK_SET);
+ #else
+ lseek64(mpq_a->fd, mpq_a->header->hashtablepos, SEEK_SET);
+ #endif
+
+ rb = _read(mpq_a->fd, mpq_a->hashtable, bytes);
+ if (rb != bytes) {
+ return LIBMPQ_EFILE_CORRUPT;
+ }
+
+ /* Decrypt hash table and check if it is correctly decrypted */
+ mpq_hash *mpq_h_end = mpq_a->hashtable + mpq_a->header->hashtablesize;
+ mpq_hash *mpq_h = NULL;
+
+ libmpq_decrypt_hashtable(mpq_a, (unsigned char *)"(hash table)");
+
+ /* Check hash table if is correctly decrypted */
+ for (mpq_h = mpq_a->hashtable; mpq_h < mpq_h_end; mpq_h++) {
+ if (mpq_h->locale != 0xFFFFFFFF && (mpq_h->locale & 0xFFFF0000) != 0) {
+ return LIBMPQ_EFILE_FORMAT;
+ }
+
+ /* Remember the highest block table entry */
+ if (mpq_h->blockindex < LIBMPQ_HASH_ENTRY_DELETED && mpq_h->blockindex > 0) {
+ mpq_a->maxblockindex = mpq_h->blockindex;
+ }
+ }
+
+ return LIBMPQ_TOOLS_SUCCESS;
}
/*
@@ -437,365 +437,365 @@ int libmpq_read_hashtable(mpq_archive *mpq_a) {
* cracked Diablo versions.
*/
int libmpq_read_blocktable(mpq_archive *mpq_a) {
- unsigned int bytes = 0;
- int rb = 0;
-
- /*
- * Allocate memory. Note that the block table should be as large as the
- * hash table. (for later file additions)
- */
- mpq_a->blocktable = (mpq_block *)malloc(sizeof(mpq_block) * mpq_a->header->hashtablesize);
- mpq_a->blockbuf = (unsigned char *)malloc(mpq_a->blocksize);
-
- if (!mpq_a->blocktable || !mpq_a->blockbuf) {
- return LIBMPQ_EALLOCMEM;
- }
-
- /* Read the block table into the buffer */
- bytes = mpq_a->header->blocktablesize * sizeof(mpq_block);
- memset(mpq_a->blocktable, 0, mpq_a->header->blocktablesize * sizeof(mpq_block));
-
- #ifdef WIN32
- _lseeki64(mpq_a->fd, mpq_a->header->blocktablepos, SEEK_SET);
- #else
- lseek64(mpq_a->fd, mpq_a->header->blocktablepos, SEEK_SET);
- #endif
-
- rb = _read(mpq_a->fd, mpq_a->blocktable, bytes);
- if (rb != bytes) {
- return LIBMPQ_EFILE_CORRUPT;
- }
-
- /*
- * Decrypt block table. Some MPQs don't have encrypted block table,
- * e.g. cracked Diablo version. We have to check if block table is
- * already decrypted
- */
- mpq_block *mpq_b_end = mpq_a->blocktable + mpq_a->maxblockindex + 1;
- mpq_block *mpq_b = NULL;
- unsigned int archivesize = mpq_a->header->archivesize + mpq_a->mpqpos;
-
- if (mpq_a->header->offset != mpq_a->blocktable->filepos) {
- libmpq_decrypt_blocktable(mpq_a, (unsigned char *)"(block table)");
- }
- for (mpq_b = mpq_a->blocktable; mpq_b < mpq_b_end; mpq_b++) {
- if (mpq_b->filepos > archivesize || mpq_b->csize > archivesize) {
- if ((mpq_a->flags & LIBMPQ_FLAG_PROTECTED) == 0) {
- return LIBMPQ_EFILE_FORMAT;
- }
- }
- mpq_b->filepos += mpq_a->mpqpos;
- }
-
- return LIBMPQ_TOOLS_SUCCESS;
+ unsigned int bytes = 0;
+ int rb = 0;
+
+ /*
+ * Allocate memory. Note that the block table should be as large as the
+ * hash table. (for later file additions)
+ */
+ mpq_a->blocktable = (mpq_block *)malloc(sizeof(mpq_block) * mpq_a->header->hashtablesize);
+ mpq_a->blockbuf = (unsigned char *)malloc(mpq_a->blocksize);
+
+ if (!mpq_a->blocktable || !mpq_a->blockbuf) {
+ return LIBMPQ_EALLOCMEM;
+ }
+
+ /* Read the block table into the buffer */
+ bytes = mpq_a->header->blocktablesize * sizeof(mpq_block);
+ memset(mpq_a->blocktable, 0, mpq_a->header->blocktablesize * sizeof(mpq_block));
+
+ #ifdef WIN32
+ _lseeki64(mpq_a->fd, mpq_a->header->blocktablepos, SEEK_SET);
+ #else
+ lseek64(mpq_a->fd, mpq_a->header->blocktablepos, SEEK_SET);
+ #endif
+
+ rb = _read(mpq_a->fd, mpq_a->blocktable, bytes);
+ if (rb != bytes) {
+ return LIBMPQ_EFILE_CORRUPT;
+ }
+
+ /*
+ * Decrypt block table. Some MPQs don't have encrypted block table,
+ * e.g. cracked Diablo version. We have to check if block table is
+ * already decrypted
+ */
+ mpq_block *mpq_b_end = mpq_a->blocktable + mpq_a->maxblockindex + 1;
+ mpq_block *mpq_b = NULL;
+ unsigned int archivesize = mpq_a->header->archivesize + mpq_a->mpqpos;
+
+ if (mpq_a->header->offset != mpq_a->blocktable->filepos) {
+ libmpq_decrypt_blocktable(mpq_a, (unsigned char *)"(block table)");
+ }
+ for (mpq_b = mpq_a->blocktable; mpq_b < mpq_b_end; mpq_b++) {
+ if (mpq_b->filepos > archivesize || mpq_b->csize > archivesize) {
+ if ((mpq_a->flags & LIBMPQ_FLAG_PROTECTED) == 0) {
+ return LIBMPQ_EFILE_FORMAT;
+ }
+ }
+ mpq_b->filepos += mpq_a->mpqpos;
+ }
+
+ return LIBMPQ_TOOLS_SUCCESS;
}
int libmpq_file_read_block(mpq_archive *mpq_a, mpq_file *mpq_f, unsigned int blockpos, char *buffer, unsigned int blockbytes) {
- unsigned char *tempbuf = NULL; /* Buffer for reading compressed data from the file */
- unsigned int readpos; /* Reading position from the file */
- unsigned int toread = 0; /* Number of bytes to read */
- unsigned int blocknum; /* Block number (needed for decrypt) */
- unsigned int bytesread = 0; /* Total number of bytes read */
- unsigned int nblocks; /* Number of blocks to load */
- unsigned int i;
-
- /* Test parameters. Block position and block size must be block-aligned, block size nonzero */
- if ((blockpos & (mpq_a->blocksize - 1)) || blockbytes == 0) {
- return 0;
- }
-
- /* Check the end of file */
- if ((blockpos + blockbytes) > mpq_f->mpq_b->fsize) {
- blockbytes = mpq_f->mpq_b->fsize - blockpos;
- }
- blocknum = blockpos / mpq_a->blocksize;
- nblocks = blockbytes / mpq_a->blocksize;
- if (blockbytes % mpq_a->blocksize) {
- nblocks++;
- }
-
- /* If file has variable block positions, we have to load them */
- if ((mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) && mpq_f->blockposloaded == FALSE) {
- unsigned int nread;
-
- if (mpq_f->mpq_b->filepos != mpq_a->filepos) {
- #ifdef WIN32
- _lseeki64(mpq_a->fd, mpq_f->mpq_b->filepos, SEEK_SET);
- #else
- lseek64(mpq_a->fd, mpq_f->mpq_b->filepos, SEEK_SET);
-
- #endif
- }
-
- /* Read block positions from begin of file. */
- nread = (mpq_f->nblocks + 1) * sizeof(int);
- nread = _read(mpq_a->fd, mpq_f->blockpos, nread);
-
- /*
- * If the archive is protected some way, perform additional check
- * Sometimes, the file appears not to be encrypted, but it is.
- */
- /*if (mpq_f->blockpos[0] != nread) {
- mpq_f->mpq_b->flags |= LIBMPQ_FILE_ENCRYPTED;
- }*/
+ unsigned char *tempbuf = NULL; /* Buffer for reading compressed data from the file */
+ unsigned int readpos; /* Reading position from the file */
+ unsigned int toread = 0; /* Number of bytes to read */
+ unsigned int blocknum; /* Block number (needed for decrypt) */
+ unsigned int bytesread = 0; /* Total number of bytes read */
+ unsigned int nblocks; /* Number of blocks to load */
+ unsigned int i;
+
+ /* Test parameters. Block position and block size must be block-aligned, block size nonzero */
+ if ((blockpos & (mpq_a->blocksize - 1)) || blockbytes == 0) {
+ return 0;
+ }
+
+ /* Check the end of file */
+ if ((blockpos + blockbytes) > mpq_f->mpq_b->fsize) {
+ blockbytes = mpq_f->mpq_b->fsize - blockpos;
+ }
+ blocknum = blockpos / mpq_a->blocksize;
+ nblocks = blockbytes / mpq_a->blocksize;
+ if (blockbytes % mpq_a->blocksize) {
+ nblocks++;
+ }
+
+ /* If file has variable block positions, we have to load them */
+ if ((mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) && mpq_f->blockposloaded == FALSE) {
+ unsigned int nread;
+
+ if (mpq_f->mpq_b->filepos != mpq_a->filepos) {
+ #ifdef WIN32
+ _lseeki64(mpq_a->fd, mpq_f->mpq_b->filepos, SEEK_SET);
+ #else
+ lseek64(mpq_a->fd, mpq_f->mpq_b->filepos, SEEK_SET);
+
+ #endif
+ }
+
+ /* Read block positions from begin of file. */
+ nread = (mpq_f->nblocks + 1) * sizeof(int);
+ nread = _read(mpq_a->fd, mpq_f->blockpos, nread);
+
+ /*
+ * If the archive is protected some way, perform additional check
+ * Sometimes, the file appears not to be encrypted, but it is.
+ */
+ /*if (mpq_f->blockpos[0] != nread) {
+ mpq_f->mpq_b->flags |= LIBMPQ_FILE_ENCRYPTED;
+ }*/
if ((mpq_f->mpq_b->flags & LIBMPQ_FILE_HAS_METADATA) == 0) {
if (mpq_f->blockpos[0] != nread) {
- mpq_f->mpq_b->flags |= LIBMPQ_FILE_ENCRYPTED;
- }
+ mpq_f->mpq_b->flags |= LIBMPQ_FILE_ENCRYPTED;
+ }
}
- /* Decrypt loaded block positions if necessary */
- if (mpq_f->mpq_b->flags & LIBMPQ_FILE_ENCRYPTED) {
-
- /* If we don't know the file seed, try to find it. */
- if (mpq_f->seed == 0) {
- mpq_f->seed = libmpq_detect_fileseed(mpq_a, mpq_f->blockpos, nread);
- }
-
- /* If we don't know the file seed, sorry but we cannot extract the file. */
- if (mpq_f->seed == 0) {
- return 0;
- }
-
- /* Decrypt block positions */
- libmpq_decrypt_block(mpq_a, mpq_f->blockpos, nread, mpq_f->seed - 1);
-
- /*
- * Check if the block positions are correctly decrypted
- * I don't know why, but sometimes it will result invalid
- * block positions on some files.
- */
- if (mpq_f->blockpos[0] != nread) {
-
- /* Try once again to detect file seed and decrypt the blocks */
-
- #ifdef WIN32
- _lseeki64(mpq_a->fd, mpq_f->mpq_b->filepos, SEEK_SET);
- #else
- lseek64(mpq_a->fd, mpq_f->mpq_b->filepos, SEEK_SET);
- #endif
-
- nread = _read(mpq_a->fd, mpq_f->blockpos, (mpq_f->nblocks + 1) * sizeof(int));
- mpq_f->seed = libmpq_detect_fileseed(mpq_a, mpq_f->blockpos, nread);
- libmpq_decrypt_block(mpq_a, mpq_f->blockpos, nread, mpq_f->seed - 1);
-
- /* Check if the block positions are correctly decrypted. */
- if (mpq_f->blockpos[0] != nread) {
- return 0;
- }
- }
- }
-
- /* Update mpq_f's variables */
- mpq_f->blockposloaded = TRUE;
- mpq_a->filepos = mpq_f->mpq_b->filepos + nread;
- }
-
- /* Get file position and number of bytes to read */
- readpos = blockpos;
- toread = blockbytes;
-
- if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) {
- readpos = mpq_f->blockpos[blocknum];
- toread = mpq_f->blockpos[blocknum + nblocks] - readpos;
- }
-
- readpos += mpq_f->mpq_b->filepos;
-
- /* Get work buffer for store read data */
+ /* Decrypt loaded block positions if necessary */
+ if (mpq_f->mpq_b->flags & LIBMPQ_FILE_ENCRYPTED) {
+
+ /* If we don't know the file seed, try to find it. */
+ if (mpq_f->seed == 0) {
+ mpq_f->seed = libmpq_detect_fileseed(mpq_a, mpq_f->blockpos, nread);
+ }
+
+ /* If we don't know the file seed, sorry but we cannot extract the file. */
+ if (mpq_f->seed == 0) {
+ return 0;
+ }
+
+ /* Decrypt block positions */
+ libmpq_decrypt_block(mpq_a, mpq_f->blockpos, nread, mpq_f->seed - 1);
+
+ /*
+ * Check if the block positions are correctly decrypted
+ * I don't know why, but sometimes it will result invalid
+ * block positions on some files.
+ */
+ if (mpq_f->blockpos[0] != nread) {
+
+ /* Try once again to detect file seed and decrypt the blocks */
+
+ #ifdef WIN32
+ _lseeki64(mpq_a->fd, mpq_f->mpq_b->filepos, SEEK_SET);
+ #else
+ lseek64(mpq_a->fd, mpq_f->mpq_b->filepos, SEEK_SET);
+ #endif
+
+ nread = _read(mpq_a->fd, mpq_f->blockpos, (mpq_f->nblocks + 1) * sizeof(int));
+ mpq_f->seed = libmpq_detect_fileseed(mpq_a, mpq_f->blockpos, nread);
+ libmpq_decrypt_block(mpq_a, mpq_f->blockpos, nread, mpq_f->seed - 1);
+
+ /* Check if the block positions are correctly decrypted. */
+ if (mpq_f->blockpos[0] != nread) {
+ return 0;
+ }
+ }
+ }
+
+ /* Update mpq_f's variables */
+ mpq_f->blockposloaded = TRUE;
+ mpq_a->filepos = mpq_f->mpq_b->filepos + nread;
+ }
+
+ /* Get file position and number of bytes to read */
+ readpos = blockpos;
+ toread = blockbytes;
+
+ if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) {
+ readpos = mpq_f->blockpos[blocknum];
+ toread = mpq_f->blockpos[blocknum + nblocks] - readpos;
+ }
+
+ readpos += mpq_f->mpq_b->filepos;
+
+ /* Get work buffer for store read data */
if ((tempbuf = (unsigned char *)malloc(toread)) == NULL) {
/* Hmmm... We should add a better error handling here :) */
return 0;
}
- /* Set file pointer, if necessary. */
- if (mpq_a->filepos != readpos) {
-
- #ifdef WIN32
- mpq_a->filepos = _lseeki64(mpq_a->fd, readpos, SEEK_SET);
- #else
- mpq_a->filepos = lseek64(mpq_a->fd, readpos, SEEK_SET);
- #endif
-
- }
-
- /* 15018F87 - Read all requested blocks. */
- bytesread = _read(mpq_a->fd, tempbuf, toread);
- mpq_a->filepos = readpos + bytesread;
-
- /* Block processing part. */
- unsigned int blockstart = 0; /* Index of block start in work buffer. */
- unsigned int blocksize = min(blockbytes, mpq_a->blocksize);
- unsigned int index = blocknum; /* Current block index. */
- bytesread = 0; /* Clear read byte counter */
-
- /* Walk through all blocks. */
- for (i = 0; i < nblocks; i++, index++) {
- int outlength = mpq_a->blocksize;
-
- /* Get current block length */
- if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) {
- blocksize = mpq_f->blockpos[index + 1] - mpq_f->blockpos[index];
- }
-
- /* If block is encrypted, we have to decrypt it. */
- if (mpq_f->mpq_b->flags & LIBMPQ_FILE_ENCRYPTED) {
- if (mpq_f->seed == 0) {
- return 0;
- }
- libmpq_decrypt_block(mpq_a, (unsigned int *)&tempbuf[blockstart], blocksize, mpq_f->seed + index);
- }
-
- /*
- * If the block is really compressed, recompress it.
- * WARNING: Some block may not be compressed, it can
- * only be determined by comparing uncompressed and
- * compressed size!
- */
- if (blocksize < blockbytes) {
-
- /* Is the file compressed with PKWARE Data Compression Library? */
- if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESS_PKWARE) {
- libmpq_pkzip_decompress(buffer, &outlength, (char *)&tempbuf[blockstart], blocksize);
- }
-
- /*
- * Is it a file compressed by Blizzard's multiple compression ?
- * Note that Storm.dll v 1.0.9 distributed with Warcraft III
- * passes the full path name of the opened archive as the new
- * last parameter.
- */
- if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESS_MULTI) {
- libmpq_multi_decompress(buffer, &outlength, (char *)&tempbuf[blockstart], blocksize);
- }
- bytesread += outlength;
- buffer += outlength;
- } else {
- memcpy(buffer, tempbuf, blocksize);
- bytesread += blocksize;
- buffer += blocksize;
- }
- blockstart += blocksize;
- }
-
- /* Delete input buffer, if necessary. */
+ /* Set file pointer, if necessary. */
+ if (mpq_a->filepos != readpos) {
+
+ #ifdef WIN32
+ mpq_a->filepos = _lseeki64(mpq_a->fd, readpos, SEEK_SET);
+ #else
+ mpq_a->filepos = lseek64(mpq_a->fd, readpos, SEEK_SET);
+ #endif
+
+ }
+
+ /* 15018F87 - Read all requested blocks. */
+ bytesread = _read(mpq_a->fd, tempbuf, toread);
+ mpq_a->filepos = readpos + bytesread;
+
+ /* Block processing part. */
+ unsigned int blockstart = 0; /* Index of block start in work buffer. */
+ unsigned int blocksize = min(blockbytes, mpq_a->blocksize);
+ unsigned int index = blocknum; /* Current block index. */
+ bytesread = 0; /* Clear read byte counter */
+
+ /* Walk through all blocks. */
+ for (i = 0; i < nblocks; i++, index++) {
+ int outlength = mpq_a->blocksize;
+
+ /* Get current block length */
+ if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) {
+ blocksize = mpq_f->blockpos[index + 1] - mpq_f->blockpos[index];
+ }
+
+ /* If block is encrypted, we have to decrypt it. */
+ if (mpq_f->mpq_b->flags & LIBMPQ_FILE_ENCRYPTED) {
+ if (mpq_f->seed == 0) {
+ return 0;
+ }
+ libmpq_decrypt_block(mpq_a, (unsigned int *)&tempbuf[blockstart], blocksize, mpq_f->seed + index);
+ }
+
+ /*
+ * If the block is really compressed, recompress it.
+ * WARNING: Some block may not be compressed, it can
+ * only be determined by comparing uncompressed and
+ * compressed size!
+ */
+ if (blocksize < blockbytes) {
+
+ /* Is the file compressed with PKWARE Data Compression Library? */
+ if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESS_PKWARE) {
+ libmpq_pkzip_decompress(buffer, &outlength, (char *)&tempbuf[blockstart], blocksize);
+ }
+
+ /*
+ * Is it a file compressed by Blizzard's multiple compression ?
+ * Note that Storm.dll v 1.0.9 distributed with Warcraft III
+ * passes the full path name of the opened archive as the new
+ * last parameter.
+ */
+ if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESS_MULTI) {
+ libmpq_multi_decompress(buffer, &outlength, (char *)&tempbuf[blockstart], blocksize);
+ }
+ bytesread += outlength;
+ buffer += outlength;
+ } else {
+ memcpy(buffer, tempbuf, blocksize);
+ bytesread += blocksize;
+ buffer += blocksize;
+ }
+ blockstart += blocksize;
+ }
+
+ /* Delete input buffer, if necessary. */
free(tempbuf);
return bytesread;
}
int libmpq_file_read_file(mpq_archive *mpq_a, mpq_file *mpq_f, unsigned int filepos, char *buffer, unsigned int toread) {
- unsigned int bytesread = 0; /* Number of bytes read from the file */
- unsigned int blockpos; /* Position in the file aligned to the whole blocks */
- unsigned int loaded = 0;
-
- /* File position is greater or equal to file size? */
- if (filepos >= mpq_f->mpq_b->fsize) {
- return 0;
- }
-
- /* If to few bytes in the file remaining, cut them */
- if ((mpq_f->mpq_b->fsize - filepos) < toread) {
- toread = (mpq_f->mpq_b->fsize - filepos);
- }
-
- /* Block position in the file */
- blockpos = filepos & ~(mpq_a->blocksize - 1);
-
- /*
- * Load the first block, if noncomplete. It may be loaded in the cache buffer.
- * We have to check if this block is loaded. If not, load it.
- */
- if ((filepos % mpq_a->blocksize) != 0) {
- /* Number of bytes remaining in the buffer */
- unsigned int tocopy;
- unsigned int loaded = mpq_a->blocksize;
-
- /* Check if data are loaded in the cache */
- if (mpq_f->accessed == FALSE || blockpos != mpq_a->blockpos) {
-
- /* Load one MPQ block into archive buffer */
- loaded = libmpq_file_read_block(mpq_a, mpq_f, blockpos, (char *)mpq_a->blockbuf, mpq_a->blocksize);
- if (loaded == 0) {
- return 0;
- }
-
- /* Save lastly accessed file and block position for later use */
- mpq_f->accessed = TRUE;
- mpq_a->blockpos = blockpos;
- mpq_a->bufpos = filepos % mpq_a->blocksize;
- }
- tocopy = loaded - mpq_a->bufpos;
- if (tocopy > toread) {
- tocopy = toread;
- }
-
- /* Copy data from block buffer into target buffer */
- memcpy(buffer, mpq_a->blockbuf + mpq_a->bufpos, tocopy);
-
- /* Update pointers */
- toread -= tocopy;
- bytesread += tocopy;
- buffer += tocopy;
- blockpos += mpq_a->blocksize;
- mpq_a->bufpos += tocopy;
-
- /* If all, return. */
- if (toread == 0) {
- return bytesread;
- }
- }
-
- /* Load the whole ("middle") blocks only if there are more or equal one block */
- if (toread > mpq_a->blocksize) {
- unsigned int blockbytes = toread & ~(mpq_a->blocksize - 1);
- loaded = libmpq_file_read_block(mpq_a, mpq_f, blockpos, buffer, blockbytes);
- if (loaded == 0) {
- return 0;
- }
-
- /* Update pointers */
- toread -= loaded;
- bytesread += loaded;
- buffer += loaded;
- blockpos += loaded;
-
- /* If all, return. */
- if (toread == 0) {
- return bytesread;
- }
- }
-
- /* Load the terminating block */
- if (toread > 0) {
- unsigned int tocopy = mpq_a->blocksize;
-
- /* Check if data are loaded in the cache */
- if (mpq_f->accessed == FALSE || blockpos != mpq_a->blockpos) {
-
- /* Load one MPQ block into archive buffer */
- tocopy = libmpq_file_read_block(mpq_a, mpq_f, blockpos, (char *)mpq_a->blockbuf, mpq_a->blocksize);
- if (tocopy == 0) {
- return 0;
- }
-
- /* Save lastly accessed file and block position for later use */
- mpq_f->accessed = TRUE;
- mpq_a->blockpos = blockpos;
- }
- mpq_a->bufpos = 0;
-
- /* Check number of bytes read */
- if (tocopy > toread) {
- tocopy = toread;
- }
-
- memcpy(buffer, mpq_a->blockbuf, tocopy);
- bytesread += tocopy;
- mpq_a->bufpos = tocopy;
- }
-
- /* Return what we've read */
- return bytesread;
+ unsigned int bytesread = 0; /* Number of bytes read from the file */
+ unsigned int blockpos; /* Position in the file aligned to the whole blocks */
+ unsigned int loaded = 0;
+
+ /* File position is greater or equal to file size? */
+ if (filepos >= mpq_f->mpq_b->fsize) {
+ return 0;
+ }
+
+ /* If to few bytes in the file remaining, cut them */
+ if ((mpq_f->mpq_b->fsize - filepos) < toread) {
+ toread = (mpq_f->mpq_b->fsize - filepos);
+ }
+
+ /* Block position in the file */
+ blockpos = filepos & ~(mpq_a->blocksize - 1);
+
+ /*
+ * Load the first block, if noncomplete. It may be loaded in the cache buffer.
+ * We have to check if this block is loaded. If not, load it.
+ */
+ if ((filepos % mpq_a->blocksize) != 0) {
+ /* Number of bytes remaining in the buffer */
+ unsigned int tocopy;
+ unsigned int loaded = mpq_a->blocksize;
+
+ /* Check if data are loaded in the cache */
+ if (mpq_f->accessed == FALSE || blockpos != mpq_a->blockpos) {
+
+ /* Load one MPQ block into archive buffer */
+ loaded = libmpq_file_read_block(mpq_a, mpq_f, blockpos, (char *)mpq_a->blockbuf, mpq_a->blocksize);
+ if (loaded == 0) {
+ return 0;
+ }
+
+ /* Save lastly accessed file and block position for later use */
+ mpq_f->accessed = TRUE;
+ mpq_a->blockpos = blockpos;
+ mpq_a->bufpos = filepos % mpq_a->blocksize;
+ }
+ tocopy = loaded - mpq_a->bufpos;
+ if (tocopy > toread) {
+ tocopy = toread;
+ }
+
+ /* Copy data from block buffer into target buffer */
+ memcpy(buffer, mpq_a->blockbuf + mpq_a->bufpos, tocopy);
+
+ /* Update pointers */
+ toread -= tocopy;
+ bytesread += tocopy;
+ buffer += tocopy;
+ blockpos += mpq_a->blocksize;
+ mpq_a->bufpos += tocopy;
+
+ /* If all, return. */
+ if (toread == 0) {
+ return bytesread;
+ }
+ }
+
+ /* Load the whole ("middle") blocks only if there are more or equal one block */
+ if (toread > mpq_a->blocksize) {
+ unsigned int blockbytes = toread & ~(mpq_a->blocksize - 1);
+ loaded = libmpq_file_read_block(mpq_a, mpq_f, blockpos, buffer, blockbytes);
+ if (loaded == 0) {
+ return 0;
+ }
+
+ /* Update pointers */
+ toread -= loaded;
+ bytesread += loaded;
+ buffer += loaded;
+ blockpos += loaded;
+
+ /* If all, return. */
+ if (toread == 0) {
+ return bytesread;
+ }
+ }
+
+ /* Load the terminating block */
+ if (toread > 0) {
+ unsigned int tocopy = mpq_a->blocksize;
+
+ /* Check if data are loaded in the cache */
+ if (mpq_f->accessed == FALSE || blockpos != mpq_a->blockpos) {
+
+ /* Load one MPQ block into archive buffer */
+ tocopy = libmpq_file_read_block(mpq_a, mpq_f, blockpos, (char *)mpq_a->blockbuf, mpq_a->blocksize);
+ if (tocopy == 0) {
+ return 0;
+ }
+
+ /* Save lastly accessed file and block position for later use */
+ mpq_f->accessed = TRUE;
+ mpq_a->blockpos = blockpos;
+ }
+ mpq_a->bufpos = 0;
+
+ /* Check number of bytes read */
+ if (tocopy > toread) {
+ tocopy = toread;
+ }
+
+ memcpy(buffer, mpq_a->blockbuf, tocopy);
+ bytesread += tocopy;
+ mpq_a->bufpos = tocopy;
+ }
+
+ /* Return what we've read */
+ return bytesread;
}