Fixes default log output to console for macOS
[sqlcipher.git] / ext / misc / zipfile.c
blobdb327809f8c424a6821f592995d6b5e47529a403
1 /*
2 ** 2017-12-26
3 **
4 ** The author disclaims copyright to this source code. In place of
5 ** a legal notice, here is a blessing:
6 **
7 ** May you do good and not evil.
8 ** May you find forgiveness for yourself and forgive others.
9 ** May you share freely, never taking more than you give.
11 ******************************************************************************
13 ** This file implements a virtual table for reading and writing ZIP archive
14 ** files.
16 ** Usage example:
18 ** SELECT name, sz, datetime(mtime,'unixepoch') FROM zipfile($filename);
20 ** Current limitations:
22 ** * No support for encryption
23 ** * No support for ZIP archives spanning multiple files
24 ** * No support for zip64 extensions
25 ** * Only the "inflate/deflate" (zlib) compression method is supported
27 #include "sqlite3ext.h"
28 SQLITE_EXTENSION_INIT1
29 #include <stdio.h>
30 #include <string.h>
31 #include <assert.h>
32 #include <stdint.h>
34 #include <zlib.h>
36 #ifndef SQLITE_OMIT_VIRTUALTABLE
38 #ifndef SQLITE_AMALGAMATION
40 #ifndef UINT32_TYPE
41 # ifdef HAVE_UINT32_T
42 # define UINT32_TYPE uint32_t
43 # else
44 # define UINT32_TYPE unsigned int
45 # endif
46 #endif
47 #ifndef UINT16_TYPE
48 # ifdef HAVE_UINT16_T
49 # define UINT16_TYPE uint16_t
50 # else
51 # define UINT16_TYPE unsigned short int
52 # endif
53 #endif
54 typedef sqlite3_int64 i64;
55 typedef unsigned char u8;
56 typedef UINT32_TYPE u32; /* 4-byte unsigned integer */
57 typedef UINT16_TYPE u16; /* 2-byte unsigned integer */
58 #define MIN(a,b) ((a)<(b) ? (a) : (b))
60 #if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
61 # define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
62 #endif
63 #if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
64 # define ALWAYS(X) (1)
65 # define NEVER(X) (0)
66 #elif !defined(NDEBUG)
67 # define ALWAYS(X) ((X)?1:(assert(0),0))
68 # define NEVER(X) ((X)?(assert(0),1):0)
69 #else
70 # define ALWAYS(X) (X)
71 # define NEVER(X) (X)
72 #endif
74 #endif /* SQLITE_AMALGAMATION */
77 ** Definitions for mode bitmasks S_IFDIR, S_IFREG and S_IFLNK.
79 ** In some ways it would be better to obtain these values from system
80 ** header files. But, the dependency is undesirable and (a) these
81 ** have been stable for decades, (b) the values are part of POSIX and
82 ** are also made explicit in [man stat], and (c) are part of the
83 ** file format for zip archives.
85 #ifndef S_IFDIR
86 # define S_IFDIR 0040000
87 #endif
88 #ifndef S_IFREG
89 # define S_IFREG 0100000
90 #endif
91 #ifndef S_IFLNK
92 # define S_IFLNK 0120000
93 #endif
95 static const char ZIPFILE_SCHEMA[] =
96 "CREATE TABLE y("
97 "name PRIMARY KEY," /* 0: Name of file in zip archive */
98 "mode," /* 1: POSIX mode for file */
99 "mtime," /* 2: Last modification time (secs since 1970)*/
100 "sz," /* 3: Size of object */
101 "rawdata," /* 4: Raw data */
102 "data," /* 5: Uncompressed data */
103 "method," /* 6: Compression method (integer) */
104 "z HIDDEN" /* 7: Name of zip file */
105 ") WITHOUT ROWID;";
107 #define ZIPFILE_F_COLUMN_IDX 7 /* Index of column "file" in the above */
108 #define ZIPFILE_BUFFER_SIZE (64*1024)
112 ** Magic numbers used to read and write zip files.
114 ** ZIPFILE_NEWENTRY_MADEBY:
115 ** Use this value for the "version-made-by" field in new zip file
116 ** entries. The upper byte indicates "unix", and the lower byte
117 ** indicates that the zip file matches pkzip specification 3.0.
118 ** This is what info-zip seems to do.
120 ** ZIPFILE_NEWENTRY_REQUIRED:
121 ** Value for "version-required-to-extract" field of new entries.
122 ** Version 2.0 is required to support folders and deflate compression.
124 ** ZIPFILE_NEWENTRY_FLAGS:
125 ** Value for "general-purpose-bit-flags" field of new entries. Bit
126 ** 11 means "utf-8 filename and comment".
128 ** ZIPFILE_SIGNATURE_CDS:
129 ** First 4 bytes of a valid CDS record.
131 ** ZIPFILE_SIGNATURE_LFH:
132 ** First 4 bytes of a valid LFH record.
134 ** ZIPFILE_SIGNATURE_EOCD
135 ** First 4 bytes of a valid EOCD record.
137 #define ZIPFILE_EXTRA_TIMESTAMP 0x5455
138 #define ZIPFILE_NEWENTRY_MADEBY ((3<<8) + 30)
139 #define ZIPFILE_NEWENTRY_REQUIRED 20
140 #define ZIPFILE_NEWENTRY_FLAGS 0x800
141 #define ZIPFILE_SIGNATURE_CDS 0x02014b50
142 #define ZIPFILE_SIGNATURE_LFH 0x04034b50
143 #define ZIPFILE_SIGNATURE_EOCD 0x06054b50
146 ** The sizes of the fixed-size part of each of the three main data
147 ** structures in a zip archive.
149 #define ZIPFILE_LFH_FIXED_SZ 30
150 #define ZIPFILE_EOCD_FIXED_SZ 22
151 #define ZIPFILE_CDS_FIXED_SZ 46
154 *** 4.3.16 End of central directory record:
156 *** end of central dir signature 4 bytes (0x06054b50)
157 *** number of this disk 2 bytes
158 *** number of the disk with the
159 *** start of the central directory 2 bytes
160 *** total number of entries in the
161 *** central directory on this disk 2 bytes
162 *** total number of entries in
163 *** the central directory 2 bytes
164 *** size of the central directory 4 bytes
165 *** offset of start of central
166 *** directory with respect to
167 *** the starting disk number 4 bytes
168 *** .ZIP file comment length 2 bytes
169 *** .ZIP file comment (variable size)
171 typedef struct ZipfileEOCD ZipfileEOCD;
172 struct ZipfileEOCD {
173 u16 iDisk;
174 u16 iFirstDisk;
175 u16 nEntry;
176 u16 nEntryTotal;
177 u32 nSize;
178 u32 iOffset;
182 *** 4.3.12 Central directory structure:
184 *** ...
186 *** central file header signature 4 bytes (0x02014b50)
187 *** version made by 2 bytes
188 *** version needed to extract 2 bytes
189 *** general purpose bit flag 2 bytes
190 *** compression method 2 bytes
191 *** last mod file time 2 bytes
192 *** last mod file date 2 bytes
193 *** crc-32 4 bytes
194 *** compressed size 4 bytes
195 *** uncompressed size 4 bytes
196 *** file name length 2 bytes
197 *** extra field length 2 bytes
198 *** file comment length 2 bytes
199 *** disk number start 2 bytes
200 *** internal file attributes 2 bytes
201 *** external file attributes 4 bytes
202 *** relative offset of local header 4 bytes
204 typedef struct ZipfileCDS ZipfileCDS;
205 struct ZipfileCDS {
206 u16 iVersionMadeBy;
207 u16 iVersionExtract;
208 u16 flags;
209 u16 iCompression;
210 u16 mTime;
211 u16 mDate;
212 u32 crc32;
213 u32 szCompressed;
214 u32 szUncompressed;
215 u16 nFile;
216 u16 nExtra;
217 u16 nComment;
218 u16 iDiskStart;
219 u16 iInternalAttr;
220 u32 iExternalAttr;
221 u32 iOffset;
222 char *zFile; /* Filename (sqlite3_malloc()) */
226 *** 4.3.7 Local file header:
228 *** local file header signature 4 bytes (0x04034b50)
229 *** version needed to extract 2 bytes
230 *** general purpose bit flag 2 bytes
231 *** compression method 2 bytes
232 *** last mod file time 2 bytes
233 *** last mod file date 2 bytes
234 *** crc-32 4 bytes
235 *** compressed size 4 bytes
236 *** uncompressed size 4 bytes
237 *** file name length 2 bytes
238 *** extra field length 2 bytes
239 ***
241 typedef struct ZipfileLFH ZipfileLFH;
242 struct ZipfileLFH {
243 u16 iVersionExtract;
244 u16 flags;
245 u16 iCompression;
246 u16 mTime;
247 u16 mDate;
248 u32 crc32;
249 u32 szCompressed;
250 u32 szUncompressed;
251 u16 nFile;
252 u16 nExtra;
255 typedef struct ZipfileEntry ZipfileEntry;
256 struct ZipfileEntry {
257 ZipfileCDS cds; /* Parsed CDS record */
258 u32 mUnixTime; /* Modification time, in UNIX format */
259 u8 *aExtra; /* cds.nExtra+cds.nComment bytes of extra data */
260 i64 iDataOff; /* Offset to data in file (if aData==0) */
261 u8 *aData; /* cds.szCompressed bytes of compressed data */
262 ZipfileEntry *pNext; /* Next element in in-memory CDS */
266 ** Cursor type for zipfile tables.
268 typedef struct ZipfileCsr ZipfileCsr;
269 struct ZipfileCsr {
270 sqlite3_vtab_cursor base; /* Base class - must be first */
271 i64 iId; /* Cursor ID */
272 u8 bEof; /* True when at EOF */
273 u8 bNoop; /* If next xNext() call is no-op */
275 /* Used outside of write transactions */
276 FILE *pFile; /* Zip file */
277 i64 iNextOff; /* Offset of next record in central directory */
278 ZipfileEOCD eocd; /* Parse of central directory record */
280 ZipfileEntry *pFreeEntry; /* Free this list when cursor is closed or reset */
281 ZipfileEntry *pCurrent; /* Current entry */
282 ZipfileCsr *pCsrNext; /* Next cursor on same virtual table */
285 typedef struct ZipfileTab ZipfileTab;
286 struct ZipfileTab {
287 sqlite3_vtab base; /* Base class - must be first */
288 char *zFile; /* Zip file this table accesses (may be NULL) */
289 sqlite3 *db; /* Host database connection */
290 u8 *aBuffer; /* Temporary buffer used for various tasks */
292 ZipfileCsr *pCsrList; /* List of cursors */
293 i64 iNextCsrid;
295 /* The following are used by write transactions only */
296 ZipfileEntry *pFirstEntry; /* Linked list of all files (if pWriteFd!=0) */
297 ZipfileEntry *pLastEntry; /* Last element in pFirstEntry list */
298 FILE *pWriteFd; /* File handle open on zip archive */
299 i64 szCurrent; /* Current size of zip archive */
300 i64 szOrig; /* Size of archive at start of transaction */
304 ** Set the error message contained in context ctx to the results of
305 ** vprintf(zFmt, ...).
307 static void zipfileCtxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){
308 char *zMsg = 0;
309 va_list ap;
310 va_start(ap, zFmt);
311 zMsg = sqlite3_vmprintf(zFmt, ap);
312 sqlite3_result_error(ctx, zMsg, -1);
313 sqlite3_free(zMsg);
314 va_end(ap);
318 ** If string zIn is quoted, dequote it in place. Otherwise, if the string
319 ** is not quoted, do nothing.
321 static void zipfileDequote(char *zIn){
322 char q = zIn[0];
323 if( q=='"' || q=='\'' || q=='`' || q=='[' ){
324 int iIn = 1;
325 int iOut = 0;
326 if( q=='[' ) q = ']';
327 while( ALWAYS(zIn[iIn]) ){
328 char c = zIn[iIn++];
329 if( c==q && zIn[iIn++]!=q ) break;
330 zIn[iOut++] = c;
332 zIn[iOut] = '\0';
337 ** Construct a new ZipfileTab virtual table object.
339 ** argv[0] -> module name ("zipfile")
340 ** argv[1] -> database name
341 ** argv[2] -> table name
342 ** argv[...] -> "column name" and other module argument fields.
344 static int zipfileConnect(
345 sqlite3 *db,
346 void *pAux,
347 int argc, const char *const*argv,
348 sqlite3_vtab **ppVtab,
349 char **pzErr
351 int nByte = sizeof(ZipfileTab) + ZIPFILE_BUFFER_SIZE;
352 int nFile = 0;
353 const char *zFile = 0;
354 ZipfileTab *pNew = 0;
355 int rc;
356 (void)pAux;
358 /* If the table name is not "zipfile", require that the argument be
359 ** specified. This stops zipfile tables from being created as:
361 ** CREATE VIRTUAL TABLE zzz USING zipfile();
363 ** It does not prevent:
365 ** CREATE VIRTUAL TABLE zipfile USING zipfile();
367 assert( 0==sqlite3_stricmp(argv[0], "zipfile") );
368 if( (0!=sqlite3_stricmp(argv[2], "zipfile") && argc<4) || argc>4 ){
369 *pzErr = sqlite3_mprintf("zipfile constructor requires one argument");
370 return SQLITE_ERROR;
373 if( argc>3 ){
374 zFile = argv[3];
375 nFile = (int)strlen(zFile)+1;
378 rc = sqlite3_declare_vtab(db, ZIPFILE_SCHEMA);
379 if( rc==SQLITE_OK ){
380 pNew = (ZipfileTab*)sqlite3_malloc64((sqlite3_int64)nByte+nFile);
381 if( pNew==0 ) return SQLITE_NOMEM;
382 memset(pNew, 0, nByte+nFile);
383 pNew->db = db;
384 pNew->aBuffer = (u8*)&pNew[1];
385 if( zFile ){
386 pNew->zFile = (char*)&pNew->aBuffer[ZIPFILE_BUFFER_SIZE];
387 memcpy(pNew->zFile, zFile, nFile);
388 zipfileDequote(pNew->zFile);
391 sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY);
392 *ppVtab = (sqlite3_vtab*)pNew;
393 return rc;
397 ** Free the ZipfileEntry structure indicated by the only argument.
399 static void zipfileEntryFree(ZipfileEntry *p){
400 if( p ){
401 sqlite3_free(p->cds.zFile);
402 sqlite3_free(p);
407 ** Release resources that should be freed at the end of a write
408 ** transaction.
410 static void zipfileCleanupTransaction(ZipfileTab *pTab){
411 ZipfileEntry *pEntry;
412 ZipfileEntry *pNext;
414 if( pTab->pWriteFd ){
415 fclose(pTab->pWriteFd);
416 pTab->pWriteFd = 0;
418 for(pEntry=pTab->pFirstEntry; pEntry; pEntry=pNext){
419 pNext = pEntry->pNext;
420 zipfileEntryFree(pEntry);
422 pTab->pFirstEntry = 0;
423 pTab->pLastEntry = 0;
424 pTab->szCurrent = 0;
425 pTab->szOrig = 0;
429 ** This method is the destructor for zipfile vtab objects.
431 static int zipfileDisconnect(sqlite3_vtab *pVtab){
432 zipfileCleanupTransaction((ZipfileTab*)pVtab);
433 sqlite3_free(pVtab);
434 return SQLITE_OK;
438 ** Constructor for a new ZipfileCsr object.
440 static int zipfileOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCsr){
441 ZipfileTab *pTab = (ZipfileTab*)p;
442 ZipfileCsr *pCsr;
443 pCsr = sqlite3_malloc(sizeof(*pCsr));
444 *ppCsr = (sqlite3_vtab_cursor*)pCsr;
445 if( pCsr==0 ){
446 return SQLITE_NOMEM;
448 memset(pCsr, 0, sizeof(*pCsr));
449 pCsr->iId = ++pTab->iNextCsrid;
450 pCsr->pCsrNext = pTab->pCsrList;
451 pTab->pCsrList = pCsr;
452 return SQLITE_OK;
456 ** Reset a cursor back to the state it was in when first returned
457 ** by zipfileOpen().
459 static void zipfileResetCursor(ZipfileCsr *pCsr){
460 ZipfileEntry *p;
461 ZipfileEntry *pNext;
463 pCsr->bEof = 0;
464 if( pCsr->pFile ){
465 fclose(pCsr->pFile);
466 pCsr->pFile = 0;
467 zipfileEntryFree(pCsr->pCurrent);
468 pCsr->pCurrent = 0;
471 for(p=pCsr->pFreeEntry; p; p=pNext){
472 pNext = p->pNext;
473 zipfileEntryFree(p);
478 ** Destructor for an ZipfileCsr.
480 static int zipfileClose(sqlite3_vtab_cursor *cur){
481 ZipfileCsr *pCsr = (ZipfileCsr*)cur;
482 ZipfileTab *pTab = (ZipfileTab*)(pCsr->base.pVtab);
483 ZipfileCsr **pp;
484 zipfileResetCursor(pCsr);
486 /* Remove this cursor from the ZipfileTab.pCsrList list. */
487 for(pp=&pTab->pCsrList; *pp!=pCsr; pp=&((*pp)->pCsrNext));
488 *pp = pCsr->pCsrNext;
490 sqlite3_free(pCsr);
491 return SQLITE_OK;
495 ** Set the error message for the virtual table associated with cursor
496 ** pCsr to the results of vprintf(zFmt, ...).
498 static void zipfileTableErr(ZipfileTab *pTab, const char *zFmt, ...){
499 va_list ap;
500 va_start(ap, zFmt);
501 sqlite3_free(pTab->base.zErrMsg);
502 pTab->base.zErrMsg = sqlite3_vmprintf(zFmt, ap);
503 va_end(ap);
505 static void zipfileCursorErr(ZipfileCsr *pCsr, const char *zFmt, ...){
506 va_list ap;
507 va_start(ap, zFmt);
508 sqlite3_free(pCsr->base.pVtab->zErrMsg);
509 pCsr->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap);
510 va_end(ap);
514 ** Read nRead bytes of data from offset iOff of file pFile into buffer
515 ** aRead[]. Return SQLITE_OK if successful, or an SQLite error code
516 ** otherwise.
518 ** If an error does occur, output variable (*pzErrmsg) may be set to point
519 ** to an English language error message. It is the responsibility of the
520 ** caller to eventually free this buffer using
521 ** sqlite3_free().
523 static int zipfileReadData(
524 FILE *pFile, /* Read from this file */
525 u8 *aRead, /* Read into this buffer */
526 int nRead, /* Number of bytes to read */
527 i64 iOff, /* Offset to read from */
528 char **pzErrmsg /* OUT: Error message (from sqlite3_malloc) */
530 size_t n;
531 fseek(pFile, (long)iOff, SEEK_SET);
532 n = fread(aRead, 1, nRead, pFile);
533 if( (int)n!=nRead ){
534 *pzErrmsg = sqlite3_mprintf("error in fread()");
535 return SQLITE_ERROR;
537 return SQLITE_OK;
540 static int zipfileAppendData(
541 ZipfileTab *pTab,
542 const u8 *aWrite,
543 int nWrite
545 if( nWrite>0 ){
546 size_t n = nWrite;
547 fseek(pTab->pWriteFd, (long)pTab->szCurrent, SEEK_SET);
548 n = fwrite(aWrite, 1, nWrite, pTab->pWriteFd);
549 if( (int)n!=nWrite ){
550 pTab->base.zErrMsg = sqlite3_mprintf("error in fwrite()");
551 return SQLITE_ERROR;
553 pTab->szCurrent += nWrite;
555 return SQLITE_OK;
559 ** Read and return a 16-bit little-endian unsigned integer from buffer aBuf.
561 static u16 zipfileGetU16(const u8 *aBuf){
562 return (aBuf[1] << 8) + aBuf[0];
566 ** Read and return a 32-bit little-endian unsigned integer from buffer aBuf.
568 static u32 zipfileGetU32(const u8 *aBuf){
569 if( aBuf==0 ) return 0;
570 return ((u32)(aBuf[3]) << 24)
571 + ((u32)(aBuf[2]) << 16)
572 + ((u32)(aBuf[1]) << 8)
573 + ((u32)(aBuf[0]) << 0);
577 ** Write a 16-bit little endiate integer into buffer aBuf.
579 static void zipfilePutU16(u8 *aBuf, u16 val){
580 aBuf[0] = val & 0xFF;
581 aBuf[1] = (val>>8) & 0xFF;
585 ** Write a 32-bit little endiate integer into buffer aBuf.
587 static void zipfilePutU32(u8 *aBuf, u32 val){
588 aBuf[0] = val & 0xFF;
589 aBuf[1] = (val>>8) & 0xFF;
590 aBuf[2] = (val>>16) & 0xFF;
591 aBuf[3] = (val>>24) & 0xFF;
594 #define zipfileRead32(aBuf) ( aBuf+=4, zipfileGetU32(aBuf-4) )
595 #define zipfileRead16(aBuf) ( aBuf+=2, zipfileGetU16(aBuf-2) )
597 #define zipfileWrite32(aBuf,val) { zipfilePutU32(aBuf,val); aBuf+=4; }
598 #define zipfileWrite16(aBuf,val) { zipfilePutU16(aBuf,val); aBuf+=2; }
601 ** Magic numbers used to read CDS records.
603 #define ZIPFILE_CDS_NFILE_OFF 28
604 #define ZIPFILE_CDS_SZCOMPRESSED_OFF 20
607 ** Decode the CDS record in buffer aBuf into (*pCDS). Return SQLITE_ERROR
608 ** if the record is not well-formed, or SQLITE_OK otherwise.
610 static int zipfileReadCDS(u8 *aBuf, ZipfileCDS *pCDS){
611 u8 *aRead = aBuf;
612 u32 sig = zipfileRead32(aRead);
613 int rc = SQLITE_OK;
614 if( sig!=ZIPFILE_SIGNATURE_CDS ){
615 rc = SQLITE_ERROR;
616 }else{
617 pCDS->iVersionMadeBy = zipfileRead16(aRead);
618 pCDS->iVersionExtract = zipfileRead16(aRead);
619 pCDS->flags = zipfileRead16(aRead);
620 pCDS->iCompression = zipfileRead16(aRead);
621 pCDS->mTime = zipfileRead16(aRead);
622 pCDS->mDate = zipfileRead16(aRead);
623 pCDS->crc32 = zipfileRead32(aRead);
624 pCDS->szCompressed = zipfileRead32(aRead);
625 pCDS->szUncompressed = zipfileRead32(aRead);
626 assert( aRead==&aBuf[ZIPFILE_CDS_NFILE_OFF] );
627 pCDS->nFile = zipfileRead16(aRead);
628 pCDS->nExtra = zipfileRead16(aRead);
629 pCDS->nComment = zipfileRead16(aRead);
630 pCDS->iDiskStart = zipfileRead16(aRead);
631 pCDS->iInternalAttr = zipfileRead16(aRead);
632 pCDS->iExternalAttr = zipfileRead32(aRead);
633 pCDS->iOffset = zipfileRead32(aRead);
634 assert( aRead==&aBuf[ZIPFILE_CDS_FIXED_SZ] );
637 return rc;
641 ** Decode the LFH record in buffer aBuf into (*pLFH). Return SQLITE_ERROR
642 ** if the record is not well-formed, or SQLITE_OK otherwise.
644 static int zipfileReadLFH(
645 u8 *aBuffer,
646 ZipfileLFH *pLFH
648 u8 *aRead = aBuffer;
649 int rc = SQLITE_OK;
651 u32 sig = zipfileRead32(aRead);
652 if( sig!=ZIPFILE_SIGNATURE_LFH ){
653 rc = SQLITE_ERROR;
654 }else{
655 pLFH->iVersionExtract = zipfileRead16(aRead);
656 pLFH->flags = zipfileRead16(aRead);
657 pLFH->iCompression = zipfileRead16(aRead);
658 pLFH->mTime = zipfileRead16(aRead);
659 pLFH->mDate = zipfileRead16(aRead);
660 pLFH->crc32 = zipfileRead32(aRead);
661 pLFH->szCompressed = zipfileRead32(aRead);
662 pLFH->szUncompressed = zipfileRead32(aRead);
663 pLFH->nFile = zipfileRead16(aRead);
664 pLFH->nExtra = zipfileRead16(aRead);
666 return rc;
671 ** Buffer aExtra (size nExtra bytes) contains zip archive "extra" fields.
672 ** Scan through this buffer to find an "extra-timestamp" field. If one
673 ** exists, extract the 32-bit modification-timestamp from it and store
674 ** the value in output parameter *pmTime.
676 ** Zero is returned if no extra-timestamp record could be found (and so
677 ** *pmTime is left unchanged), or non-zero otherwise.
679 ** The general format of an extra field is:
681 ** Header ID 2 bytes
682 ** Data Size 2 bytes
683 ** Data N bytes
685 static int zipfileScanExtra(u8 *aExtra, int nExtra, u32 *pmTime){
686 int ret = 0;
687 u8 *p = aExtra;
688 u8 *pEnd = &aExtra[nExtra];
690 while( p<pEnd ){
691 u16 id = zipfileRead16(p);
692 u16 nByte = zipfileRead16(p);
694 switch( id ){
695 case ZIPFILE_EXTRA_TIMESTAMP: {
696 u8 b = p[0];
697 if( b & 0x01 ){ /* 0x01 -> modtime is present */
698 *pmTime = zipfileGetU32(&p[1]);
699 ret = 1;
701 break;
705 p += nByte;
707 return ret;
711 ** Convert the standard MS-DOS timestamp stored in the mTime and mDate
712 ** fields of the CDS structure passed as the only argument to a 32-bit
713 ** UNIX seconds-since-the-epoch timestamp. Return the result.
715 ** "Standard" MS-DOS time format:
717 ** File modification time:
718 ** Bits 00-04: seconds divided by 2
719 ** Bits 05-10: minute
720 ** Bits 11-15: hour
721 ** File modification date:
722 ** Bits 00-04: day
723 ** Bits 05-08: month (1-12)
724 ** Bits 09-15: years from 1980
726 ** https://msdn.microsoft.com/en-us/library/9kkf9tah.aspx
728 static u32 zipfileMtime(ZipfileCDS *pCDS){
729 int Y,M,D,X1,X2,A,B,sec,min,hr;
730 i64 JDsec;
731 Y = (1980 + ((pCDS->mDate >> 9) & 0x7F));
732 M = ((pCDS->mDate >> 5) & 0x0F);
733 D = (pCDS->mDate & 0x1F);
734 sec = (pCDS->mTime & 0x1F)*2;
735 min = (pCDS->mTime >> 5) & 0x3F;
736 hr = (pCDS->mTime >> 11) & 0x1F;
737 if( M<=2 ){
738 Y--;
739 M += 12;
741 X1 = 36525*(Y+4716)/100;
742 X2 = 306001*(M+1)/10000;
743 A = Y/100;
744 B = 2 - A + (A/4);
745 JDsec = (i64)((X1 + X2 + D + B - 1524.5)*86400) + hr*3600 + min*60 + sec;
746 return (u32)(JDsec - (i64)24405875*(i64)8640);
750 ** The opposite of zipfileMtime(). This function populates the mTime and
751 ** mDate fields of the CDS structure passed as the first argument according
752 ** to the UNIX timestamp value passed as the second.
754 static void zipfileMtimeToDos(ZipfileCDS *pCds, u32 mUnixTime){
755 /* Convert unix timestamp to JD (2440588 is noon on 1/1/1970) */
756 i64 JD = (i64)2440588 + mUnixTime / (24*60*60);
758 int A, B, C, D, E;
759 int yr, mon, day;
760 int hr, min, sec;
762 A = (int)((JD - 1867216.25)/36524.25);
763 A = (int)(JD + 1 + A - (A/4));
764 B = A + 1524;
765 C = (int)((B - 122.1)/365.25);
766 D = (36525*(C&32767))/100;
767 E = (int)((B-D)/30.6001);
769 day = B - D - (int)(30.6001*E);
770 mon = (E<14 ? E-1 : E-13);
771 yr = mon>2 ? C-4716 : C-4715;
773 hr = (mUnixTime % (24*60*60)) / (60*60);
774 min = (mUnixTime % (60*60)) / 60;
775 sec = (mUnixTime % 60);
777 if( yr>=1980 ){
778 pCds->mDate = (u16)(day + (mon << 5) + ((yr-1980) << 9));
779 pCds->mTime = (u16)(sec/2 + (min<<5) + (hr<<11));
780 }else{
781 pCds->mDate = pCds->mTime = 0;
784 assert( mUnixTime<315507600
785 || mUnixTime==zipfileMtime(pCds)
786 || ((mUnixTime % 2) && mUnixTime-1==zipfileMtime(pCds))
787 /* || (mUnixTime % 2) */
792 ** If aBlob is not NULL, then it is a pointer to a buffer (nBlob bytes in
793 ** size) containing an entire zip archive image. Or, if aBlob is NULL,
794 ** then pFile is a file-handle open on a zip file. In either case, this
795 ** function creates a ZipfileEntry object based on the zip archive entry
796 ** for which the CDS record is at offset iOff.
798 ** If successful, SQLITE_OK is returned and (*ppEntry) set to point to
799 ** the new object. Otherwise, an SQLite error code is returned and the
800 ** final value of (*ppEntry) undefined.
802 static int zipfileGetEntry(
803 ZipfileTab *pTab, /* Store any error message here */
804 const u8 *aBlob, /* Pointer to in-memory file image */
805 int nBlob, /* Size of aBlob[] in bytes */
806 FILE *pFile, /* If aBlob==0, read from this file */
807 i64 iOff, /* Offset of CDS record */
808 ZipfileEntry **ppEntry /* OUT: Pointer to new object */
810 u8 *aRead;
811 char **pzErr = &pTab->base.zErrMsg;
812 int rc = SQLITE_OK;
813 (void)nBlob;
815 if( aBlob==0 ){
816 aRead = pTab->aBuffer;
817 rc = zipfileReadData(pFile, aRead, ZIPFILE_CDS_FIXED_SZ, iOff, pzErr);
818 }else{
819 aRead = (u8*)&aBlob[iOff];
822 if( rc==SQLITE_OK ){
823 sqlite3_int64 nAlloc;
824 ZipfileEntry *pNew;
826 int nFile = zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF]);
827 int nExtra = zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF+2]);
828 nExtra += zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF+4]);
830 nAlloc = sizeof(ZipfileEntry) + nExtra;
831 if( aBlob ){
832 nAlloc += zipfileGetU32(&aRead[ZIPFILE_CDS_SZCOMPRESSED_OFF]);
835 pNew = (ZipfileEntry*)sqlite3_malloc64(nAlloc);
836 if( pNew==0 ){
837 rc = SQLITE_NOMEM;
838 }else{
839 memset(pNew, 0, sizeof(ZipfileEntry));
840 rc = zipfileReadCDS(aRead, &pNew->cds);
841 if( rc!=SQLITE_OK ){
842 *pzErr = sqlite3_mprintf("failed to read CDS at offset %lld", iOff);
843 }else if( aBlob==0 ){
844 rc = zipfileReadData(
845 pFile, aRead, nExtra+nFile, iOff+ZIPFILE_CDS_FIXED_SZ, pzErr
847 }else{
848 aRead = (u8*)&aBlob[iOff + ZIPFILE_CDS_FIXED_SZ];
852 if( rc==SQLITE_OK ){
853 u32 *pt = &pNew->mUnixTime;
854 pNew->cds.zFile = sqlite3_mprintf("%.*s", nFile, aRead);
855 pNew->aExtra = (u8*)&pNew[1];
856 memcpy(pNew->aExtra, &aRead[nFile], nExtra);
857 if( pNew->cds.zFile==0 ){
858 rc = SQLITE_NOMEM;
859 }else if( 0==zipfileScanExtra(&aRead[nFile], pNew->cds.nExtra, pt) ){
860 pNew->mUnixTime = zipfileMtime(&pNew->cds);
864 if( rc==SQLITE_OK ){
865 static const int szFix = ZIPFILE_LFH_FIXED_SZ;
866 ZipfileLFH lfh;
867 if( pFile ){
868 rc = zipfileReadData(pFile, aRead, szFix, pNew->cds.iOffset, pzErr);
869 }else{
870 aRead = (u8*)&aBlob[pNew->cds.iOffset];
873 if( rc==SQLITE_OK ) rc = zipfileReadLFH(aRead, &lfh);
874 if( rc==SQLITE_OK ){
875 pNew->iDataOff = pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ;
876 pNew->iDataOff += lfh.nFile + lfh.nExtra;
877 if( aBlob && pNew->cds.szCompressed ){
878 pNew->aData = &pNew->aExtra[nExtra];
879 memcpy(pNew->aData, &aBlob[pNew->iDataOff], pNew->cds.szCompressed);
881 }else{
882 *pzErr = sqlite3_mprintf("failed to read LFH at offset %d",
883 (int)pNew->cds.iOffset
888 if( rc!=SQLITE_OK ){
889 zipfileEntryFree(pNew);
890 }else{
891 *ppEntry = pNew;
895 return rc;
899 ** Advance an ZipfileCsr to its next row of output.
901 static int zipfileNext(sqlite3_vtab_cursor *cur){
902 ZipfileCsr *pCsr = (ZipfileCsr*)cur;
903 int rc = SQLITE_OK;
905 if( pCsr->pFile ){
906 i64 iEof = pCsr->eocd.iOffset + pCsr->eocd.nSize;
907 zipfileEntryFree(pCsr->pCurrent);
908 pCsr->pCurrent = 0;
909 if( pCsr->iNextOff>=iEof ){
910 pCsr->bEof = 1;
911 }else{
912 ZipfileEntry *p = 0;
913 ZipfileTab *pTab = (ZipfileTab*)(cur->pVtab);
914 rc = zipfileGetEntry(pTab, 0, 0, pCsr->pFile, pCsr->iNextOff, &p);
915 if( rc==SQLITE_OK ){
916 pCsr->iNextOff += ZIPFILE_CDS_FIXED_SZ;
917 pCsr->iNextOff += (int)p->cds.nExtra + p->cds.nFile + p->cds.nComment;
919 pCsr->pCurrent = p;
921 }else{
922 if( !pCsr->bNoop ){
923 pCsr->pCurrent = pCsr->pCurrent->pNext;
925 if( pCsr->pCurrent==0 ){
926 pCsr->bEof = 1;
930 pCsr->bNoop = 0;
931 return rc;
934 static void zipfileFree(void *p) {
935 sqlite3_free(p);
939 ** Buffer aIn (size nIn bytes) contains compressed data. Uncompressed, the
940 ** size is nOut bytes. This function uncompresses the data and sets the
941 ** return value in context pCtx to the result (a blob).
943 ** If an error occurs, an error code is left in pCtx instead.
945 static void zipfileInflate(
946 sqlite3_context *pCtx, /* Store result here */
947 const u8 *aIn, /* Compressed data */
948 int nIn, /* Size of buffer aIn[] in bytes */
949 int nOut /* Expected output size */
951 u8 *aRes = sqlite3_malloc(nOut);
952 if( aRes==0 ){
953 sqlite3_result_error_nomem(pCtx);
954 }else{
955 int err;
956 z_stream str;
957 memset(&str, 0, sizeof(str));
959 str.next_in = (Byte*)aIn;
960 str.avail_in = nIn;
961 str.next_out = (Byte*)aRes;
962 str.avail_out = nOut;
964 err = inflateInit2(&str, -15);
965 if( err!=Z_OK ){
966 zipfileCtxErrorMsg(pCtx, "inflateInit2() failed (%d)", err);
967 }else{
968 err = inflate(&str, Z_NO_FLUSH);
969 if( err!=Z_STREAM_END ){
970 zipfileCtxErrorMsg(pCtx, "inflate() failed (%d)", err);
971 }else{
972 sqlite3_result_blob(pCtx, aRes, nOut, zipfileFree);
973 aRes = 0;
976 sqlite3_free(aRes);
977 inflateEnd(&str);
982 ** Buffer aIn (size nIn bytes) contains uncompressed data. This function
983 ** compresses it and sets (*ppOut) to point to a buffer containing the
984 ** compressed data. The caller is responsible for eventually calling
985 ** sqlite3_free() to release buffer (*ppOut). Before returning, (*pnOut)
986 ** is set to the size of buffer (*ppOut) in bytes.
988 ** If no error occurs, SQLITE_OK is returned. Otherwise, an SQLite error
989 ** code is returned and an error message left in virtual-table handle
990 ** pTab. The values of (*ppOut) and (*pnOut) are left unchanged in this
991 ** case.
993 static int zipfileDeflate(
994 const u8 *aIn, int nIn, /* Input */
995 u8 **ppOut, int *pnOut, /* Output */
996 char **pzErr /* OUT: Error message */
998 int rc = SQLITE_OK;
999 sqlite3_int64 nAlloc;
1000 z_stream str;
1001 u8 *aOut;
1003 memset(&str, 0, sizeof(str));
1004 str.next_in = (Bytef*)aIn;
1005 str.avail_in = nIn;
1006 deflateInit2(&str, 9, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
1008 nAlloc = deflateBound(&str, nIn);
1009 aOut = (u8*)sqlite3_malloc64(nAlloc);
1010 if( aOut==0 ){
1011 rc = SQLITE_NOMEM;
1012 }else{
1013 int res;
1014 str.next_out = aOut;
1015 str.avail_out = nAlloc;
1016 res = deflate(&str, Z_FINISH);
1017 if( res==Z_STREAM_END ){
1018 *ppOut = aOut;
1019 *pnOut = (int)str.total_out;
1020 }else{
1021 sqlite3_free(aOut);
1022 *pzErr = sqlite3_mprintf("zipfile: deflate() error");
1023 rc = SQLITE_ERROR;
1025 deflateEnd(&str);
1028 return rc;
1033 ** Return values of columns for the row at which the series_cursor
1034 ** is currently pointing.
1036 static int zipfileColumn(
1037 sqlite3_vtab_cursor *cur, /* The cursor */
1038 sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
1039 int i /* Which column to return */
1041 ZipfileCsr *pCsr = (ZipfileCsr*)cur;
1042 ZipfileCDS *pCDS = &pCsr->pCurrent->cds;
1043 int rc = SQLITE_OK;
1044 switch( i ){
1045 case 0: /* name */
1046 sqlite3_result_text(ctx, pCDS->zFile, -1, SQLITE_TRANSIENT);
1047 break;
1048 case 1: /* mode */
1049 /* TODO: Whether or not the following is correct surely depends on
1050 ** the platform on which the archive was created. */
1051 sqlite3_result_int(ctx, pCDS->iExternalAttr >> 16);
1052 break;
1053 case 2: { /* mtime */
1054 sqlite3_result_int64(ctx, pCsr->pCurrent->mUnixTime);
1055 break;
1057 case 3: { /* sz */
1058 if( sqlite3_vtab_nochange(ctx)==0 ){
1059 sqlite3_result_int64(ctx, pCDS->szUncompressed);
1061 break;
1063 case 4: /* rawdata */
1064 if( sqlite3_vtab_nochange(ctx) ) break;
1065 case 5: { /* data */
1066 if( i==4 || pCDS->iCompression==0 || pCDS->iCompression==8 ){
1067 int sz = pCDS->szCompressed;
1068 int szFinal = pCDS->szUncompressed;
1069 if( szFinal>0 ){
1070 u8 *aBuf;
1071 u8 *aFree = 0;
1072 if( pCsr->pCurrent->aData ){
1073 aBuf = pCsr->pCurrent->aData;
1074 }else{
1075 aBuf = aFree = sqlite3_malloc64(sz);
1076 if( aBuf==0 ){
1077 rc = SQLITE_NOMEM;
1078 }else{
1079 FILE *pFile = pCsr->pFile;
1080 if( pFile==0 ){
1081 pFile = ((ZipfileTab*)(pCsr->base.pVtab))->pWriteFd;
1083 rc = zipfileReadData(pFile, aBuf, sz, pCsr->pCurrent->iDataOff,
1084 &pCsr->base.pVtab->zErrMsg
1088 if( rc==SQLITE_OK ){
1089 if( i==5 && pCDS->iCompression ){
1090 zipfileInflate(ctx, aBuf, sz, szFinal);
1091 }else{
1092 sqlite3_result_blob(ctx, aBuf, sz, SQLITE_TRANSIENT);
1095 sqlite3_free(aFree);
1096 }else{
1097 /* Figure out if this is a directory or a zero-sized file. Consider
1098 ** it to be a directory either if the mode suggests so, or if
1099 ** the final character in the name is '/'. */
1100 u32 mode = pCDS->iExternalAttr >> 16;
1101 if( !(mode & S_IFDIR)
1102 && pCDS->nFile>=1
1103 && pCDS->zFile[pCDS->nFile-1]!='/'
1105 sqlite3_result_blob(ctx, "", 0, SQLITE_STATIC);
1109 break;
1111 case 6: /* method */
1112 sqlite3_result_int(ctx, pCDS->iCompression);
1113 break;
1114 default: /* z */
1115 assert( i==7 );
1116 sqlite3_result_int64(ctx, pCsr->iId);
1117 break;
1120 return rc;
1124 ** Return TRUE if the cursor is at EOF.
1126 static int zipfileEof(sqlite3_vtab_cursor *cur){
1127 ZipfileCsr *pCsr = (ZipfileCsr*)cur;
1128 return pCsr->bEof;
1132 ** If aBlob is not NULL, then it points to a buffer nBlob bytes in size
1133 ** containing an entire zip archive image. Or, if aBlob is NULL, then pFile
1134 ** is guaranteed to be a file-handle open on a zip file.
1136 ** This function attempts to locate the EOCD record within the zip archive
1137 ** and populate *pEOCD with the results of decoding it. SQLITE_OK is
1138 ** returned if successful. Otherwise, an SQLite error code is returned and
1139 ** an English language error message may be left in virtual-table pTab.
1141 static int zipfileReadEOCD(
1142 ZipfileTab *pTab, /* Return errors here */
1143 const u8 *aBlob, /* Pointer to in-memory file image */
1144 int nBlob, /* Size of aBlob[] in bytes */
1145 FILE *pFile, /* Read from this file if aBlob==0 */
1146 ZipfileEOCD *pEOCD /* Object to populate */
1148 u8 *aRead = pTab->aBuffer; /* Temporary buffer */
1149 int nRead; /* Bytes to read from file */
1150 int rc = SQLITE_OK;
1152 memset(pEOCD, 0, sizeof(ZipfileEOCD));
1153 if( aBlob==0 ){
1154 i64 iOff; /* Offset to read from */
1155 i64 szFile; /* Total size of file in bytes */
1156 fseek(pFile, 0, SEEK_END);
1157 szFile = (i64)ftell(pFile);
1158 if( szFile==0 ){
1159 return SQLITE_OK;
1161 nRead = (int)(MIN(szFile, ZIPFILE_BUFFER_SIZE));
1162 iOff = szFile - nRead;
1163 rc = zipfileReadData(pFile, aRead, nRead, iOff, &pTab->base.zErrMsg);
1164 }else{
1165 nRead = (int)(MIN(nBlob, ZIPFILE_BUFFER_SIZE));
1166 aRead = (u8*)&aBlob[nBlob-nRead];
1169 if( rc==SQLITE_OK ){
1170 int i;
1172 /* Scan backwards looking for the signature bytes */
1173 for(i=nRead-20; i>=0; i--){
1174 if( aRead[i]==0x50 && aRead[i+1]==0x4b
1175 && aRead[i+2]==0x05 && aRead[i+3]==0x06
1177 break;
1180 if( i<0 ){
1181 pTab->base.zErrMsg = sqlite3_mprintf(
1182 "cannot find end of central directory record"
1184 return SQLITE_ERROR;
1187 aRead += i+4;
1188 pEOCD->iDisk = zipfileRead16(aRead);
1189 pEOCD->iFirstDisk = zipfileRead16(aRead);
1190 pEOCD->nEntry = zipfileRead16(aRead);
1191 pEOCD->nEntryTotal = zipfileRead16(aRead);
1192 pEOCD->nSize = zipfileRead32(aRead);
1193 pEOCD->iOffset = zipfileRead32(aRead);
1196 return rc;
1200 ** Add object pNew to the linked list that begins at ZipfileTab.pFirstEntry
1201 ** and ends with pLastEntry. If argument pBefore is NULL, then pNew is added
1202 ** to the end of the list. Otherwise, it is added to the list immediately
1203 ** before pBefore (which is guaranteed to be a part of said list).
1205 static void zipfileAddEntry(
1206 ZipfileTab *pTab,
1207 ZipfileEntry *pBefore,
1208 ZipfileEntry *pNew
1210 assert( (pTab->pFirstEntry==0)==(pTab->pLastEntry==0) );
1211 assert( pNew->pNext==0 );
1212 if( pBefore==0 ){
1213 if( pTab->pFirstEntry==0 ){
1214 pTab->pFirstEntry = pTab->pLastEntry = pNew;
1215 }else{
1216 assert( pTab->pLastEntry->pNext==0 );
1217 pTab->pLastEntry->pNext = pNew;
1218 pTab->pLastEntry = pNew;
1220 }else{
1221 ZipfileEntry **pp;
1222 for(pp=&pTab->pFirstEntry; *pp!=pBefore; pp=&((*pp)->pNext));
1223 pNew->pNext = pBefore;
1224 *pp = pNew;
1228 static int zipfileLoadDirectory(ZipfileTab *pTab, const u8 *aBlob, int nBlob){
1229 ZipfileEOCD eocd;
1230 int rc;
1231 int i;
1232 i64 iOff;
1234 rc = zipfileReadEOCD(pTab, aBlob, nBlob, pTab->pWriteFd, &eocd);
1235 iOff = eocd.iOffset;
1236 for(i=0; rc==SQLITE_OK && i<eocd.nEntry; i++){
1237 ZipfileEntry *pNew = 0;
1238 rc = zipfileGetEntry(pTab, aBlob, nBlob, pTab->pWriteFd, iOff, &pNew);
1240 if( rc==SQLITE_OK ){
1241 zipfileAddEntry(pTab, 0, pNew);
1242 iOff += ZIPFILE_CDS_FIXED_SZ;
1243 iOff += (int)pNew->cds.nExtra + pNew->cds.nFile + pNew->cds.nComment;
1246 return rc;
1250 ** xFilter callback.
1252 static int zipfileFilter(
1253 sqlite3_vtab_cursor *cur,
1254 int idxNum, const char *idxStr,
1255 int argc, sqlite3_value **argv
1257 ZipfileTab *pTab = (ZipfileTab*)cur->pVtab;
1258 ZipfileCsr *pCsr = (ZipfileCsr*)cur;
1259 const char *zFile = 0; /* Zip file to scan */
1260 int rc = SQLITE_OK; /* Return Code */
1261 int bInMemory = 0; /* True for an in-memory zipfile */
1263 (void)idxStr;
1264 (void)argc;
1266 zipfileResetCursor(pCsr);
1268 if( pTab->zFile ){
1269 zFile = pTab->zFile;
1270 }else if( idxNum==0 ){
1271 zipfileCursorErr(pCsr, "zipfile() function requires an argument");
1272 return SQLITE_ERROR;
1273 }else if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
1274 static const u8 aEmptyBlob = 0;
1275 const u8 *aBlob = (const u8*)sqlite3_value_blob(argv[0]);
1276 int nBlob = sqlite3_value_bytes(argv[0]);
1277 assert( pTab->pFirstEntry==0 );
1278 if( aBlob==0 ){
1279 aBlob = &aEmptyBlob;
1280 nBlob = 0;
1282 rc = zipfileLoadDirectory(pTab, aBlob, nBlob);
1283 pCsr->pFreeEntry = pTab->pFirstEntry;
1284 pTab->pFirstEntry = pTab->pLastEntry = 0;
1285 if( rc!=SQLITE_OK ) return rc;
1286 bInMemory = 1;
1287 }else{
1288 zFile = (const char*)sqlite3_value_text(argv[0]);
1291 if( 0==pTab->pWriteFd && 0==bInMemory ){
1292 pCsr->pFile = zFile ? fopen(zFile, "rb") : 0;
1293 if( pCsr->pFile==0 ){
1294 zipfileCursorErr(pCsr, "cannot open file: %s", zFile);
1295 rc = SQLITE_ERROR;
1296 }else{
1297 rc = zipfileReadEOCD(pTab, 0, 0, pCsr->pFile, &pCsr->eocd);
1298 if( rc==SQLITE_OK ){
1299 if( pCsr->eocd.nEntry==0 ){
1300 pCsr->bEof = 1;
1301 }else{
1302 pCsr->iNextOff = pCsr->eocd.iOffset;
1303 rc = zipfileNext(cur);
1307 }else{
1308 pCsr->bNoop = 1;
1309 pCsr->pCurrent = pCsr->pFreeEntry ? pCsr->pFreeEntry : pTab->pFirstEntry;
1310 rc = zipfileNext(cur);
1313 return rc;
1317 ** xBestIndex callback.
1319 static int zipfileBestIndex(
1320 sqlite3_vtab *tab,
1321 sqlite3_index_info *pIdxInfo
1323 int i;
1324 int idx = -1;
1325 int unusable = 0;
1326 (void)tab;
1328 for(i=0; i<pIdxInfo->nConstraint; i++){
1329 const struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i];
1330 if( pCons->iColumn!=ZIPFILE_F_COLUMN_IDX ) continue;
1331 if( pCons->usable==0 ){
1332 unusable = 1;
1333 }else if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){
1334 idx = i;
1337 pIdxInfo->estimatedCost = 1000.0;
1338 if( idx>=0 ){
1339 pIdxInfo->aConstraintUsage[idx].argvIndex = 1;
1340 pIdxInfo->aConstraintUsage[idx].omit = 1;
1341 pIdxInfo->idxNum = 1;
1342 }else if( unusable ){
1343 return SQLITE_CONSTRAINT;
1345 return SQLITE_OK;
1348 static ZipfileEntry *zipfileNewEntry(const char *zPath){
1349 ZipfileEntry *pNew;
1350 pNew = sqlite3_malloc(sizeof(ZipfileEntry));
1351 if( pNew ){
1352 memset(pNew, 0, sizeof(ZipfileEntry));
1353 pNew->cds.zFile = sqlite3_mprintf("%s", zPath);
1354 if( pNew->cds.zFile==0 ){
1355 sqlite3_free(pNew);
1356 pNew = 0;
1359 return pNew;
1362 static int zipfileSerializeLFH(ZipfileEntry *pEntry, u8 *aBuf){
1363 ZipfileCDS *pCds = &pEntry->cds;
1364 u8 *a = aBuf;
1366 pCds->nExtra = 9;
1368 /* Write the LFH itself */
1369 zipfileWrite32(a, ZIPFILE_SIGNATURE_LFH);
1370 zipfileWrite16(a, pCds->iVersionExtract);
1371 zipfileWrite16(a, pCds->flags);
1372 zipfileWrite16(a, pCds->iCompression);
1373 zipfileWrite16(a, pCds->mTime);
1374 zipfileWrite16(a, pCds->mDate);
1375 zipfileWrite32(a, pCds->crc32);
1376 zipfileWrite32(a, pCds->szCompressed);
1377 zipfileWrite32(a, pCds->szUncompressed);
1378 zipfileWrite16(a, (u16)pCds->nFile);
1379 zipfileWrite16(a, pCds->nExtra);
1380 assert( a==&aBuf[ZIPFILE_LFH_FIXED_SZ] );
1382 /* Add the file name */
1383 memcpy(a, pCds->zFile, (int)pCds->nFile);
1384 a += (int)pCds->nFile;
1386 /* The "extra" data */
1387 zipfileWrite16(a, ZIPFILE_EXTRA_TIMESTAMP);
1388 zipfileWrite16(a, 5);
1389 *a++ = 0x01;
1390 zipfileWrite32(a, pEntry->mUnixTime);
1392 return a-aBuf;
1395 static int zipfileAppendEntry(
1396 ZipfileTab *pTab,
1397 ZipfileEntry *pEntry,
1398 const u8 *pData,
1399 int nData
1401 u8 *aBuf = pTab->aBuffer;
1402 int nBuf;
1403 int rc;
1405 nBuf = zipfileSerializeLFH(pEntry, aBuf);
1406 rc = zipfileAppendData(pTab, aBuf, nBuf);
1407 if( rc==SQLITE_OK ){
1408 pEntry->iDataOff = pTab->szCurrent;
1409 rc = zipfileAppendData(pTab, pData, nData);
1412 return rc;
1415 static int zipfileGetMode(
1416 sqlite3_value *pVal,
1417 int bIsDir, /* If true, default to directory */
1418 u32 *pMode, /* OUT: Mode value */
1419 char **pzErr /* OUT: Error message */
1421 const char *z = (const char*)sqlite3_value_text(pVal);
1422 u32 mode = 0;
1423 if( z==0 ){
1424 mode = (bIsDir ? (S_IFDIR + 0755) : (S_IFREG + 0644));
1425 }else if( z[0]>='0' && z[0]<='9' ){
1426 mode = (unsigned int)sqlite3_value_int(pVal);
1427 }else{
1428 const char zTemplate[11] = "-rwxrwxrwx";
1429 int i;
1430 if( strlen(z)!=10 ) goto parse_error;
1431 switch( z[0] ){
1432 case '-': mode |= S_IFREG; break;
1433 case 'd': mode |= S_IFDIR; break;
1434 case 'l': mode |= S_IFLNK; break;
1435 default: goto parse_error;
1437 for(i=1; i<10; i++){
1438 if( z[i]==zTemplate[i] ) mode |= 1 << (9-i);
1439 else if( z[i]!='-' ) goto parse_error;
1442 if( ((mode & S_IFDIR)==0)==bIsDir ){
1443 /* The "mode" attribute is a directory, but data has been specified.
1444 ** Or vice-versa - no data but "mode" is a file or symlink. */
1445 *pzErr = sqlite3_mprintf("zipfile: mode does not match data");
1446 return SQLITE_CONSTRAINT;
1448 *pMode = mode;
1449 return SQLITE_OK;
1451 parse_error:
1452 *pzErr = sqlite3_mprintf("zipfile: parse error in mode: %s", z);
1453 return SQLITE_ERROR;
1457 ** Both (const char*) arguments point to nul-terminated strings. Argument
1458 ** nB is the value of strlen(zB). This function returns 0 if the strings are
1459 ** identical, ignoring any trailing '/' character in either path. */
1460 static int zipfileComparePath(const char *zA, const char *zB, int nB){
1461 int nA = (int)strlen(zA);
1462 if( nA>0 && zA[nA-1]=='/' ) nA--;
1463 if( nB>0 && zB[nB-1]=='/' ) nB--;
1464 if( nA==nB && memcmp(zA, zB, nA)==0 ) return 0;
1465 return 1;
1468 static int zipfileBegin(sqlite3_vtab *pVtab){
1469 ZipfileTab *pTab = (ZipfileTab*)pVtab;
1470 int rc = SQLITE_OK;
1472 assert( pTab->pWriteFd==0 );
1473 if( pTab->zFile==0 || pTab->zFile[0]==0 ){
1474 pTab->base.zErrMsg = sqlite3_mprintf("zipfile: missing filename");
1475 return SQLITE_ERROR;
1478 /* Open a write fd on the file. Also load the entire central directory
1479 ** structure into memory. During the transaction any new file data is
1480 ** appended to the archive file, but the central directory is accumulated
1481 ** in main-memory until the transaction is committed. */
1482 pTab->pWriteFd = fopen(pTab->zFile, "ab+");
1483 if( pTab->pWriteFd==0 ){
1484 pTab->base.zErrMsg = sqlite3_mprintf(
1485 "zipfile: failed to open file %s for writing", pTab->zFile
1487 rc = SQLITE_ERROR;
1488 }else{
1489 fseek(pTab->pWriteFd, 0, SEEK_END);
1490 pTab->szCurrent = pTab->szOrig = (i64)ftell(pTab->pWriteFd);
1491 rc = zipfileLoadDirectory(pTab, 0, 0);
1494 if( rc!=SQLITE_OK ){
1495 zipfileCleanupTransaction(pTab);
1498 return rc;
1502 ** Return the current time as a 32-bit timestamp in UNIX epoch format (like
1503 ** time(2)).
1505 static u32 zipfileTime(void){
1506 sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
1507 u32 ret;
1508 if( pVfs==0 ) return 0;
1509 if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){
1510 i64 ms;
1511 pVfs->xCurrentTimeInt64(pVfs, &ms);
1512 ret = (u32)((ms/1000) - ((i64)24405875 * 8640));
1513 }else{
1514 double day;
1515 pVfs->xCurrentTime(pVfs, &day);
1516 ret = (u32)((day - 2440587.5) * 86400);
1518 return ret;
1522 ** Return a 32-bit timestamp in UNIX epoch format.
1524 ** If the value passed as the only argument is either NULL or an SQL NULL,
1525 ** return the current time. Otherwise, return the value stored in (*pVal)
1526 ** cast to a 32-bit unsigned integer.
1528 static u32 zipfileGetTime(sqlite3_value *pVal){
1529 if( pVal==0 || sqlite3_value_type(pVal)==SQLITE_NULL ){
1530 return zipfileTime();
1532 return (u32)sqlite3_value_int64(pVal);
1536 ** Unless it is NULL, entry pOld is currently part of the pTab->pFirstEntry
1537 ** linked list. Remove it from the list and free the object.
1539 static void zipfileRemoveEntryFromList(ZipfileTab *pTab, ZipfileEntry *pOld){
1540 if( pOld ){
1541 if( pTab->pFirstEntry==pOld ){
1542 pTab->pFirstEntry = pOld->pNext;
1543 if( pTab->pLastEntry==pOld ) pTab->pLastEntry = 0;
1544 }else{
1545 ZipfileEntry *p;
1546 for(p=pTab->pFirstEntry; p; p=p->pNext){
1547 if( p->pNext==pOld ){
1548 p->pNext = pOld->pNext;
1549 if( pTab->pLastEntry==pOld ) pTab->pLastEntry = p;
1550 break;
1554 zipfileEntryFree(pOld);
1559 ** xUpdate method.
1561 static int zipfileUpdate(
1562 sqlite3_vtab *pVtab,
1563 int nVal,
1564 sqlite3_value **apVal,
1565 sqlite_int64 *pRowid
1567 ZipfileTab *pTab = (ZipfileTab*)pVtab;
1568 int rc = SQLITE_OK; /* Return Code */
1569 ZipfileEntry *pNew = 0; /* New in-memory CDS entry */
1571 u32 mode = 0; /* Mode for new entry */
1572 u32 mTime = 0; /* Modification time for new entry */
1573 i64 sz = 0; /* Uncompressed size */
1574 const char *zPath = 0; /* Path for new entry */
1575 int nPath = 0; /* strlen(zPath) */
1576 const u8 *pData = 0; /* Pointer to buffer containing content */
1577 int nData = 0; /* Size of pData buffer in bytes */
1578 int iMethod = 0; /* Compression method for new entry */
1579 u8 *pFree = 0; /* Free this */
1580 char *zFree = 0; /* Also free this */
1581 ZipfileEntry *pOld = 0;
1582 ZipfileEntry *pOld2 = 0;
1583 int bUpdate = 0; /* True for an update that modifies "name" */
1584 int bIsDir = 0;
1585 u32 iCrc32 = 0;
1587 (void)pRowid;
1589 if( pTab->pWriteFd==0 ){
1590 rc = zipfileBegin(pVtab);
1591 if( rc!=SQLITE_OK ) return rc;
1594 /* If this is a DELETE or UPDATE, find the archive entry to delete. */
1595 if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
1596 const char *zDelete = (const char*)sqlite3_value_text(apVal[0]);
1597 int nDelete = (int)strlen(zDelete);
1598 if( nVal>1 ){
1599 const char *zUpdate = (const char*)sqlite3_value_text(apVal[1]);
1600 if( zUpdate && zipfileComparePath(zUpdate, zDelete, nDelete)!=0 ){
1601 bUpdate = 1;
1604 for(pOld=pTab->pFirstEntry; 1; pOld=pOld->pNext){
1605 if( zipfileComparePath(pOld->cds.zFile, zDelete, nDelete)==0 ){
1606 break;
1608 assert( pOld->pNext );
1612 if( nVal>1 ){
1613 /* Check that "sz" and "rawdata" are both NULL: */
1614 if( sqlite3_value_type(apVal[5])!=SQLITE_NULL ){
1615 zipfileTableErr(pTab, "sz must be NULL");
1616 rc = SQLITE_CONSTRAINT;
1618 if( sqlite3_value_type(apVal[6])!=SQLITE_NULL ){
1619 zipfileTableErr(pTab, "rawdata must be NULL");
1620 rc = SQLITE_CONSTRAINT;
1623 if( rc==SQLITE_OK ){
1624 if( sqlite3_value_type(apVal[7])==SQLITE_NULL ){
1625 /* data=NULL. A directory */
1626 bIsDir = 1;
1627 }else{
1628 /* Value specified for "data", and possibly "method". This must be
1629 ** a regular file or a symlink. */
1630 const u8 *aIn = sqlite3_value_blob(apVal[7]);
1631 int nIn = sqlite3_value_bytes(apVal[7]);
1632 int bAuto = sqlite3_value_type(apVal[8])==SQLITE_NULL;
1634 iMethod = sqlite3_value_int(apVal[8]);
1635 sz = nIn;
1636 pData = aIn;
1637 nData = nIn;
1638 if( iMethod!=0 && iMethod!=8 ){
1639 zipfileTableErr(pTab, "unknown compression method: %d", iMethod);
1640 rc = SQLITE_CONSTRAINT;
1641 }else{
1642 if( bAuto || iMethod ){
1643 int nCmp;
1644 rc = zipfileDeflate(aIn, nIn, &pFree, &nCmp, &pTab->base.zErrMsg);
1645 if( rc==SQLITE_OK ){
1646 if( iMethod || nCmp<nIn ){
1647 iMethod = 8;
1648 pData = pFree;
1649 nData = nCmp;
1653 iCrc32 = crc32(0, aIn, nIn);
1658 if( rc==SQLITE_OK ){
1659 rc = zipfileGetMode(apVal[3], bIsDir, &mode, &pTab->base.zErrMsg);
1662 if( rc==SQLITE_OK ){
1663 zPath = (const char*)sqlite3_value_text(apVal[2]);
1664 if( zPath==0 ) zPath = "";
1665 nPath = (int)strlen(zPath);
1666 mTime = zipfileGetTime(apVal[4]);
1669 if( rc==SQLITE_OK && bIsDir ){
1670 /* For a directory, check that the last character in the path is a
1671 ** '/'. This appears to be required for compatibility with info-zip
1672 ** (the unzip command on unix). It does not create directories
1673 ** otherwise. */
1674 if( nPath<=0 || zPath[nPath-1]!='/' ){
1675 zFree = sqlite3_mprintf("%s/", zPath);
1676 zPath = (const char*)zFree;
1677 if( zFree==0 ){
1678 rc = SQLITE_NOMEM;
1679 nPath = 0;
1680 }else{
1681 nPath = (int)strlen(zPath);
1686 /* Check that we're not inserting a duplicate entry -OR- updating an
1687 ** entry with a path, thereby making it into a duplicate. */
1688 if( (pOld==0 || bUpdate) && rc==SQLITE_OK ){
1689 ZipfileEntry *p;
1690 for(p=pTab->pFirstEntry; p; p=p->pNext){
1691 if( zipfileComparePath(p->cds.zFile, zPath, nPath)==0 ){
1692 switch( sqlite3_vtab_on_conflict(pTab->db) ){
1693 case SQLITE_IGNORE: {
1694 goto zipfile_update_done;
1696 case SQLITE_REPLACE: {
1697 pOld2 = p;
1698 break;
1700 default: {
1701 zipfileTableErr(pTab, "duplicate name: \"%s\"", zPath);
1702 rc = SQLITE_CONSTRAINT;
1703 break;
1706 break;
1711 if( rc==SQLITE_OK ){
1712 /* Create the new CDS record. */
1713 pNew = zipfileNewEntry(zPath);
1714 if( pNew==0 ){
1715 rc = SQLITE_NOMEM;
1716 }else{
1717 pNew->cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY;
1718 pNew->cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED;
1719 pNew->cds.flags = ZIPFILE_NEWENTRY_FLAGS;
1720 pNew->cds.iCompression = (u16)iMethod;
1721 zipfileMtimeToDos(&pNew->cds, mTime);
1722 pNew->cds.crc32 = iCrc32;
1723 pNew->cds.szCompressed = nData;
1724 pNew->cds.szUncompressed = (u32)sz;
1725 pNew->cds.iExternalAttr = (mode<<16);
1726 pNew->cds.iOffset = (u32)pTab->szCurrent;
1727 pNew->cds.nFile = (u16)nPath;
1728 pNew->mUnixTime = (u32)mTime;
1729 rc = zipfileAppendEntry(pTab, pNew, pData, nData);
1730 zipfileAddEntry(pTab, pOld, pNew);
1735 if( rc==SQLITE_OK && (pOld || pOld2) ){
1736 ZipfileCsr *pCsr;
1737 for(pCsr=pTab->pCsrList; pCsr; pCsr=pCsr->pCsrNext){
1738 if( pCsr->pCurrent && (pCsr->pCurrent==pOld || pCsr->pCurrent==pOld2) ){
1739 pCsr->pCurrent = pCsr->pCurrent->pNext;
1740 pCsr->bNoop = 1;
1744 zipfileRemoveEntryFromList(pTab, pOld);
1745 zipfileRemoveEntryFromList(pTab, pOld2);
1748 zipfile_update_done:
1749 sqlite3_free(pFree);
1750 sqlite3_free(zFree);
1751 return rc;
1754 static int zipfileSerializeEOCD(ZipfileEOCD *p, u8 *aBuf){
1755 u8 *a = aBuf;
1756 zipfileWrite32(a, ZIPFILE_SIGNATURE_EOCD);
1757 zipfileWrite16(a, p->iDisk);
1758 zipfileWrite16(a, p->iFirstDisk);
1759 zipfileWrite16(a, p->nEntry);
1760 zipfileWrite16(a, p->nEntryTotal);
1761 zipfileWrite32(a, p->nSize);
1762 zipfileWrite32(a, p->iOffset);
1763 zipfileWrite16(a, 0); /* Size of trailing comment in bytes*/
1765 return a-aBuf;
1768 static int zipfileAppendEOCD(ZipfileTab *pTab, ZipfileEOCD *p){
1769 int nBuf = zipfileSerializeEOCD(p, pTab->aBuffer);
1770 assert( nBuf==ZIPFILE_EOCD_FIXED_SZ );
1771 return zipfileAppendData(pTab, pTab->aBuffer, nBuf);
1775 ** Serialize the CDS structure into buffer aBuf[]. Return the number
1776 ** of bytes written.
1778 static int zipfileSerializeCDS(ZipfileEntry *pEntry, u8 *aBuf){
1779 u8 *a = aBuf;
1780 ZipfileCDS *pCDS = &pEntry->cds;
1782 if( pEntry->aExtra==0 ){
1783 pCDS->nExtra = 9;
1786 zipfileWrite32(a, ZIPFILE_SIGNATURE_CDS);
1787 zipfileWrite16(a, pCDS->iVersionMadeBy);
1788 zipfileWrite16(a, pCDS->iVersionExtract);
1789 zipfileWrite16(a, pCDS->flags);
1790 zipfileWrite16(a, pCDS->iCompression);
1791 zipfileWrite16(a, pCDS->mTime);
1792 zipfileWrite16(a, pCDS->mDate);
1793 zipfileWrite32(a, pCDS->crc32);
1794 zipfileWrite32(a, pCDS->szCompressed);
1795 zipfileWrite32(a, pCDS->szUncompressed);
1796 assert( a==&aBuf[ZIPFILE_CDS_NFILE_OFF] );
1797 zipfileWrite16(a, pCDS->nFile);
1798 zipfileWrite16(a, pCDS->nExtra);
1799 zipfileWrite16(a, pCDS->nComment);
1800 zipfileWrite16(a, pCDS->iDiskStart);
1801 zipfileWrite16(a, pCDS->iInternalAttr);
1802 zipfileWrite32(a, pCDS->iExternalAttr);
1803 zipfileWrite32(a, pCDS->iOffset);
1805 memcpy(a, pCDS->zFile, pCDS->nFile);
1806 a += pCDS->nFile;
1808 if( pEntry->aExtra ){
1809 int n = (int)pCDS->nExtra + (int)pCDS->nComment;
1810 memcpy(a, pEntry->aExtra, n);
1811 a += n;
1812 }else{
1813 assert( pCDS->nExtra==9 );
1814 zipfileWrite16(a, ZIPFILE_EXTRA_TIMESTAMP);
1815 zipfileWrite16(a, 5);
1816 *a++ = 0x01;
1817 zipfileWrite32(a, pEntry->mUnixTime);
1820 return a-aBuf;
1823 static int zipfileCommit(sqlite3_vtab *pVtab){
1824 ZipfileTab *pTab = (ZipfileTab*)pVtab;
1825 int rc = SQLITE_OK;
1826 if( pTab->pWriteFd ){
1827 i64 iOffset = pTab->szCurrent;
1828 ZipfileEntry *p;
1829 ZipfileEOCD eocd;
1830 int nEntry = 0;
1832 /* Write out all entries */
1833 for(p=pTab->pFirstEntry; rc==SQLITE_OK && p; p=p->pNext){
1834 int n = zipfileSerializeCDS(p, pTab->aBuffer);
1835 rc = zipfileAppendData(pTab, pTab->aBuffer, n);
1836 nEntry++;
1839 /* Write out the EOCD record */
1840 eocd.iDisk = 0;
1841 eocd.iFirstDisk = 0;
1842 eocd.nEntry = (u16)nEntry;
1843 eocd.nEntryTotal = (u16)nEntry;
1844 eocd.nSize = (u32)(pTab->szCurrent - iOffset);
1845 eocd.iOffset = (u32)iOffset;
1846 rc = zipfileAppendEOCD(pTab, &eocd);
1848 zipfileCleanupTransaction(pTab);
1850 return rc;
1853 static int zipfileRollback(sqlite3_vtab *pVtab){
1854 return zipfileCommit(pVtab);
1857 static ZipfileCsr *zipfileFindCursor(ZipfileTab *pTab, i64 iId){
1858 ZipfileCsr *pCsr;
1859 for(pCsr=pTab->pCsrList; pCsr; pCsr=pCsr->pCsrNext){
1860 if( iId==pCsr->iId ) break;
1862 return pCsr;
1865 static void zipfileFunctionCds(
1866 sqlite3_context *context,
1867 int argc,
1868 sqlite3_value **argv
1870 ZipfileCsr *pCsr;
1871 ZipfileTab *pTab = (ZipfileTab*)sqlite3_user_data(context);
1872 assert( argc>0 );
1874 pCsr = zipfileFindCursor(pTab, sqlite3_value_int64(argv[0]));
1875 if( pCsr ){
1876 ZipfileCDS *p = &pCsr->pCurrent->cds;
1877 char *zRes = sqlite3_mprintf("{"
1878 "\"version-made-by\" : %u, "
1879 "\"version-to-extract\" : %u, "
1880 "\"flags\" : %u, "
1881 "\"compression\" : %u, "
1882 "\"time\" : %u, "
1883 "\"date\" : %u, "
1884 "\"crc32\" : %u, "
1885 "\"compressed-size\" : %u, "
1886 "\"uncompressed-size\" : %u, "
1887 "\"file-name-length\" : %u, "
1888 "\"extra-field-length\" : %u, "
1889 "\"file-comment-length\" : %u, "
1890 "\"disk-number-start\" : %u, "
1891 "\"internal-attr\" : %u, "
1892 "\"external-attr\" : %u, "
1893 "\"offset\" : %u }",
1894 (u32)p->iVersionMadeBy, (u32)p->iVersionExtract,
1895 (u32)p->flags, (u32)p->iCompression,
1896 (u32)p->mTime, (u32)p->mDate,
1897 (u32)p->crc32, (u32)p->szCompressed,
1898 (u32)p->szUncompressed, (u32)p->nFile,
1899 (u32)p->nExtra, (u32)p->nComment,
1900 (u32)p->iDiskStart, (u32)p->iInternalAttr,
1901 (u32)p->iExternalAttr, (u32)p->iOffset
1904 if( zRes==0 ){
1905 sqlite3_result_error_nomem(context);
1906 }else{
1907 sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT);
1908 sqlite3_free(zRes);
1914 ** xFindFunction method.
1916 static int zipfileFindFunction(
1917 sqlite3_vtab *pVtab, /* Virtual table handle */
1918 int nArg, /* Number of SQL function arguments */
1919 const char *zName, /* Name of SQL function */
1920 void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */
1921 void **ppArg /* OUT: User data for *pxFunc */
1923 (void)nArg;
1924 if( sqlite3_stricmp("zipfile_cds", zName)==0 ){
1925 *pxFunc = zipfileFunctionCds;
1926 *ppArg = (void*)pVtab;
1927 return 1;
1929 return 0;
1932 typedef struct ZipfileBuffer ZipfileBuffer;
1933 struct ZipfileBuffer {
1934 u8 *a; /* Pointer to buffer */
1935 int n; /* Size of buffer in bytes */
1936 int nAlloc; /* Byte allocated at a[] */
1939 typedef struct ZipfileCtx ZipfileCtx;
1940 struct ZipfileCtx {
1941 int nEntry;
1942 ZipfileBuffer body;
1943 ZipfileBuffer cds;
1946 static int zipfileBufferGrow(ZipfileBuffer *pBuf, int nByte){
1947 if( pBuf->n+nByte>pBuf->nAlloc ){
1948 u8 *aNew;
1949 sqlite3_int64 nNew = pBuf->n ? pBuf->n*2 : 512;
1950 int nReq = pBuf->n + nByte;
1952 while( nNew<nReq ) nNew = nNew*2;
1953 aNew = sqlite3_realloc64(pBuf->a, nNew);
1954 if( aNew==0 ) return SQLITE_NOMEM;
1955 pBuf->a = aNew;
1956 pBuf->nAlloc = (int)nNew;
1958 return SQLITE_OK;
1962 ** xStep() callback for the zipfile() aggregate. This can be called in
1963 ** any of the following ways:
1965 ** SELECT zipfile(name,data) ...
1966 ** SELECT zipfile(name,mode,mtime,data) ...
1967 ** SELECT zipfile(name,mode,mtime,data,method) ...
1969 static void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
1970 ZipfileCtx *p; /* Aggregate function context */
1971 ZipfileEntry e; /* New entry to add to zip archive */
1973 sqlite3_value *pName = 0;
1974 sqlite3_value *pMode = 0;
1975 sqlite3_value *pMtime = 0;
1976 sqlite3_value *pData = 0;
1977 sqlite3_value *pMethod = 0;
1979 int bIsDir = 0;
1980 u32 mode;
1981 int rc = SQLITE_OK;
1982 char *zErr = 0;
1984 int iMethod = -1; /* Compression method to use (0 or 8) */
1986 const u8 *aData = 0; /* Possibly compressed data for new entry */
1987 int nData = 0; /* Size of aData[] in bytes */
1988 int szUncompressed = 0; /* Size of data before compression */
1989 u8 *aFree = 0; /* Free this before returning */
1990 u32 iCrc32 = 0; /* crc32 of uncompressed data */
1992 char *zName = 0; /* Path (name) of new entry */
1993 int nName = 0; /* Size of zName in bytes */
1994 char *zFree = 0; /* Free this before returning */
1995 int nByte;
1997 memset(&e, 0, sizeof(e));
1998 p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx));
1999 if( p==0 ) return;
2001 /* Martial the arguments into stack variables */
2002 if( nVal!=2 && nVal!=4 && nVal!=5 ){
2003 zErr = sqlite3_mprintf("wrong number of arguments to function zipfile()");
2004 rc = SQLITE_ERROR;
2005 goto zipfile_step_out;
2007 pName = apVal[0];
2008 if( nVal==2 ){
2009 pData = apVal[1];
2010 }else{
2011 pMode = apVal[1];
2012 pMtime = apVal[2];
2013 pData = apVal[3];
2014 if( nVal==5 ){
2015 pMethod = apVal[4];
2019 /* Check that the 'name' parameter looks ok. */
2020 zName = (char*)sqlite3_value_text(pName);
2021 nName = sqlite3_value_bytes(pName);
2022 if( zName==0 ){
2023 zErr = sqlite3_mprintf("first argument to zipfile() must be non-NULL");
2024 rc = SQLITE_ERROR;
2025 goto zipfile_step_out;
2028 /* Inspect the 'method' parameter. This must be either 0 (store), 8 (use
2029 ** deflate compression) or NULL (choose automatically). */
2030 if( pMethod && SQLITE_NULL!=sqlite3_value_type(pMethod) ){
2031 iMethod = (int)sqlite3_value_int64(pMethod);
2032 if( iMethod!=0 && iMethod!=8 ){
2033 zErr = sqlite3_mprintf("illegal method value: %d", iMethod);
2034 rc = SQLITE_ERROR;
2035 goto zipfile_step_out;
2039 /* Now inspect the data. If this is NULL, then the new entry must be a
2040 ** directory. Otherwise, figure out whether or not the data should
2041 ** be deflated or simply stored in the zip archive. */
2042 if( sqlite3_value_type(pData)==SQLITE_NULL ){
2043 bIsDir = 1;
2044 iMethod = 0;
2045 }else{
2046 aData = sqlite3_value_blob(pData);
2047 szUncompressed = nData = sqlite3_value_bytes(pData);
2048 iCrc32 = crc32(0, aData, nData);
2049 if( iMethod<0 || iMethod==8 ){
2050 int nOut = 0;
2051 rc = zipfileDeflate(aData, nData, &aFree, &nOut, &zErr);
2052 if( rc!=SQLITE_OK ){
2053 goto zipfile_step_out;
2055 if( iMethod==8 || nOut<nData ){
2056 aData = aFree;
2057 nData = nOut;
2058 iMethod = 8;
2059 }else{
2060 iMethod = 0;
2065 /* Decode the "mode" argument. */
2066 rc = zipfileGetMode(pMode, bIsDir, &mode, &zErr);
2067 if( rc ) goto zipfile_step_out;
2069 /* Decode the "mtime" argument. */
2070 e.mUnixTime = zipfileGetTime(pMtime);
2072 /* If this is a directory entry, ensure that there is exactly one '/'
2073 ** at the end of the path. Or, if this is not a directory and the path
2074 ** ends in '/' it is an error. */
2075 if( bIsDir==0 ){
2076 if( nName>0 && zName[nName-1]=='/' ){
2077 zErr = sqlite3_mprintf("non-directory name must not end with /");
2078 rc = SQLITE_ERROR;
2079 goto zipfile_step_out;
2081 }else{
2082 if( nName==0 || zName[nName-1]!='/' ){
2083 zName = zFree = sqlite3_mprintf("%s/", zName);
2084 if( zName==0 ){
2085 rc = SQLITE_NOMEM;
2086 goto zipfile_step_out;
2088 nName = (int)strlen(zName);
2089 }else{
2090 while( nName>1 && zName[nName-2]=='/' ) nName--;
2094 /* Assemble the ZipfileEntry object for the new zip archive entry */
2095 e.cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY;
2096 e.cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED;
2097 e.cds.flags = ZIPFILE_NEWENTRY_FLAGS;
2098 e.cds.iCompression = (u16)iMethod;
2099 zipfileMtimeToDos(&e.cds, (u32)e.mUnixTime);
2100 e.cds.crc32 = iCrc32;
2101 e.cds.szCompressed = nData;
2102 e.cds.szUncompressed = szUncompressed;
2103 e.cds.iExternalAttr = (mode<<16);
2104 e.cds.iOffset = p->body.n;
2105 e.cds.nFile = (u16)nName;
2106 e.cds.zFile = zName;
2108 /* Append the LFH to the body of the new archive */
2109 nByte = ZIPFILE_LFH_FIXED_SZ + e.cds.nFile + 9;
2110 if( (rc = zipfileBufferGrow(&p->body, nByte)) ) goto zipfile_step_out;
2111 p->body.n += zipfileSerializeLFH(&e, &p->body.a[p->body.n]);
2113 /* Append the data to the body of the new archive */
2114 if( nData>0 ){
2115 if( (rc = zipfileBufferGrow(&p->body, nData)) ) goto zipfile_step_out;
2116 memcpy(&p->body.a[p->body.n], aData, nData);
2117 p->body.n += nData;
2120 /* Append the CDS record to the directory of the new archive */
2121 nByte = ZIPFILE_CDS_FIXED_SZ + e.cds.nFile + 9;
2122 if( (rc = zipfileBufferGrow(&p->cds, nByte)) ) goto zipfile_step_out;
2123 p->cds.n += zipfileSerializeCDS(&e, &p->cds.a[p->cds.n]);
2125 /* Increment the count of entries in the archive */
2126 p->nEntry++;
2128 zipfile_step_out:
2129 sqlite3_free(aFree);
2130 sqlite3_free(zFree);
2131 if( rc ){
2132 if( zErr ){
2133 sqlite3_result_error(pCtx, zErr, -1);
2134 }else{
2135 sqlite3_result_error_code(pCtx, rc);
2138 sqlite3_free(zErr);
2142 ** xFinalize() callback for zipfile aggregate function.
2144 static void zipfileFinal(sqlite3_context *pCtx){
2145 ZipfileCtx *p;
2146 ZipfileEOCD eocd;
2147 sqlite3_int64 nZip;
2148 u8 *aZip;
2150 p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx));
2151 if( p==0 ) return;
2152 if( p->nEntry>0 ){
2153 memset(&eocd, 0, sizeof(eocd));
2154 eocd.nEntry = (u16)p->nEntry;
2155 eocd.nEntryTotal = (u16)p->nEntry;
2156 eocd.nSize = p->cds.n;
2157 eocd.iOffset = p->body.n;
2159 nZip = p->body.n + p->cds.n + ZIPFILE_EOCD_FIXED_SZ;
2160 aZip = (u8*)sqlite3_malloc64(nZip);
2161 if( aZip==0 ){
2162 sqlite3_result_error_nomem(pCtx);
2163 }else{
2164 memcpy(aZip, p->body.a, p->body.n);
2165 memcpy(&aZip[p->body.n], p->cds.a, p->cds.n);
2166 zipfileSerializeEOCD(&eocd, &aZip[p->body.n + p->cds.n]);
2167 sqlite3_result_blob(pCtx, aZip, (int)nZip, zipfileFree);
2171 sqlite3_free(p->body.a);
2172 sqlite3_free(p->cds.a);
2177 ** Register the "zipfile" virtual table.
2179 static int zipfileRegister(sqlite3 *db){
2180 static sqlite3_module zipfileModule = {
2181 1, /* iVersion */
2182 zipfileConnect, /* xCreate */
2183 zipfileConnect, /* xConnect */
2184 zipfileBestIndex, /* xBestIndex */
2185 zipfileDisconnect, /* xDisconnect */
2186 zipfileDisconnect, /* xDestroy */
2187 zipfileOpen, /* xOpen - open a cursor */
2188 zipfileClose, /* xClose - close a cursor */
2189 zipfileFilter, /* xFilter - configure scan constraints */
2190 zipfileNext, /* xNext - advance a cursor */
2191 zipfileEof, /* xEof - check for end of scan */
2192 zipfileColumn, /* xColumn - read data */
2193 0, /* xRowid - read data */
2194 zipfileUpdate, /* xUpdate */
2195 zipfileBegin, /* xBegin */
2196 0, /* xSync */
2197 zipfileCommit, /* xCommit */
2198 zipfileRollback, /* xRollback */
2199 zipfileFindFunction, /* xFindMethod */
2200 0, /* xRename */
2201 0, /* xSavepoint */
2202 0, /* xRelease */
2203 0, /* xRollback */
2204 0, /* xShadowName */
2205 0 /* xIntegrity */
2208 int rc = sqlite3_create_module(db, "zipfile" , &zipfileModule, 0);
2209 if( rc==SQLITE_OK ) rc = sqlite3_overload_function(db, "zipfile_cds", -1);
2210 if( rc==SQLITE_OK ){
2211 rc = sqlite3_create_function(db, "zipfile", -1, SQLITE_UTF8, 0, 0,
2212 zipfileStep, zipfileFinal
2215 assert( sizeof(i64)==8 );
2216 assert( sizeof(u32)==4 );
2217 assert( sizeof(u16)==2 );
2218 assert( sizeof(u8)==1 );
2219 return rc;
2221 #else /* SQLITE_OMIT_VIRTUALTABLE */
2222 # define zipfileRegister(x) SQLITE_OK
2223 #endif
2225 #ifdef _WIN32
2226 __declspec(dllexport)
2227 #endif
2228 int sqlite3_zipfile_init(
2229 sqlite3 *db,
2230 char **pzErrMsg,
2231 const sqlite3_api_routines *pApi
2233 SQLITE_EXTENSION_INIT2(pApi);
2234 (void)pzErrMsg; /* Unused parameter */
2235 return zipfileRegister(db);