00001
00002
00003
00004
00005
00006
00007
00008 #include <stdio.h>
00009 #include <stdlib.h>
00010 #include <string.h>
00011 #include "zlib.h"
00012 #include "unzip.h"
00013
00014 #define READ_8(adr) ((unsigned char)*(adr))
00015 #define READ_16(adr) ( READ_8(adr) | (READ_8(adr+1) << 8) )
00016 #define READ_32(adr) ( READ_16(adr) | (READ_16((adr)+2) << 16) )
00017
00018 #define WRITE_8(buff, n) do { \
00019 *((unsigned char*)(buff)) = (unsigned char) ((n) & 0xff); \
00020 } while(0)
00021 #define WRITE_16(buff, n) do { \
00022 WRITE_8((unsigned char*)(buff), n); \
00023 WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \
00024 } while(0)
00025 #define WRITE_32(buff, n) do { \
00026 WRITE_16((unsigned char*)(buff), (n) & 0xffff); \
00027 WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \
00028 } while(0)
00029
00030 extern int ZEXPORT unzRepair(file, fileOut, fileOutTmp, nRecovered, bytesRecovered)
00031 const char* file;
00032 const char* fileOut;
00033 const char* fileOutTmp;
00034 uLong* nRecovered;
00035 uLong* bytesRecovered;
00036 {
00037 int err = Z_OK;
00038 FILE* fpZip = fopen(file, "rb");
00039 FILE* fpOut = fopen(fileOut, "wb");
00040 FILE* fpOutCD = fopen(fileOutTmp, "wb");
00041 if (fpZip != NULL && fpOut != NULL) {
00042 int entries = 0;
00043 uLong totalBytes = 0;
00044 char header[30];
00045 char filename[256];
00046 char extra[1024];
00047 int offset = 0;
00048 int offsetCD = 0;
00049 while ( fread(header, 1, 30, fpZip) == 30 ) {
00050 int currentOffset = offset;
00051
00052
00053 if (READ_32(header) == 0x04034b50) {
00054 unsigned int version = READ_16(header + 4);
00055 unsigned int gpflag = READ_16(header + 6);
00056 unsigned int method = READ_16(header + 8);
00057 unsigned int filetime = READ_16(header + 10);
00058 unsigned int filedate = READ_16(header + 12);
00059 unsigned int crc = READ_32(header + 14);
00060 unsigned int cpsize = READ_32(header + 18);
00061 unsigned int uncpsize = READ_32(header + 22);
00062 unsigned int fnsize = READ_16(header + 26);
00063 unsigned int extsize = READ_16(header + 28);
00064 filename[0] = extra[0] = '\0';
00065
00066
00067 if (fwrite(header, 1, 30, fpOut) == 30) {
00068 offset += 30;
00069 } else {
00070 err = Z_ERRNO;
00071 break;
00072 }
00073
00074
00075 if (fnsize > 0) {
00076 if (fread(filename, 1, fnsize, fpZip) == fnsize) {
00077 if (fwrite(filename, 1, fnsize, fpOut) == fnsize) {
00078 offset += fnsize;
00079 } else {
00080 err = Z_ERRNO;
00081 break;
00082 }
00083 } else {
00084 err = Z_ERRNO;
00085 break;
00086 }
00087 } else {
00088 err = Z_STREAM_ERROR;
00089 break;
00090 }
00091
00092
00093 if (extsize > 0) {
00094 if (fread(extra, 1, extsize, fpZip) == extsize) {
00095 if (fwrite(extra, 1, extsize, fpOut) == extsize) {
00096 offset += extsize;
00097 } else {
00098 err = Z_ERRNO;
00099 break;
00100 }
00101 } else {
00102 err = Z_ERRNO;
00103 break;
00104 }
00105 }
00106
00107
00108 {
00109 int dataSize = cpsize;
00110 if (dataSize == 0) {
00111 dataSize = uncpsize;
00112 }
00113 if (dataSize > 0) {
00114 char* data = malloc(dataSize);
00115 if (data != NULL) {
00116 if ((int)fread(data, 1, dataSize, fpZip) == dataSize) {
00117 if ((int)fwrite(data, 1, dataSize, fpOut) == dataSize) {
00118 offset += dataSize;
00119 totalBytes += dataSize;
00120 } else {
00121 err = Z_ERRNO;
00122 }
00123 } else {
00124 err = Z_ERRNO;
00125 }
00126 free(data);
00127 if (err != Z_OK) {
00128 break;
00129 }
00130 } else {
00131 err = Z_MEM_ERROR;
00132 break;
00133 }
00134 }
00135 }
00136
00137
00138 {
00139 char header[46];
00140 char* comment = "";
00141 int comsize = (int) strlen(comment);
00142 WRITE_32(header, 0x02014b50);
00143 WRITE_16(header + 4, version);
00144 WRITE_16(header + 6, version);
00145 WRITE_16(header + 8, gpflag);
00146 WRITE_16(header + 10, method);
00147 WRITE_16(header + 12, filetime);
00148 WRITE_16(header + 14, filedate);
00149 WRITE_32(header + 16, crc);
00150 WRITE_32(header + 20, cpsize);
00151 WRITE_32(header + 24, uncpsize);
00152 WRITE_16(header + 28, fnsize);
00153 WRITE_16(header + 30, extsize);
00154 WRITE_16(header + 32, comsize);
00155 WRITE_16(header + 34, 0);
00156 WRITE_16(header + 36, 0);
00157 WRITE_32(header + 38, 0);
00158 WRITE_32(header + 42, currentOffset);
00159
00160 if (fwrite(header, 1, 46, fpOutCD) == 46) {
00161 offsetCD += 46;
00162
00163
00164 if (fnsize > 0) {
00165 if (fwrite(filename, 1, fnsize, fpOutCD) == fnsize) {
00166 offsetCD += fnsize;
00167 } else {
00168 err = Z_ERRNO;
00169 break;
00170 }
00171 } else {
00172 err = Z_STREAM_ERROR;
00173 break;
00174 }
00175
00176
00177 if (extsize > 0) {
00178 if (fwrite(extra, 1, extsize, fpOutCD) == extsize) {
00179 offsetCD += extsize;
00180 } else {
00181 err = Z_ERRNO;
00182 break;
00183 }
00184 }
00185
00186
00187 if (comsize > 0) {
00188 if ((int)fwrite(comment, 1, comsize, fpOutCD) == comsize) {
00189 offsetCD += comsize;
00190 } else {
00191 err = Z_ERRNO;
00192 break;
00193 }
00194 }
00195
00196
00197 } else {
00198 err = Z_ERRNO;
00199 break;
00200 }
00201 }
00202
00203
00204 entries++;
00205
00206 } else {
00207 break;
00208 }
00209 }
00210
00211
00212 {
00213 int entriesZip = entries;
00214 char header[22];
00215 char* comment = "";
00216 int comsize = (int) strlen(comment);
00217 if (entriesZip > 0xffff) {
00218 entriesZip = 0xffff;
00219 }
00220 WRITE_32(header, 0x06054b50);
00221 WRITE_16(header + 4, 0);
00222 WRITE_16(header + 6, 0);
00223 WRITE_16(header + 8, entriesZip);
00224 WRITE_16(header + 10, entriesZip);
00225 WRITE_32(header + 12, offsetCD);
00226 WRITE_32(header + 16, offset);
00227 WRITE_16(header + 20, comsize);
00228
00229
00230 if (fwrite(header, 1, 22, fpOutCD) == 22) {
00231
00232
00233 if (comsize > 0) {
00234 if ((int)fwrite(comment, 1, comsize, fpOutCD) != comsize) {
00235 err = Z_ERRNO;
00236 }
00237 }
00238
00239 } else {
00240 err = Z_ERRNO;
00241 }
00242 }
00243
00244
00245 fclose(fpOutCD);
00246 if (err == Z_OK) {
00247 fpOutCD = fopen(fileOutTmp, "rb");
00248 if (fpOutCD != NULL) {
00249 int nRead;
00250 char buffer[8192];
00251 while ( (nRead = (int)fread(buffer, 1, sizeof(buffer), fpOutCD)) > 0) {
00252 if ((int)fwrite(buffer, 1, nRead, fpOut) != nRead) {
00253 err = Z_ERRNO;
00254 break;
00255 }
00256 }
00257 fclose(fpOutCD);
00258 }
00259 }
00260
00261
00262 fclose(fpZip);
00263 fclose(fpOut);
00264
00265
00266 (void)remove(fileOutTmp);
00267
00268
00269 if (err == Z_OK) {
00270 if (nRecovered != NULL) {
00271 *nRecovered = entries;
00272 }
00273 if (bytesRecovered != NULL) {
00274 *bytesRecovered = totalBytes;
00275 }
00276 }
00277 } else {
00278 err = Z_STREAM_ERROR;
00279 }
00280 return err;
00281 }