File indexing completed on 2024-12-01 13:11:46
0001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ 0002 /* FemtoZip - superlightweight C++ module to create a compressed ZIP archive 0003 Copyright (C) 2005-2006 Ariya Hidayat <ariya@kde.org> 0004 0005 Redistribution and use in source and binary forms, with or without 0006 modification, are permitted provided that the following conditions 0007 are met: 0008 * Redistributions of source code must retain the above copyright notice, 0009 this list of conditions and the following disclaimer. 0010 * Redistributions in binary form must reproduce the above copyright notice, 0011 this list of conditions and the following disclaimer in the documentation 0012 and/or other materials provided with the distribution. 0013 * Neither the name of the authors nor the names of its contributors may be 0014 used to endorse or promote products derived from this software without 0015 specific prior written permission. 0016 0017 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 0018 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 0019 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 0020 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 0021 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 0022 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 0023 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 0024 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 0025 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 0026 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 0027 THE POSSIBILITY OF SUCH DAMAGE. 0028 */ 0029 0030 #ifndef USE_GSF_OUTPUT 0031 0032 #include "FemtoZip.hxx" 0033 0034 #include <stdlib.h> // malloc, free, realoc 0035 #include <stdio.h> // printf (debug mode) 0036 #include <string.h> // memcpy, memset, strlen 0037 #include <time.h> // time, localtime, time_t 0038 0039 // uses small (16 entries) CRC table instead of the large (256 entries) one 0040 // very useful if memory requirement is critical 0041 #define FEMTOZIP_SMALLTABLE 0042 0043 #ifdef DEBUG 0044 #define FEMTOZIP_DEBUG 0045 #endif 0046 0047 #ifdef FEMTOZIP_DEBUG 0048 #define FZ_DEBUG(M) printf M 0049 #else 0050 #define FZ_DEBUG(M) 0051 #endif 0052 0053 // see http://www.w3.org/TR/PNG-CRCAppendix.html on info regarding CRC-32 0054 0055 #ifdef FEMTOZIP_SMALLTABLE 0056 static const unsigned long crc_table[16] = 0057 { 0058 0x00000000L, 0x1db71064L, 0x3b6e20c8L, 0x26d930acL, 0059 0x76dc4190L, 0x6b6b51f4L, 0x4db26158L, 0x5005713cL, 0060 0xedb88320L, 0xf00f9344L, 0xd6d6a3e8L, 0xcb61b38cL, 0061 0x9b64c2b0L, 0x86d3d2d4L, 0xa00ae278L, 0xbdbdf21cL 0062 }; 0063 #else 0064 static const unsigned long crc_table[256] = 0065 { 0066 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0067 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0068 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0069 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, 0070 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 0071 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0072 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0073 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, 0074 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0075 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, 0076 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0077 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0078 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0079 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, 0080 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 0081 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0082 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0083 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, 0084 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0085 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, 0086 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0087 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0088 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0089 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, 0090 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0091 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0092 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0093 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, 0094 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0095 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, 0096 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0097 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0098 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0099 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, 0100 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 0101 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0102 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0103 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, 0104 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0105 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, 0106 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0107 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0108 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0109 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L, 0110 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 0111 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0112 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0113 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, 0114 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0115 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, 0116 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0117 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0118 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0119 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, 0120 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0121 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0122 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0123 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, 0124 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0125 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, 0126 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0127 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0128 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0129 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL 0130 }; 0131 #endif 0132 0133 0134 // entry record is stored as linked list 0135 0136 class FemtoZipEntry 0137 { 0138 public: 0139 char *name; 0140 int compressionLevel; 0141 unsigned long uncompressedSize; 0142 unsigned long compressedSize; 0143 unsigned long headerPos; 0144 unsigned short timeStamp; 0145 unsigned short dateStamp; 0146 unsigned long crc32; 0147 FemtoZipEntry *next; 0148 0149 FemtoZipEntry(const char *n, int cl): 0150 name(0), compressionLevel(cl), uncompressedSize(0), 0151 compressedSize(0), headerPos(0), timeStamp(0), dateStamp(0), 0152 crc32(0xffffffffL), // pre-condition, all bits are '1' 0153 next(0) 0154 { 0155 name = strdup(n); 0156 } 0157 0158 ~FemtoZipEntry() 0159 { 0160 free(name); 0161 } 0162 private: 0163 FemtoZipEntry(FemtoZipEntry const &); 0164 FemtoZipEntry &operator=(FemtoZipEntry const &); 0165 }; 0166 0167 class FemtoZipPrivate 0168 { 0169 public: 0170 int errorCode; 0171 FILE *fhandle; 0172 FemtoZipEntry *entryList; 0173 FemtoZipEntry *currentEntry; 0174 unsigned char buffer[46]; 0175 0176 FemtoZipPrivate(): errorCode(FemtoZip::NoError), fhandle(0), 0177 entryList(0), currentEntry(0) 0178 { 0179 } 0180 0181 void createZip(const char *zipfile) 0182 { 0183 FZ_DEBUG(("Creating ZIP: %s\n", zipfile)); 0184 0185 fhandle = fopen(zipfile, "wb"); 0186 if (!fhandle) 0187 errorCode = FemtoZip::ErrorCreateZip; 0188 } 0189 0190 unsigned long updateCRC(unsigned long crc, const void *data, unsigned long len) 0191 { 0192 const unsigned char *buf = (const unsigned char *) data; 0193 0194 for (unsigned long i = 0; i < len; i++) 0195 #ifdef FEMTOZIP_SMALLTABLE 0196 { 0197 crc ^= buf[i]; 0198 crc = crc_table[crc & 0x0f] ^ (crc >> 4); 0199 crc = crc_table[crc & 0x0f] ^ (crc >> 4); 0200 } 0201 #else 0202 crc = crc_table[(crc ^ buf[i]) & 0xff] ^ (crc >> 8); 0203 #endif 0204 return crc; 0205 } 0206 0207 // write central directory, by walking the linked list 0208 // also: free the entry one by one 0209 void closeZip() 0210 { 0211 // last entry not closed 0212 if (currentEntry) 0213 { 0214 FZ_DEBUG(("automatically closing last entry %s", currentEntry->name)); 0215 closeEntry(); 0216 } 0217 if (!fhandle) 0218 return; 0219 unsigned long centralDirPos = (unsigned long) ftell(fhandle); 0220 unsigned short entryCount = 0; 0221 FemtoZipEntry *entry = entryList; 0222 while (entry && (errorCode == FemtoZip::NoError)) 0223 { 0224 FZ_DEBUG(("central directory: entry for %s\n", entry->name)); 0225 size_t namelen = strlen(entry->name); 0226 0227 /* 0228 central directory record: total size >= 46 bytes 0229 0230 offset size description 0231 --------------------------------------- 0232 0 4 signature: 'P','K',1,2 0233 4 2 version made by 0234 6 2 version needed to extract 0235 8 2 general purpose bit flag 0236 10 2 compression method 0=store 8=deflate 0237 12 2 last mod file time 0238 14 2 last mod file date 0239 16 4 crc-32 0240 20 4 compressed size 0241 24 4 uncompressed size 0242 28 2 file name length 0243 30 2 extra field length 0244 32 2 file comment length 0245 34 2 disk number start 0246 36 2 internal file attributes 0247 38 4 external file attributes 0248 42 4 relative offset of local header 0249 */ 0250 0251 buffer[0] = 0x50; 0252 buffer[1] = 0x4b; 0253 buffer[2] = 0x01; 0254 buffer[3] = 0x02; 0255 buffer[4] = 0x14; 0256 buffer[5] = 0; 0257 buffer[6] = 0x0a; 0258 buffer[7] = 0; 0259 buffer[8] = 0; 0260 buffer[9] = 0; 0261 buffer[10] = (entry->compressionLevel==0) ? 0 : 8; 0262 buffer[11] = 0x0; 0263 buffer[12] = (unsigned char)(entry->timeStamp & 0xff); 0264 buffer[13] = (unsigned char)((entry->timeStamp>>8) & 0xff); 0265 buffer[14] = (unsigned char)(entry->dateStamp & 0xff); 0266 buffer[15] = (unsigned char)((entry->dateStamp>>8) & 0xff); 0267 buffer[16] = entry->crc32 & 0xff; 0268 buffer[17] = (entry->crc32>>8) & 0xff; 0269 buffer[18] = (entry->crc32>>16) & 0xff; 0270 buffer[19] = (entry->crc32>>24) & 0xff; 0271 buffer[20] = entry->compressedSize & 0xff; 0272 buffer[21] = (entry->compressedSize>>8) & 0xff; 0273 buffer[22] = (entry->compressedSize>>16) & 0xff; 0274 buffer[23] = (entry->compressedSize>>24) & 0xff; 0275 buffer[24] = entry->uncompressedSize & 0xff; 0276 buffer[25] = (entry->uncompressedSize>>8) & 0xff; 0277 buffer[26] = (entry->uncompressedSize>>16) & 0xff; 0278 buffer[27] = (entry->uncompressedSize>>24) & 0xff; 0279 buffer[28] = namelen & 0xff; 0280 buffer[29] = (namelen>>8) & 0xff; 0281 buffer[30] = 0; 0282 buffer[31] = 0; 0283 buffer[32] = 0; 0284 buffer[33] = 0; 0285 buffer[34] = 0; 0286 buffer[35] = 0; 0287 buffer[36] = 0; 0288 buffer[37] = 0; 0289 buffer[38] = 0; 0290 buffer[39] = 0; 0291 buffer[40] = 0; 0292 buffer[41] = 0; 0293 buffer[42] = entry->headerPos & 0xff; 0294 buffer[43] = (entry->headerPos>>8) & 0xff; 0295 buffer[44] = (entry->headerPos>>16) & 0xff; 0296 buffer[45] = (entry->headerPos>>24) & 0xff; 0297 0298 if (fwrite(buffer, 1, 46, fhandle) != 46) 0299 errorCode = FemtoZip::ErrorWriteData; 0300 else 0301 { 0302 if (fwrite(entry->name, 1, namelen, fhandle) != namelen) 0303 errorCode = FemtoZip::ErrorWriteData; 0304 } 0305 0306 FemtoZipEntry *next_entry = entry->next; 0307 delete entry; 0308 entry = next_entry; 0309 entryCount++; 0310 } 0311 unsigned long centralDirSize = (unsigned long)ftell(fhandle) - centralDirPos; 0312 0313 /* 0314 end of central directory record: total size 22 bytes 0315 0316 offset size description 0317 --------------------------------------- 0318 0 4 signature: 'P','K',5,6 0319 4 2 number of this disk 0320 6 2 number of this disk with the start of the central directory 0321 8 2 total number of entries in the central directory on this disk 0322 10 2 total number of entries in the central directory 0323 12 4 size of the central directory 0324 16 4 offset of start of central directory with respect to the starting disk number 0325 20 2 comment length 0326 22 var. comment field 0327 */ 0328 0329 buffer[0] = 'P'; 0330 buffer[1] = 'K'; 0331 buffer[2] = 5; 0332 buffer[3] = 6; 0333 buffer[4] = 0x00; 0334 buffer[5] = 0x00; 0335 buffer[6] = 0x00; 0336 buffer[7] = 0x00; 0337 buffer[8] = (unsigned char)(entryCount & 0xff); 0338 buffer[9] = (unsigned char)((entryCount >> 8) & 0xff); 0339 buffer[10] = (unsigned char)(entryCount & 0xff); 0340 buffer[11] = (unsigned char)((entryCount >> 8) & 0xff); 0341 buffer[12] = centralDirSize & 0xff; 0342 buffer[13] = (centralDirSize>>8) & 0xff; 0343 buffer[14] = (centralDirSize>>16) & 0xff; 0344 buffer[15] = (centralDirSize>>24) & 0xff; 0345 buffer[16] = centralDirPos & 0xff; 0346 buffer[17] = (centralDirPos>>8) & 0xff; 0347 buffer[18] = (centralDirPos>>16) & 0xff; 0348 buffer[19] = (centralDirPos>>24) & 0xff; 0349 buffer[20] = 0x00; 0350 buffer[21] = 0x00; 0351 if (fwrite(buffer, 1, 22, fhandle) != 22) 0352 errorCode = FemtoZip::ErrorWriteData; 0353 0354 // that's all, we're done ! 0355 fclose(fhandle); 0356 fhandle = 0; 0357 } 0358 0359 void writeLocalHeader(FemtoZipEntry *entry) 0360 { 0361 if (!entry) return; 0362 0363 size_t namelen = strlen(entry->name); 0364 0365 /* 0366 local file header: total size 22 bytes 0367 0368 offset size description 0369 --------------------------------------- 0370 0 4 signature: 'P','K',3,4 0371 4 2 version needed to extract 0372 6 2 general purpose bit flag 0373 8 2 compression method 0=store 8=deflate 0374 10 2 last mod file time 0375 12 2 last mod file date 0376 14 4 crc-32 0377 18 4 compressed size 0378 22 4 uncompressed size 0379 26 2 file name length 0380 28 2 extra field length 0381 30 var. file name (NOT null terminated) 0382 */ 0383 0384 buffer[0] = 'P'; 0385 buffer[1] = 'K'; 0386 buffer[2] = 3; 0387 buffer[3] = 4; 0388 buffer[4] = 0x0a; 0389 buffer[5] = 0; 0390 buffer[6] = 0; 0391 buffer[7] = 0; 0392 buffer[8] = (currentEntry->compressionLevel==0) ? 0 : 8; 0393 buffer[9] = 0; 0394 buffer[10] = (unsigned char)(currentEntry->timeStamp & 0xff); 0395 buffer[11] = (unsigned char)((currentEntry->timeStamp>>8) & 0xff); 0396 buffer[12] = (unsigned char)(currentEntry->dateStamp & 0xff); 0397 buffer[13] = (unsigned char)((currentEntry->dateStamp>>8) & 0xff); 0398 buffer[14] = currentEntry->crc32 & 0xff; 0399 buffer[15] = (currentEntry->crc32>>8) & 0xff; 0400 buffer[16] = (currentEntry->crc32>>16) & 0xff; 0401 buffer[17] = (currentEntry->crc32>>24) & 0xff; 0402 buffer[18] = currentEntry->compressedSize & 0xff; 0403 buffer[19] = (currentEntry->compressedSize>>8) & 0xff; 0404 buffer[20] = (currentEntry->compressedSize>>16) & 0xff; 0405 buffer[21] = (currentEntry->compressedSize>>24) & 0xff; 0406 buffer[22] = currentEntry->uncompressedSize & 0xff; 0407 buffer[23] = (currentEntry->uncompressedSize>>8) & 0xff; 0408 buffer[24] = (currentEntry->uncompressedSize>>16) & 0xff; 0409 buffer[25] = (currentEntry->uncompressedSize>>24) & 0xff; 0410 buffer[26] = namelen & 0xff; 0411 buffer[27] = (namelen>>8) & 0xff; 0412 buffer[28] = 0; 0413 buffer[29] = 0; 0414 0415 if (fwrite(buffer, 1, 30, fhandle) != 30) 0416 errorCode = FemtoZip::ErrorWriteData; 0417 else 0418 { 0419 if (fwrite(entry->name, 1, namelen, fhandle) != namelen) 0420 errorCode = FemtoZip::ErrorWriteData; 0421 } 0422 } 0423 0424 0425 void createEntry(const char *name, int compressionLevel) 0426 { 0427 if (errorCode != FemtoZip::NoError) 0428 return; 0429 0430 if (fhandle == 0) 0431 { 0432 FZ_DEBUG(("createEntry error: file already closed")); 0433 return; 0434 } 0435 0436 // somebody forget to close previous entry 0437 if (currentEntry != 0) 0438 { 0439 FZ_DEBUG(("createEntry warning: previous entry is not manually closed")); 0440 closeEntry(); 0441 } 0442 0443 // sanity check 0444 if (compressionLevel < 0) 0445 compressionLevel = 0; 0446 0447 // create new entry and append it to the linked list 0448 currentEntry = new FemtoZipEntry(name, compressionLevel); 0449 if (entryList != 0) 0450 { 0451 FemtoZipEntry *e = entryList; 0452 while (e->next) 0453 e = e->next; 0454 e->next = currentEntry; 0455 } 0456 else 0457 entryList = currentEntry; 0458 0459 // anything to do with time stamp 0460 time_t currentEpoch; 0461 time(¤tEpoch); 0462 struct tm *currentTime = localtime(¤tEpoch); 0463 0464 currentEntry->timeStamp = (unsigned short) 0465 (((currentTime->tm_hour & 31) << 11) | // 5-bit hours 0466 ((currentTime->tm_min & 63) << 5) | // 6-bit minutes 0467 ((currentTime->tm_sec & 31)*2)); // 5-bit seconds*2 0468 0469 if (currentTime->tm_year >= 80) 0470 // note: year is using 1980 as reference 0471 currentEntry->dateStamp = (unsigned short) 0472 ((((currentTime->tm_year-80) & 127) << 9) | // 7-bit years 0473 (((currentTime->tm_mon+1) & 15) << 5) | // 4-bit months 0474 (currentTime->tm_mday & 31)); // 5-bit days 0475 else 0476 // before 1980, can't be represented so set to Jan 1, 1980 0477 currentEntry->dateStamp = (1 << 5) | 1; 0478 0479 // because we need to "fix" the header in closeEntry() 0480 currentEntry->headerPos = (unsigned long) ftell(fhandle); 0481 0482 writeLocalHeader(currentEntry); 0483 } 0484 0485 void closeEntry() 0486 { 0487 if (errorCode != FemtoZip::NoError) 0488 return; 0489 0490 if (!fhandle) 0491 { 0492 FZ_DEBUG(("closeEntry error: file already closed")); 0493 return; 0494 } 0495 0496 if (!currentEntry) 0497 { 0498 FZ_DEBUG(("closeEntry error: no entry is opened")); 0499 return; 0500 } 0501 0502 currentEntry->compressedSize = currentEntry->uncompressedSize; 0503 0504 // post-condition for the CRC-32, i.e. one's complement 0505 currentEntry->crc32 ^= 0xffffffffL; 0506 0507 // we need to come back again here later on 0508 long filepos = ftell(fhandle); 0509 0510 // "fix" the local header in the right position 0511 fseek(fhandle, (long) currentEntry->headerPos, SEEK_SET); 0512 writeLocalHeader(currentEntry); 0513 0514 // back to where we left 0515 fseek(fhandle, filepos, SEEK_SET); 0516 0517 // that's all for this one 0518 currentEntry = 0; 0519 } 0520 0521 void writeData(unsigned long len, const void *data) 0522 { 0523 if (errorCode != FemtoZip::NoError) 0524 return; 0525 0526 if (!fhandle) 0527 { 0528 FZ_DEBUG(("writeData error: file already closed")); 0529 return; 0530 } 0531 0532 if (!currentEntry) 0533 { 0534 FZ_DEBUG(("writeData error: no entry is opened")); 0535 return; 0536 } 0537 0538 currentEntry->crc32 = updateCRC(currentEntry->crc32, data, len); 0539 currentEntry->uncompressedSize += len; 0540 0541 // method: Store 0542 if (fwrite(data, 1, len, fhandle) != len) 0543 errorCode = FemtoZip::ErrorWriteData; 0544 } 0545 }; 0546 0547 0548 0549 0550 0551 FemtoZip::FemtoZip(const char *zipfile) : d(0) 0552 { 0553 d = new FemtoZipPrivate; 0554 d->createZip(zipfile); 0555 } 0556 0557 FemtoZip::~FemtoZip() 0558 { 0559 d->closeZip(); 0560 delete d; 0561 } 0562 0563 void FemtoZip::createEntry(const char *name, int compressionLevel) 0564 { 0565 d->createEntry(name, compressionLevel); 0566 } 0567 0568 void FemtoZip::writeString(const char *str) 0569 { 0570 d->writeData(strlen(str), str); 0571 } 0572 0573 void FemtoZip::closeEntry() 0574 { 0575 d->closeEntry(); 0576 } 0577 0578 int FemtoZip::errorCode() const 0579 { 0580 return d->errorCode; 0581 } 0582 0583 #endif 0584 0585 /* vim:set shiftwidth=4 softtabstop=4 noexpandtab: */