Enhance the command-line completion extension to return the names of
[sqlite.git] / ext / misc / zipfile.c
bloba685ae0622dd0ecff88433debc60d80cfffd196d
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>
33 #include <zlib.h>
35 #ifndef SQLITE_OMIT_VIRTUALTABLE
37 #ifndef SQLITE_AMALGAMATION
39 typedef sqlite3_int64 i64;
40 typedef unsigned char u8;
41 typedef unsigned short u16;
42 typedef unsigned long u32;
43 #define MIN(a,b) ((a)<(b) ? (a) : (b))
45 #if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
46 # define ALWAYS(X) (1)
47 # define NEVER(X) (0)
48 #elif !defined(NDEBUG)
49 # define ALWAYS(X) ((X)?1:(assert(0),0))
50 # define NEVER(X) ((X)?(assert(0),1):0)
51 #else
52 # define ALWAYS(X) (X)
53 # define NEVER(X) (X)
54 #endif
56 #endif /* SQLITE_AMALGAMATION */
59 ** Definitions for mode bitmasks S_IFDIR, S_IFREG and S_IFLNK.
61 ** In some ways it would be better to obtain these values from system
62 ** header files. But, the dependency is undesirable and (a) these
63 ** have been stable for decades, (b) the values are part of POSIX and
64 ** are also made explicit in [man stat], and (c) are part of the
65 ** file format for zip archives.
67 #ifndef S_IFDIR
68 # define S_IFDIR 0040000
69 #endif
70 #ifndef S_IFREG
71 # define S_IFREG 0100000
72 #endif
73 #ifndef S_IFLNK
74 # define S_IFLNK 0120000
75 #endif
77 static const char ZIPFILE_SCHEMA[] =
78 "CREATE TABLE y("
79 "name PRIMARY KEY," /* 0: Name of file in zip archive */
80 "mode," /* 1: POSIX mode for file */
81 "mtime," /* 2: Last modification time (secs since 1970)*/
82 "sz," /* 3: Size of object */
83 "rawdata," /* 4: Raw data */
84 "data," /* 5: Uncompressed data */
85 "method," /* 6: Compression method (integer) */
86 "z HIDDEN" /* 7: Name of zip file */
87 ") WITHOUT ROWID;";
89 #define ZIPFILE_F_COLUMN_IDX 7 /* Index of column "file" in the above */
90 #define ZIPFILE_BUFFER_SIZE (64*1024)
94 ** Magic numbers used to read and write zip files.
96 ** ZIPFILE_NEWENTRY_MADEBY:
97 ** Use this value for the "version-made-by" field in new zip file
98 ** entries. The upper byte indicates "unix", and the lower byte
99 ** indicates that the zip file matches pkzip specification 3.0.
100 ** This is what info-zip seems to do.
102 ** ZIPFILE_NEWENTRY_REQUIRED:
103 ** Value for "version-required-to-extract" field of new entries.
104 ** Version 2.0 is required to support folders and deflate compression.
106 ** ZIPFILE_NEWENTRY_FLAGS:
107 ** Value for "general-purpose-bit-flags" field of new entries. Bit
108 ** 11 means "utf-8 filename and comment".
110 ** ZIPFILE_SIGNATURE_CDS:
111 ** First 4 bytes of a valid CDS record.
113 ** ZIPFILE_SIGNATURE_LFH:
114 ** First 4 bytes of a valid LFH record.
116 ** ZIPFILE_SIGNATURE_EOCD
117 ** First 4 bytes of a valid EOCD record.
119 #define ZIPFILE_EXTRA_TIMESTAMP 0x5455
120 #define ZIPFILE_NEWENTRY_MADEBY ((3<<8) + 30)
121 #define ZIPFILE_NEWENTRY_REQUIRED 20
122 #define ZIPFILE_NEWENTRY_FLAGS 0x800
123 #define ZIPFILE_SIGNATURE_CDS 0x02014b50
124 #define ZIPFILE_SIGNATURE_LFH 0x04034b50
125 #define ZIPFILE_SIGNATURE_EOCD 0x06054b50
128 ** The sizes of the fixed-size part of each of the three main data
129 ** structures in a zip archive.
131 #define ZIPFILE_LFH_FIXED_SZ 30
132 #define ZIPFILE_EOCD_FIXED_SZ 22
133 #define ZIPFILE_CDS_FIXED_SZ 46
136 *** 4.3.16 End of central directory record:
138 *** end of central dir signature 4 bytes (0x06054b50)
139 *** number of this disk 2 bytes
140 *** number of the disk with the
141 *** start of the central directory 2 bytes
142 *** total number of entries in the
143 *** central directory on this disk 2 bytes
144 *** total number of entries in
145 *** the central directory 2 bytes
146 *** size of the central directory 4 bytes
147 *** offset of start of central
148 *** directory with respect to
149 *** the starting disk number 4 bytes
150 *** .ZIP file comment length 2 bytes
151 *** .ZIP file comment (variable size)
153 typedef struct ZipfileEOCD ZipfileEOCD;
154 struct ZipfileEOCD {
155 u16 iDisk;
156 u16 iFirstDisk;
157 u16 nEntry;
158 u16 nEntryTotal;
159 u32 nSize;
160 u32 iOffset;
164 *** 4.3.12 Central directory structure:
166 *** ...
168 *** central file header signature 4 bytes (0x02014b50)
169 *** version made by 2 bytes
170 *** version needed to extract 2 bytes
171 *** general purpose bit flag 2 bytes
172 *** compression method 2 bytes
173 *** last mod file time 2 bytes
174 *** last mod file date 2 bytes
175 *** crc-32 4 bytes
176 *** compressed size 4 bytes
177 *** uncompressed size 4 bytes
178 *** file name length 2 bytes
179 *** extra field length 2 bytes
180 *** file comment length 2 bytes
181 *** disk number start 2 bytes
182 *** internal file attributes 2 bytes
183 *** external file attributes 4 bytes
184 *** relative offset of local header 4 bytes
186 typedef struct ZipfileCDS ZipfileCDS;
187 struct ZipfileCDS {
188 u16 iVersionMadeBy;
189 u16 iVersionExtract;
190 u16 flags;
191 u16 iCompression;
192 u16 mTime;
193 u16 mDate;
194 u32 crc32;
195 u32 szCompressed;
196 u32 szUncompressed;
197 u16 nFile;
198 u16 nExtra;
199 u16 nComment;
200 u16 iDiskStart;
201 u16 iInternalAttr;
202 u32 iExternalAttr;
203 u32 iOffset;
204 char *zFile; /* Filename (sqlite3_malloc()) */
208 *** 4.3.7 Local file header:
210 *** local file header signature 4 bytes (0x04034b50)
211 *** version needed to extract 2 bytes
212 *** general purpose bit flag 2 bytes
213 *** compression method 2 bytes
214 *** last mod file time 2 bytes
215 *** last mod file date 2 bytes
216 *** crc-32 4 bytes
217 *** compressed size 4 bytes
218 *** uncompressed size 4 bytes
219 *** file name length 2 bytes
220 *** extra field length 2 bytes
221 ***
223 typedef struct ZipfileLFH ZipfileLFH;
224 struct ZipfileLFH {
225 u16 iVersionExtract;
226 u16 flags;
227 u16 iCompression;
228 u16 mTime;
229 u16 mDate;
230 u32 crc32;
231 u32 szCompressed;
232 u32 szUncompressed;
233 u16 nFile;
234 u16 nExtra;
237 typedef struct ZipfileEntry ZipfileEntry;
238 struct ZipfileEntry {
239 ZipfileCDS cds; /* Parsed CDS record */
240 u32 mUnixTime; /* Modification time, in UNIX format */
241 u8 *aExtra; /* cds.nExtra+cds.nComment bytes of extra data */
242 i64 iDataOff; /* Offset to data in file (if aData==0) */
243 u8 *aData; /* cds.szCompressed bytes of compressed data */
244 ZipfileEntry *pNext; /* Next element in in-memory CDS */
248 ** Cursor type for zipfile tables.
250 typedef struct ZipfileCsr ZipfileCsr;
251 struct ZipfileCsr {
252 sqlite3_vtab_cursor base; /* Base class - must be first */
253 i64 iId; /* Cursor ID */
254 u8 bEof; /* True when at EOF */
255 u8 bNoop; /* If next xNext() call is no-op */
257 /* Used outside of write transactions */
258 FILE *pFile; /* Zip file */
259 i64 iNextOff; /* Offset of next record in central directory */
260 ZipfileEOCD eocd; /* Parse of central directory record */
262 ZipfileEntry *pFreeEntry; /* Free this list when cursor is closed or reset */
263 ZipfileEntry *pCurrent; /* Current entry */
264 ZipfileCsr *pCsrNext; /* Next cursor on same virtual table */
267 typedef struct ZipfileTab ZipfileTab;
268 struct ZipfileTab {
269 sqlite3_vtab base; /* Base class - must be first */
270 char *zFile; /* Zip file this table accesses (may be NULL) */
271 sqlite3 *db; /* Host database connection */
272 u8 *aBuffer; /* Temporary buffer used for various tasks */
274 ZipfileCsr *pCsrList; /* List of cursors */
275 i64 iNextCsrid;
277 /* The following are used by write transactions only */
278 ZipfileEntry *pFirstEntry; /* Linked list of all files (if pWriteFd!=0) */
279 ZipfileEntry *pLastEntry; /* Last element in pFirstEntry list */
280 FILE *pWriteFd; /* File handle open on zip archive */
281 i64 szCurrent; /* Current size of zip archive */
282 i64 szOrig; /* Size of archive at start of transaction */
286 ** Set the error message contained in context ctx to the results of
287 ** vprintf(zFmt, ...).
289 static void zipfileCtxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){
290 char *zMsg = 0;
291 va_list ap;
292 va_start(ap, zFmt);
293 zMsg = sqlite3_vmprintf(zFmt, ap);
294 sqlite3_result_error(ctx, zMsg, -1);
295 sqlite3_free(zMsg);
296 va_end(ap);
300 ** If string zIn is quoted, dequote it in place. Otherwise, if the string
301 ** is not quoted, do nothing.
303 static void zipfileDequote(char *zIn){
304 char q = zIn[0];
305 if( q=='"' || q=='\'' || q=='`' || q=='[' ){
306 int iIn = 1;
307 int iOut = 0;
308 if( q=='[' ) q = ']';
309 while( ALWAYS(zIn[iIn]) ){
310 char c = zIn[iIn++];
311 if( c==q && zIn[iIn++]!=q ) break;
312 zIn[iOut++] = c;
314 zIn[iOut] = '\0';
319 ** Construct a new ZipfileTab virtual table object.
321 ** argv[0] -> module name ("zipfile")
322 ** argv[1] -> database name
323 ** argv[2] -> table name
324 ** argv[...] -> "column name" and other module argument fields.
326 static int zipfileConnect(
327 sqlite3 *db,
328 void *pAux,
329 int argc, const char *const*argv,
330 sqlite3_vtab **ppVtab,
331 char **pzErr
333 int nByte = sizeof(ZipfileTab) + ZIPFILE_BUFFER_SIZE;
334 int nFile = 0;
335 const char *zFile = 0;
336 ZipfileTab *pNew = 0;
337 int rc;
339 /* If the table name is not "zipfile", require that the argument be
340 ** specified. This stops zipfile tables from being created as:
342 ** CREATE VIRTUAL TABLE zzz USING zipfile();
344 ** It does not prevent:
346 ** CREATE VIRTUAL TABLE zipfile USING zipfile();
348 assert( 0==sqlite3_stricmp(argv[0], "zipfile") );
349 if( (0!=sqlite3_stricmp(argv[2], "zipfile") && argc<4) || argc>4 ){
350 *pzErr = sqlite3_mprintf("zipfile constructor requires one argument");
351 return SQLITE_ERROR;
354 if( argc>3 ){
355 zFile = argv[3];
356 nFile = (int)strlen(zFile)+1;
359 rc = sqlite3_declare_vtab(db, ZIPFILE_SCHEMA);
360 if( rc==SQLITE_OK ){
361 pNew = (ZipfileTab*)sqlite3_malloc(nByte+nFile);
362 if( pNew==0 ) return SQLITE_NOMEM;
363 memset(pNew, 0, nByte+nFile);
364 pNew->db = db;
365 pNew->aBuffer = (u8*)&pNew[1];
366 if( zFile ){
367 pNew->zFile = (char*)&pNew->aBuffer[ZIPFILE_BUFFER_SIZE];
368 memcpy(pNew->zFile, zFile, nFile);
369 zipfileDequote(pNew->zFile);
372 *ppVtab = (sqlite3_vtab*)pNew;
373 return rc;
377 ** Free the ZipfileEntry structure indicated by the only argument.
379 static void zipfileEntryFree(ZipfileEntry *p){
380 if( p ){
381 sqlite3_free(p->cds.zFile);
382 sqlite3_free(p);
387 ** Release resources that should be freed at the end of a write
388 ** transaction.
390 static void zipfileCleanupTransaction(ZipfileTab *pTab){
391 ZipfileEntry *pEntry;
392 ZipfileEntry *pNext;
394 if( pTab->pWriteFd ){
395 fclose(pTab->pWriteFd);
396 pTab->pWriteFd = 0;
398 for(pEntry=pTab->pFirstEntry; pEntry; pEntry=pNext){
399 pNext = pEntry->pNext;
400 zipfileEntryFree(pEntry);
402 pTab->pFirstEntry = 0;
403 pTab->pLastEntry = 0;
404 pTab->szCurrent = 0;
405 pTab->szOrig = 0;
409 ** This method is the destructor for zipfile vtab objects.
411 static int zipfileDisconnect(sqlite3_vtab *pVtab){
412 zipfileCleanupTransaction((ZipfileTab*)pVtab);
413 sqlite3_free(pVtab);
414 return SQLITE_OK;
418 ** Constructor for a new ZipfileCsr object.
420 static int zipfileOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCsr){
421 ZipfileTab *pTab = (ZipfileTab*)p;
422 ZipfileCsr *pCsr;
423 pCsr = sqlite3_malloc(sizeof(*pCsr));
424 *ppCsr = (sqlite3_vtab_cursor*)pCsr;
425 if( pCsr==0 ){
426 return SQLITE_NOMEM;
428 memset(pCsr, 0, sizeof(*pCsr));
429 pCsr->iId = ++pTab->iNextCsrid;
430 pCsr->pCsrNext = pTab->pCsrList;
431 pTab->pCsrList = pCsr;
432 return SQLITE_OK;
436 ** Reset a cursor back to the state it was in when first returned
437 ** by zipfileOpen().
439 static void zipfileResetCursor(ZipfileCsr *pCsr){
440 ZipfileEntry *p;
441 ZipfileEntry *pNext;
443 pCsr->bEof = 0;
444 if( pCsr->pFile ){
445 fclose(pCsr->pFile);
446 pCsr->pFile = 0;
447 zipfileEntryFree(pCsr->pCurrent);
448 pCsr->pCurrent = 0;
451 for(p=pCsr->pFreeEntry; p; p=pNext){
452 pNext = p->pNext;
453 zipfileEntryFree(p);
458 ** Destructor for an ZipfileCsr.
460 static int zipfileClose(sqlite3_vtab_cursor *cur){
461 ZipfileCsr *pCsr = (ZipfileCsr*)cur;
462 ZipfileTab *pTab = (ZipfileTab*)(pCsr->base.pVtab);
463 ZipfileCsr **pp;
464 zipfileResetCursor(pCsr);
466 /* Remove this cursor from the ZipfileTab.pCsrList list. */
467 for(pp=&pTab->pCsrList; *pp!=pCsr; pp=&((*pp)->pCsrNext));
468 *pp = pCsr->pCsrNext;
470 sqlite3_free(pCsr);
471 return SQLITE_OK;
475 ** Set the error message for the virtual table associated with cursor
476 ** pCsr to the results of vprintf(zFmt, ...).
478 static void zipfileTableErr(ZipfileTab *pTab, const char *zFmt, ...){
479 va_list ap;
480 va_start(ap, zFmt);
481 sqlite3_free(pTab->base.zErrMsg);
482 pTab->base.zErrMsg = sqlite3_vmprintf(zFmt, ap);
483 va_end(ap);
485 static void zipfileCursorErr(ZipfileCsr *pCsr, const char *zFmt, ...){
486 va_list ap;
487 va_start(ap, zFmt);
488 sqlite3_free(pCsr->base.pVtab->zErrMsg);
489 pCsr->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap);
490 va_end(ap);
494 ** Read nRead bytes of data from offset iOff of file pFile into buffer
495 ** aRead[]. Return SQLITE_OK if successful, or an SQLite error code
496 ** otherwise.
498 ** If an error does occur, output variable (*pzErrmsg) may be set to point
499 ** to an English language error message. It is the responsibility of the
500 ** caller to eventually free this buffer using
501 ** sqlite3_free().
503 static int zipfileReadData(
504 FILE *pFile, /* Read from this file */
505 u8 *aRead, /* Read into this buffer */
506 int nRead, /* Number of bytes to read */
507 i64 iOff, /* Offset to read from */
508 char **pzErrmsg /* OUT: Error message (from sqlite3_malloc) */
510 size_t n;
511 fseek(pFile, (long)iOff, SEEK_SET);
512 n = fread(aRead, 1, nRead, pFile);
513 if( (int)n!=nRead ){
514 *pzErrmsg = sqlite3_mprintf("error in fread()");
515 return SQLITE_ERROR;
517 return SQLITE_OK;
520 static int zipfileAppendData(
521 ZipfileTab *pTab,
522 const u8 *aWrite,
523 int nWrite
525 size_t n;
526 fseek(pTab->pWriteFd, (long)pTab->szCurrent, SEEK_SET);
527 n = fwrite(aWrite, 1, nWrite, pTab->pWriteFd);
528 if( (int)n!=nWrite ){
529 pTab->base.zErrMsg = sqlite3_mprintf("error in fwrite()");
530 return SQLITE_ERROR;
532 pTab->szCurrent += nWrite;
533 return SQLITE_OK;
537 ** Read and return a 16-bit little-endian unsigned integer from buffer aBuf.
539 static u16 zipfileGetU16(const u8 *aBuf){
540 return (aBuf[1] << 8) + aBuf[0];
544 ** Read and return a 32-bit little-endian unsigned integer from buffer aBuf.
546 static u32 zipfileGetU32(const u8 *aBuf){
547 return ((u32)(aBuf[3]) << 24)
548 + ((u32)(aBuf[2]) << 16)
549 + ((u32)(aBuf[1]) << 8)
550 + ((u32)(aBuf[0]) << 0);
554 ** Write a 16-bit little endiate integer into buffer aBuf.
556 static void zipfilePutU16(u8 *aBuf, u16 val){
557 aBuf[0] = val & 0xFF;
558 aBuf[1] = (val>>8) & 0xFF;
562 ** Write a 32-bit little endiate integer into buffer aBuf.
564 static void zipfilePutU32(u8 *aBuf, u32 val){
565 aBuf[0] = val & 0xFF;
566 aBuf[1] = (val>>8) & 0xFF;
567 aBuf[2] = (val>>16) & 0xFF;
568 aBuf[3] = (val>>24) & 0xFF;
571 #define zipfileRead32(aBuf) ( aBuf+=4, zipfileGetU32(aBuf-4) )
572 #define zipfileRead16(aBuf) ( aBuf+=2, zipfileGetU16(aBuf-2) )
574 #define zipfileWrite32(aBuf,val) { zipfilePutU32(aBuf,val); aBuf+=4; }
575 #define zipfileWrite16(aBuf,val) { zipfilePutU16(aBuf,val); aBuf+=2; }
578 ** Magic numbers used to read CDS records.
580 #define ZIPFILE_CDS_NFILE_OFF 28
581 #define ZIPFILE_CDS_SZCOMPRESSED_OFF 20
584 ** Decode the CDS record in buffer aBuf into (*pCDS). Return SQLITE_ERROR
585 ** if the record is not well-formed, or SQLITE_OK otherwise.
587 static int zipfileReadCDS(u8 *aBuf, ZipfileCDS *pCDS){
588 u8 *aRead = aBuf;
589 u32 sig = zipfileRead32(aRead);
590 int rc = SQLITE_OK;
591 if( sig!=ZIPFILE_SIGNATURE_CDS ){
592 rc = SQLITE_ERROR;
593 }else{
594 pCDS->iVersionMadeBy = zipfileRead16(aRead);
595 pCDS->iVersionExtract = zipfileRead16(aRead);
596 pCDS->flags = zipfileRead16(aRead);
597 pCDS->iCompression = zipfileRead16(aRead);
598 pCDS->mTime = zipfileRead16(aRead);
599 pCDS->mDate = zipfileRead16(aRead);
600 pCDS->crc32 = zipfileRead32(aRead);
601 pCDS->szCompressed = zipfileRead32(aRead);
602 pCDS->szUncompressed = zipfileRead32(aRead);
603 assert( aRead==&aBuf[ZIPFILE_CDS_NFILE_OFF] );
604 pCDS->nFile = zipfileRead16(aRead);
605 pCDS->nExtra = zipfileRead16(aRead);
606 pCDS->nComment = zipfileRead16(aRead);
607 pCDS->iDiskStart = zipfileRead16(aRead);
608 pCDS->iInternalAttr = zipfileRead16(aRead);
609 pCDS->iExternalAttr = zipfileRead32(aRead);
610 pCDS->iOffset = zipfileRead32(aRead);
611 assert( aRead==&aBuf[ZIPFILE_CDS_FIXED_SZ] );
614 return rc;
618 ** Decode the LFH record in buffer aBuf into (*pLFH). Return SQLITE_ERROR
619 ** if the record is not well-formed, or SQLITE_OK otherwise.
621 static int zipfileReadLFH(
622 u8 *aBuffer,
623 ZipfileLFH *pLFH
625 u8 *aRead = aBuffer;
626 int rc = SQLITE_OK;
628 u32 sig = zipfileRead32(aRead);
629 if( sig!=ZIPFILE_SIGNATURE_LFH ){
630 rc = SQLITE_ERROR;
631 }else{
632 pLFH->iVersionExtract = zipfileRead16(aRead);
633 pLFH->flags = zipfileRead16(aRead);
634 pLFH->iCompression = zipfileRead16(aRead);
635 pLFH->mTime = zipfileRead16(aRead);
636 pLFH->mDate = zipfileRead16(aRead);
637 pLFH->crc32 = zipfileRead32(aRead);
638 pLFH->szCompressed = zipfileRead32(aRead);
639 pLFH->szUncompressed = zipfileRead32(aRead);
640 pLFH->nFile = zipfileRead16(aRead);
641 pLFH->nExtra = zipfileRead16(aRead);
643 return rc;
648 ** Buffer aExtra (size nExtra bytes) contains zip archive "extra" fields.
649 ** Scan through this buffer to find an "extra-timestamp" field. If one
650 ** exists, extract the 32-bit modification-timestamp from it and store
651 ** the value in output parameter *pmTime.
653 ** Zero is returned if no extra-timestamp record could be found (and so
654 ** *pmTime is left unchanged), or non-zero otherwise.
656 ** The general format of an extra field is:
658 ** Header ID 2 bytes
659 ** Data Size 2 bytes
660 ** Data N bytes
662 static int zipfileScanExtra(u8 *aExtra, int nExtra, u32 *pmTime){
663 int ret = 0;
664 u8 *p = aExtra;
665 u8 *pEnd = &aExtra[nExtra];
667 while( p<pEnd ){
668 u16 id = zipfileRead16(p);
669 u16 nByte = zipfileRead16(p);
671 switch( id ){
672 case ZIPFILE_EXTRA_TIMESTAMP: {
673 u8 b = p[0];
674 if( b & 0x01 ){ /* 0x01 -> modtime is present */
675 *pmTime = zipfileGetU32(&p[1]);
676 ret = 1;
678 break;
682 p += nByte;
684 return ret;
688 ** Convert the standard MS-DOS timestamp stored in the mTime and mDate
689 ** fields of the CDS structure passed as the only argument to a 32-bit
690 ** UNIX seconds-since-the-epoch timestamp. Return the result.
692 ** "Standard" MS-DOS time format:
694 ** File modification time:
695 ** Bits 00-04: seconds divided by 2
696 ** Bits 05-10: minute
697 ** Bits 11-15: hour
698 ** File modification date:
699 ** Bits 00-04: day
700 ** Bits 05-08: month (1-12)
701 ** Bits 09-15: years from 1980
703 ** https://msdn.microsoft.com/en-us/library/9kkf9tah.aspx
705 static u32 zipfileMtime(ZipfileCDS *pCDS){
706 int Y = (1980 + ((pCDS->mDate >> 9) & 0x7F));
707 int M = ((pCDS->mDate >> 5) & 0x0F);
708 int D = (pCDS->mDate & 0x1F);
709 int B = -13;
711 int sec = (pCDS->mTime & 0x1F)*2;
712 int min = (pCDS->mTime >> 5) & 0x3F;
713 int hr = (pCDS->mTime >> 11) & 0x1F;
714 i64 JD;
716 /* JD = INT(365.25 * (Y+4716)) + INT(30.6001 * (M+1)) + D + B - 1524.5 */
718 /* Calculate the JD in seconds for noon on the day in question */
719 if( M<3 ){
720 Y = Y-1;
721 M = M+12;
723 JD = (i64)(24*60*60) * (
724 (int)(365.25 * (Y + 4716))
725 + (int)(30.6001 * (M + 1))
726 + D + B - 1524
729 /* Correct the JD for the time within the day */
730 JD += (hr-12) * 3600 + min * 60 + sec;
732 /* Convert JD to unix timestamp (the JD epoch is 2440587.5) */
733 return (u32)(JD - (i64)(24405875) * 24*60*6);
737 ** The opposite of zipfileMtime(). This function populates the mTime and
738 ** mDate fields of the CDS structure passed as the first argument according
739 ** to the UNIX timestamp value passed as the second.
741 static void zipfileMtimeToDos(ZipfileCDS *pCds, u32 mUnixTime){
742 /* Convert unix timestamp to JD (2440588 is noon on 1/1/1970) */
743 i64 JD = (i64)2440588 + mUnixTime / (24*60*60);
745 int A, B, C, D, E;
746 int yr, mon, day;
747 int hr, min, sec;
749 A = (int)((JD - 1867216.25)/36524.25);
750 A = (int)(JD + 1 + A - (A/4));
751 B = A + 1524;
752 C = (int)((B - 122.1)/365.25);
753 D = (36525*(C&32767))/100;
754 E = (int)((B-D)/30.6001);
756 day = B - D - (int)(30.6001*E);
757 mon = (E<14 ? E-1 : E-13);
758 yr = mon>2 ? C-4716 : C-4715;
760 hr = (mUnixTime % (24*60*60)) / (60*60);
761 min = (mUnixTime % (60*60)) / 60;
762 sec = (mUnixTime % 60);
764 if( yr>=1980 ){
765 pCds->mDate = (u16)(day + (mon << 5) + ((yr-1980) << 9));
766 pCds->mTime = (u16)(sec/2 + (min<<5) + (hr<<11));
767 }else{
768 pCds->mDate = pCds->mTime = 0;
771 assert( mUnixTime<315507600
772 || mUnixTime==zipfileMtime(pCds)
773 || ((mUnixTime % 2) && mUnixTime-1==zipfileMtime(pCds))
774 /* || (mUnixTime % 2) */
779 ** If aBlob is not NULL, then it is a pointer to a buffer (nBlob bytes in
780 ** size) containing an entire zip archive image. Or, if aBlob is NULL,
781 ** then pFile is a file-handle open on a zip file. In either case, this
782 ** function creates a ZipfileEntry object based on the zip archive entry
783 ** for which the CDS record is at offset iOff.
785 ** If successful, SQLITE_OK is returned and (*ppEntry) set to point to
786 ** the new object. Otherwise, an SQLite error code is returned and the
787 ** final value of (*ppEntry) undefined.
789 static int zipfileGetEntry(
790 ZipfileTab *pTab, /* Store any error message here */
791 const u8 *aBlob, /* Pointer to in-memory file image */
792 int nBlob, /* Size of aBlob[] in bytes */
793 FILE *pFile, /* If aBlob==0, read from this file */
794 i64 iOff, /* Offset of CDS record */
795 ZipfileEntry **ppEntry /* OUT: Pointer to new object */
797 u8 *aRead;
798 char **pzErr = &pTab->base.zErrMsg;
799 int rc = SQLITE_OK;
801 if( aBlob==0 ){
802 aRead = pTab->aBuffer;
803 rc = zipfileReadData(pFile, aRead, ZIPFILE_CDS_FIXED_SZ, iOff, pzErr);
804 }else{
805 aRead = (u8*)&aBlob[iOff];
808 if( rc==SQLITE_OK ){
809 int nAlloc;
810 ZipfileEntry *pNew;
812 int nFile = zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF]);
813 int nExtra = zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF+2]);
814 nExtra += zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF+4]);
816 nAlloc = sizeof(ZipfileEntry) + nExtra;
817 if( aBlob ){
818 nAlloc += zipfileGetU32(&aRead[ZIPFILE_CDS_SZCOMPRESSED_OFF]);
821 pNew = (ZipfileEntry*)sqlite3_malloc(nAlloc);
822 if( pNew==0 ){
823 rc = SQLITE_NOMEM;
824 }else{
825 memset(pNew, 0, sizeof(ZipfileEntry));
826 rc = zipfileReadCDS(aRead, &pNew->cds);
827 if( rc!=SQLITE_OK ){
828 *pzErr = sqlite3_mprintf("failed to read CDS at offset %lld", iOff);
829 }else if( aBlob==0 ){
830 rc = zipfileReadData(
831 pFile, aRead, nExtra+nFile, iOff+ZIPFILE_CDS_FIXED_SZ, pzErr
833 }else{
834 aRead = (u8*)&aBlob[iOff + ZIPFILE_CDS_FIXED_SZ];
838 if( rc==SQLITE_OK ){
839 u32 *pt = &pNew->mUnixTime;
840 pNew->cds.zFile = sqlite3_mprintf("%.*s", nFile, aRead);
841 pNew->aExtra = (u8*)&pNew[1];
842 memcpy(pNew->aExtra, &aRead[nFile], nExtra);
843 if( pNew->cds.zFile==0 ){
844 rc = SQLITE_NOMEM;
845 }else if( 0==zipfileScanExtra(&aRead[nFile], pNew->cds.nExtra, pt) ){
846 pNew->mUnixTime = zipfileMtime(&pNew->cds);
850 if( rc==SQLITE_OK ){
851 static const int szFix = ZIPFILE_LFH_FIXED_SZ;
852 ZipfileLFH lfh;
853 if( pFile ){
854 rc = zipfileReadData(pFile, aRead, szFix, pNew->cds.iOffset, pzErr);
855 }else{
856 aRead = (u8*)&aBlob[pNew->cds.iOffset];
859 rc = zipfileReadLFH(aRead, &lfh);
860 if( rc==SQLITE_OK ){
861 pNew->iDataOff = pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ;
862 pNew->iDataOff += lfh.nFile + lfh.nExtra;
863 if( aBlob && pNew->cds.szCompressed ){
864 pNew->aData = &pNew->aExtra[nExtra];
865 memcpy(pNew->aData, &aBlob[pNew->iDataOff], pNew->cds.szCompressed);
867 }else{
868 *pzErr = sqlite3_mprintf("failed to read LFH at offset %d",
869 (int)pNew->cds.iOffset
874 if( rc!=SQLITE_OK ){
875 zipfileEntryFree(pNew);
876 }else{
877 *ppEntry = pNew;
881 return rc;
885 ** Advance an ZipfileCsr to its next row of output.
887 static int zipfileNext(sqlite3_vtab_cursor *cur){
888 ZipfileCsr *pCsr = (ZipfileCsr*)cur;
889 int rc = SQLITE_OK;
891 if( pCsr->pFile ){
892 i64 iEof = pCsr->eocd.iOffset + pCsr->eocd.nSize;
893 zipfileEntryFree(pCsr->pCurrent);
894 pCsr->pCurrent = 0;
895 if( pCsr->iNextOff>=iEof ){
896 pCsr->bEof = 1;
897 }else{
898 ZipfileEntry *p = 0;
899 ZipfileTab *pTab = (ZipfileTab*)(cur->pVtab);
900 rc = zipfileGetEntry(pTab, 0, 0, pCsr->pFile, pCsr->iNextOff, &p);
901 if( rc==SQLITE_OK ){
902 pCsr->iNextOff += ZIPFILE_CDS_FIXED_SZ;
903 pCsr->iNextOff += (int)p->cds.nExtra + p->cds.nFile + p->cds.nComment;
905 pCsr->pCurrent = p;
907 }else{
908 if( !pCsr->bNoop ){
909 pCsr->pCurrent = pCsr->pCurrent->pNext;
911 if( pCsr->pCurrent==0 ){
912 pCsr->bEof = 1;
916 pCsr->bNoop = 0;
917 return rc;
920 static void zipfileFree(void *p) {
921 sqlite3_free(p);
925 ** Buffer aIn (size nIn bytes) contains compressed data. Uncompressed, the
926 ** size is nOut bytes. This function uncompresses the data and sets the
927 ** return value in context pCtx to the result (a blob).
929 ** If an error occurs, an error code is left in pCtx instead.
931 static void zipfileInflate(
932 sqlite3_context *pCtx, /* Store result here */
933 const u8 *aIn, /* Compressed data */
934 int nIn, /* Size of buffer aIn[] in bytes */
935 int nOut /* Expected output size */
937 u8 *aRes = sqlite3_malloc(nOut);
938 if( aRes==0 ){
939 sqlite3_result_error_nomem(pCtx);
940 }else{
941 int err;
942 z_stream str;
943 memset(&str, 0, sizeof(str));
945 str.next_in = (Byte*)aIn;
946 str.avail_in = nIn;
947 str.next_out = (Byte*)aRes;
948 str.avail_out = nOut;
950 err = inflateInit2(&str, -15);
951 if( err!=Z_OK ){
952 zipfileCtxErrorMsg(pCtx, "inflateInit2() failed (%d)", err);
953 }else{
954 err = inflate(&str, Z_NO_FLUSH);
955 if( err!=Z_STREAM_END ){
956 zipfileCtxErrorMsg(pCtx, "inflate() failed (%d)", err);
957 }else{
958 sqlite3_result_blob(pCtx, aRes, nOut, zipfileFree);
959 aRes = 0;
962 sqlite3_free(aRes);
963 inflateEnd(&str);
968 ** Buffer aIn (size nIn bytes) contains uncompressed data. This function
969 ** compresses it and sets (*ppOut) to point to a buffer containing the
970 ** compressed data. The caller is responsible for eventually calling
971 ** sqlite3_free() to release buffer (*ppOut). Before returning, (*pnOut)
972 ** is set to the size of buffer (*ppOut) in bytes.
974 ** If no error occurs, SQLITE_OK is returned. Otherwise, an SQLite error
975 ** code is returned and an error message left in virtual-table handle
976 ** pTab. The values of (*ppOut) and (*pnOut) are left unchanged in this
977 ** case.
979 static int zipfileDeflate(
980 const u8 *aIn, int nIn, /* Input */
981 u8 **ppOut, int *pnOut, /* Output */
982 char **pzErr /* OUT: Error message */
984 int nAlloc = (int)compressBound(nIn);
985 u8 *aOut;
986 int rc = SQLITE_OK;
988 aOut = (u8*)sqlite3_malloc(nAlloc);
989 if( aOut==0 ){
990 rc = SQLITE_NOMEM;
991 }else{
992 int res;
993 z_stream str;
994 memset(&str, 0, sizeof(str));
995 str.next_in = (Bytef*)aIn;
996 str.avail_in = nIn;
997 str.next_out = aOut;
998 str.avail_out = nAlloc;
1000 deflateInit2(&str, 9, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
1001 res = deflate(&str, Z_FINISH);
1003 if( res==Z_STREAM_END ){
1004 *ppOut = aOut;
1005 *pnOut = (int)str.total_out;
1006 }else{
1007 sqlite3_free(aOut);
1008 *pzErr = sqlite3_mprintf("zipfile: deflate() error");
1009 rc = SQLITE_ERROR;
1011 deflateEnd(&str);
1014 return rc;
1019 ** Return values of columns for the row at which the series_cursor
1020 ** is currently pointing.
1022 static int zipfileColumn(
1023 sqlite3_vtab_cursor *cur, /* The cursor */
1024 sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
1025 int i /* Which column to return */
1027 ZipfileCsr *pCsr = (ZipfileCsr*)cur;
1028 ZipfileCDS *pCDS = &pCsr->pCurrent->cds;
1029 int rc = SQLITE_OK;
1030 switch( i ){
1031 case 0: /* name */
1032 sqlite3_result_text(ctx, pCDS->zFile, -1, SQLITE_TRANSIENT);
1033 break;
1034 case 1: /* mode */
1035 /* TODO: Whether or not the following is correct surely depends on
1036 ** the platform on which the archive was created. */
1037 sqlite3_result_int(ctx, pCDS->iExternalAttr >> 16);
1038 break;
1039 case 2: { /* mtime */
1040 sqlite3_result_int64(ctx, pCsr->pCurrent->mUnixTime);
1041 break;
1043 case 3: { /* sz */
1044 if( sqlite3_vtab_nochange(ctx)==0 ){
1045 sqlite3_result_int64(ctx, pCDS->szUncompressed);
1047 break;
1049 case 4: /* rawdata */
1050 if( sqlite3_vtab_nochange(ctx) ) break;
1051 case 5: { /* data */
1052 if( i==4 || pCDS->iCompression==0 || pCDS->iCompression==8 ){
1053 int sz = pCDS->szCompressed;
1054 int szFinal = pCDS->szUncompressed;
1055 if( szFinal>0 ){
1056 u8 *aBuf;
1057 u8 *aFree = 0;
1058 if( pCsr->pCurrent->aData ){
1059 aBuf = pCsr->pCurrent->aData;
1060 }else{
1061 aBuf = aFree = sqlite3_malloc(sz);
1062 if( aBuf==0 ){
1063 rc = SQLITE_NOMEM;
1064 }else{
1065 FILE *pFile = pCsr->pFile;
1066 if( pFile==0 ){
1067 pFile = ((ZipfileTab*)(pCsr->base.pVtab))->pWriteFd;
1069 rc = zipfileReadData(pFile, aBuf, sz, pCsr->pCurrent->iDataOff,
1070 &pCsr->base.pVtab->zErrMsg
1074 if( rc==SQLITE_OK ){
1075 if( i==5 && pCDS->iCompression ){
1076 zipfileInflate(ctx, aBuf, sz, szFinal);
1077 }else{
1078 sqlite3_result_blob(ctx, aBuf, sz, SQLITE_TRANSIENT);
1081 sqlite3_free(aFree);
1082 }else{
1083 /* Figure out if this is a directory or a zero-sized file. Consider
1084 ** it to be a directory either if the mode suggests so, or if
1085 ** the final character in the name is '/'. */
1086 u32 mode = pCDS->iExternalAttr >> 16;
1087 if( !(mode & S_IFDIR) && pCDS->zFile[pCDS->nFile-1]!='/' ){
1088 sqlite3_result_blob(ctx, "", 0, SQLITE_STATIC);
1092 break;
1094 case 6: /* method */
1095 sqlite3_result_int(ctx, pCDS->iCompression);
1096 break;
1097 default: /* z */
1098 assert( i==7 );
1099 sqlite3_result_int64(ctx, pCsr->iId);
1100 break;
1103 return rc;
1107 ** Return TRUE if the cursor is at EOF.
1109 static int zipfileEof(sqlite3_vtab_cursor *cur){
1110 ZipfileCsr *pCsr = (ZipfileCsr*)cur;
1111 return pCsr->bEof;
1115 ** If aBlob is not NULL, then it points to a buffer nBlob bytes in size
1116 ** containing an entire zip archive image. Or, if aBlob is NULL, then pFile
1117 ** is guaranteed to be a file-handle open on a zip file.
1119 ** This function attempts to locate the EOCD record within the zip archive
1120 ** and populate *pEOCD with the results of decoding it. SQLITE_OK is
1121 ** returned if successful. Otherwise, an SQLite error code is returned and
1122 ** an English language error message may be left in virtual-table pTab.
1124 static int zipfileReadEOCD(
1125 ZipfileTab *pTab, /* Return errors here */
1126 const u8 *aBlob, /* Pointer to in-memory file image */
1127 int nBlob, /* Size of aBlob[] in bytes */
1128 FILE *pFile, /* Read from this file if aBlob==0 */
1129 ZipfileEOCD *pEOCD /* Object to populate */
1131 u8 *aRead = pTab->aBuffer; /* Temporary buffer */
1132 int nRead; /* Bytes to read from file */
1133 int rc = SQLITE_OK;
1135 if( aBlob==0 ){
1136 i64 iOff; /* Offset to read from */
1137 i64 szFile; /* Total size of file in bytes */
1138 fseek(pFile, 0, SEEK_END);
1139 szFile = (i64)ftell(pFile);
1140 if( szFile==0 ){
1141 memset(pEOCD, 0, sizeof(ZipfileEOCD));
1142 return SQLITE_OK;
1144 nRead = (int)(MIN(szFile, ZIPFILE_BUFFER_SIZE));
1145 iOff = szFile - nRead;
1146 rc = zipfileReadData(pFile, aRead, nRead, iOff, &pTab->base.zErrMsg);
1147 }else{
1148 nRead = (int)(MIN(nBlob, ZIPFILE_BUFFER_SIZE));
1149 aRead = (u8*)&aBlob[nBlob-nRead];
1152 if( rc==SQLITE_OK ){
1153 int i;
1155 /* Scan backwards looking for the signature bytes */
1156 for(i=nRead-20; i>=0; i--){
1157 if( aRead[i]==0x50 && aRead[i+1]==0x4b
1158 && aRead[i+2]==0x05 && aRead[i+3]==0x06
1160 break;
1163 if( i<0 ){
1164 pTab->base.zErrMsg = sqlite3_mprintf(
1165 "cannot find end of central directory record"
1167 return SQLITE_ERROR;
1170 aRead += i+4;
1171 pEOCD->iDisk = zipfileRead16(aRead);
1172 pEOCD->iFirstDisk = zipfileRead16(aRead);
1173 pEOCD->nEntry = zipfileRead16(aRead);
1174 pEOCD->nEntryTotal = zipfileRead16(aRead);
1175 pEOCD->nSize = zipfileRead32(aRead);
1176 pEOCD->iOffset = zipfileRead32(aRead);
1179 return rc;
1183 ** Add object pNew to the linked list that begins at ZipfileTab.pFirstEntry
1184 ** and ends with pLastEntry. If argument pBefore is NULL, then pNew is added
1185 ** to the end of the list. Otherwise, it is added to the list immediately
1186 ** before pBefore (which is guaranteed to be a part of said list).
1188 static void zipfileAddEntry(
1189 ZipfileTab *pTab,
1190 ZipfileEntry *pBefore,
1191 ZipfileEntry *pNew
1193 assert( (pTab->pFirstEntry==0)==(pTab->pLastEntry==0) );
1194 assert( pNew->pNext==0 );
1195 if( pBefore==0 ){
1196 if( pTab->pFirstEntry==0 ){
1197 pTab->pFirstEntry = pTab->pLastEntry = pNew;
1198 }else{
1199 assert( pTab->pLastEntry->pNext==0 );
1200 pTab->pLastEntry->pNext = pNew;
1201 pTab->pLastEntry = pNew;
1203 }else{
1204 ZipfileEntry **pp;
1205 for(pp=&pTab->pFirstEntry; *pp!=pBefore; pp=&((*pp)->pNext));
1206 pNew->pNext = pBefore;
1207 *pp = pNew;
1211 static int zipfileLoadDirectory(ZipfileTab *pTab, const u8 *aBlob, int nBlob){
1212 ZipfileEOCD eocd;
1213 int rc;
1214 int i;
1215 i64 iOff;
1217 rc = zipfileReadEOCD(pTab, aBlob, nBlob, pTab->pWriteFd, &eocd);
1218 iOff = eocd.iOffset;
1219 for(i=0; rc==SQLITE_OK && i<eocd.nEntry; i++){
1220 ZipfileEntry *pNew = 0;
1221 rc = zipfileGetEntry(pTab, aBlob, nBlob, pTab->pWriteFd, iOff, &pNew);
1223 if( rc==SQLITE_OK ){
1224 zipfileAddEntry(pTab, 0, pNew);
1225 iOff += ZIPFILE_CDS_FIXED_SZ;
1226 iOff += (int)pNew->cds.nExtra + pNew->cds.nFile + pNew->cds.nComment;
1229 return rc;
1233 ** xFilter callback.
1235 static int zipfileFilter(
1236 sqlite3_vtab_cursor *cur,
1237 int idxNum, const char *idxStr,
1238 int argc, sqlite3_value **argv
1240 ZipfileTab *pTab = (ZipfileTab*)cur->pVtab;
1241 ZipfileCsr *pCsr = (ZipfileCsr*)cur;
1242 const char *zFile = 0; /* Zip file to scan */
1243 int rc = SQLITE_OK; /* Return Code */
1244 int bInMemory = 0; /* True for an in-memory zipfile */
1246 zipfileResetCursor(pCsr);
1248 if( pTab->zFile ){
1249 zFile = pTab->zFile;
1250 }else if( idxNum==0 ){
1251 zipfileCursorErr(pCsr, "zipfile() function requires an argument");
1252 return SQLITE_ERROR;
1253 }else if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
1254 const u8 *aBlob = (const u8*)sqlite3_value_blob(argv[0]);
1255 int nBlob = sqlite3_value_bytes(argv[0]);
1256 assert( pTab->pFirstEntry==0 );
1257 rc = zipfileLoadDirectory(pTab, aBlob, nBlob);
1258 pCsr->pFreeEntry = pTab->pFirstEntry;
1259 pTab->pFirstEntry = pTab->pLastEntry = 0;
1260 if( rc!=SQLITE_OK ) return rc;
1261 bInMemory = 1;
1262 }else{
1263 zFile = (const char*)sqlite3_value_text(argv[0]);
1266 if( 0==pTab->pWriteFd && 0==bInMemory ){
1267 pCsr->pFile = fopen(zFile, "rb");
1268 if( pCsr->pFile==0 ){
1269 zipfileCursorErr(pCsr, "cannot open file: %s", zFile);
1270 rc = SQLITE_ERROR;
1271 }else{
1272 rc = zipfileReadEOCD(pTab, 0, 0, pCsr->pFile, &pCsr->eocd);
1273 if( rc==SQLITE_OK ){
1274 if( pCsr->eocd.nEntry==0 ){
1275 pCsr->bEof = 1;
1276 }else{
1277 pCsr->iNextOff = pCsr->eocd.iOffset;
1278 rc = zipfileNext(cur);
1282 }else{
1283 pCsr->bNoop = 1;
1284 pCsr->pCurrent = pCsr->pFreeEntry ? pCsr->pFreeEntry : pTab->pFirstEntry;
1285 rc = zipfileNext(cur);
1288 return rc;
1292 ** xBestIndex callback.
1294 static int zipfileBestIndex(
1295 sqlite3_vtab *tab,
1296 sqlite3_index_info *pIdxInfo
1298 int i;
1300 for(i=0; i<pIdxInfo->nConstraint; i++){
1301 const struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i];
1302 if( pCons->usable==0 ) continue;
1303 if( pCons->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
1304 if( pCons->iColumn!=ZIPFILE_F_COLUMN_IDX ) continue;
1305 break;
1308 if( i<pIdxInfo->nConstraint ){
1309 pIdxInfo->aConstraintUsage[i].argvIndex = 1;
1310 pIdxInfo->aConstraintUsage[i].omit = 1;
1311 pIdxInfo->estimatedCost = 1000.0;
1312 pIdxInfo->idxNum = 1;
1313 }else{
1314 pIdxInfo->estimatedCost = (double)(((sqlite3_int64)1) << 50);
1315 pIdxInfo->idxNum = 0;
1318 return SQLITE_OK;
1321 static ZipfileEntry *zipfileNewEntry(const char *zPath){
1322 ZipfileEntry *pNew;
1323 pNew = sqlite3_malloc(sizeof(ZipfileEntry));
1324 if( pNew ){
1325 memset(pNew, 0, sizeof(ZipfileEntry));
1326 pNew->cds.zFile = sqlite3_mprintf("%s", zPath);
1327 if( pNew->cds.zFile==0 ){
1328 sqlite3_free(pNew);
1329 pNew = 0;
1332 return pNew;
1335 static int zipfileSerializeLFH(ZipfileEntry *pEntry, u8 *aBuf){
1336 ZipfileCDS *pCds = &pEntry->cds;
1337 u8 *a = aBuf;
1339 pCds->nExtra = 9;
1341 /* Write the LFH itself */
1342 zipfileWrite32(a, ZIPFILE_SIGNATURE_LFH);
1343 zipfileWrite16(a, pCds->iVersionExtract);
1344 zipfileWrite16(a, pCds->flags);
1345 zipfileWrite16(a, pCds->iCompression);
1346 zipfileWrite16(a, pCds->mTime);
1347 zipfileWrite16(a, pCds->mDate);
1348 zipfileWrite32(a, pCds->crc32);
1349 zipfileWrite32(a, pCds->szCompressed);
1350 zipfileWrite32(a, pCds->szUncompressed);
1351 zipfileWrite16(a, (u16)pCds->nFile);
1352 zipfileWrite16(a, pCds->nExtra);
1353 assert( a==&aBuf[ZIPFILE_LFH_FIXED_SZ] );
1355 /* Add the file name */
1356 memcpy(a, pCds->zFile, (int)pCds->nFile);
1357 a += (int)pCds->nFile;
1359 /* The "extra" data */
1360 zipfileWrite16(a, ZIPFILE_EXTRA_TIMESTAMP);
1361 zipfileWrite16(a, 5);
1362 *a++ = 0x01;
1363 zipfileWrite32(a, pEntry->mUnixTime);
1365 return a-aBuf;
1368 static int zipfileAppendEntry(
1369 ZipfileTab *pTab,
1370 ZipfileEntry *pEntry,
1371 const u8 *pData,
1372 int nData
1374 u8 *aBuf = pTab->aBuffer;
1375 int nBuf;
1376 int rc;
1378 nBuf = zipfileSerializeLFH(pEntry, aBuf);
1379 rc = zipfileAppendData(pTab, aBuf, nBuf);
1380 if( rc==SQLITE_OK ){
1381 pEntry->iDataOff = pTab->szCurrent;
1382 rc = zipfileAppendData(pTab, pData, nData);
1385 return rc;
1388 static int zipfileGetMode(
1389 sqlite3_value *pVal,
1390 int bIsDir, /* If true, default to directory */
1391 u32 *pMode, /* OUT: Mode value */
1392 char **pzErr /* OUT: Error message */
1394 const char *z = (const char*)sqlite3_value_text(pVal);
1395 u32 mode = 0;
1396 if( z==0 ){
1397 mode = (bIsDir ? (S_IFDIR + 0755) : (S_IFREG + 0644));
1398 }else if( z[0]>='0' && z[0]<='9' ){
1399 mode = (unsigned int)sqlite3_value_int(pVal);
1400 }else{
1401 const char zTemplate[11] = "-rwxrwxrwx";
1402 int i;
1403 if( strlen(z)!=10 ) goto parse_error;
1404 switch( z[0] ){
1405 case '-': mode |= S_IFREG; break;
1406 case 'd': mode |= S_IFDIR; break;
1407 case 'l': mode |= S_IFLNK; break;
1408 default: goto parse_error;
1410 for(i=1; i<10; i++){
1411 if( z[i]==zTemplate[i] ) mode |= 1 << (9-i);
1412 else if( z[i]!='-' ) goto parse_error;
1415 if( ((mode & S_IFDIR)==0)==bIsDir ){
1416 /* The "mode" attribute is a directory, but data has been specified.
1417 ** Or vice-versa - no data but "mode" is a file or symlink. */
1418 *pzErr = sqlite3_mprintf("zipfile: mode does not match data");
1419 return SQLITE_CONSTRAINT;
1421 *pMode = mode;
1422 return SQLITE_OK;
1424 parse_error:
1425 *pzErr = sqlite3_mprintf("zipfile: parse error in mode: %s", z);
1426 return SQLITE_ERROR;
1430 ** Both (const char*) arguments point to nul-terminated strings. Argument
1431 ** nB is the value of strlen(zB). This function returns 0 if the strings are
1432 ** identical, ignoring any trailing '/' character in either path. */
1433 static int zipfileComparePath(const char *zA, const char *zB, int nB){
1434 int nA = (int)strlen(zA);
1435 if( zA[nA-1]=='/' ) nA--;
1436 if( zB[nB-1]=='/' ) nB--;
1437 if( nA==nB && memcmp(zA, zB, nA)==0 ) return 0;
1438 return 1;
1441 static int zipfileBegin(sqlite3_vtab *pVtab){
1442 ZipfileTab *pTab = (ZipfileTab*)pVtab;
1443 int rc = SQLITE_OK;
1445 assert( pTab->pWriteFd==0 );
1447 /* Open a write fd on the file. Also load the entire central directory
1448 ** structure into memory. During the transaction any new file data is
1449 ** appended to the archive file, but the central directory is accumulated
1450 ** in main-memory until the transaction is committed. */
1451 pTab->pWriteFd = fopen(pTab->zFile, "ab+");
1452 if( pTab->pWriteFd==0 ){
1453 pTab->base.zErrMsg = sqlite3_mprintf(
1454 "zipfile: failed to open file %s for writing", pTab->zFile
1456 rc = SQLITE_ERROR;
1457 }else{
1458 fseek(pTab->pWriteFd, 0, SEEK_END);
1459 pTab->szCurrent = pTab->szOrig = (i64)ftell(pTab->pWriteFd);
1460 rc = zipfileLoadDirectory(pTab, 0, 0);
1463 if( rc!=SQLITE_OK ){
1464 zipfileCleanupTransaction(pTab);
1467 return rc;
1471 ** Return the current time as a 32-bit timestamp in UNIX epoch format (like
1472 ** time(2)).
1474 static u32 zipfileTime(void){
1475 sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
1476 u32 ret;
1477 if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){
1478 i64 ms;
1479 pVfs->xCurrentTimeInt64(pVfs, &ms);
1480 ret = (u32)((ms/1000) - ((i64)24405875 * 8640));
1481 }else{
1482 double day;
1483 pVfs->xCurrentTime(pVfs, &day);
1484 ret = (u32)((day - 2440587.5) * 86400);
1486 return ret;
1490 ** Return a 32-bit timestamp in UNIX epoch format.
1492 ** If the value passed as the only argument is either NULL or an SQL NULL,
1493 ** return the current time. Otherwise, return the value stored in (*pVal)
1494 ** cast to a 32-bit unsigned integer.
1496 static u32 zipfileGetTime(sqlite3_value *pVal){
1497 if( pVal==0 || sqlite3_value_type(pVal)==SQLITE_NULL ){
1498 return zipfileTime();
1500 return (u32)sqlite3_value_int64(pVal);
1504 ** xUpdate method.
1506 static int zipfileUpdate(
1507 sqlite3_vtab *pVtab,
1508 int nVal,
1509 sqlite3_value **apVal,
1510 sqlite_int64 *pRowid
1512 ZipfileTab *pTab = (ZipfileTab*)pVtab;
1513 int rc = SQLITE_OK; /* Return Code */
1514 ZipfileEntry *pNew = 0; /* New in-memory CDS entry */
1516 u32 mode = 0; /* Mode for new entry */
1517 u32 mTime = 0; /* Modification time for new entry */
1518 i64 sz = 0; /* Uncompressed size */
1519 const char *zPath = 0; /* Path for new entry */
1520 int nPath = 0; /* strlen(zPath) */
1521 const u8 *pData = 0; /* Pointer to buffer containing content */
1522 int nData = 0; /* Size of pData buffer in bytes */
1523 int iMethod = 0; /* Compression method for new entry */
1524 u8 *pFree = 0; /* Free this */
1525 char *zFree = 0; /* Also free this */
1526 ZipfileEntry *pOld = 0;
1527 int bIsDir = 0;
1528 u32 iCrc32 = 0;
1530 if( pTab->pWriteFd==0 ){
1531 rc = zipfileBegin(pVtab);
1532 if( rc!=SQLITE_OK ) return rc;
1535 /* If this is a DELETE or UPDATE, find the archive entry to delete. */
1536 if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
1537 const char *zDelete = (const char*)sqlite3_value_text(apVal[0]);
1538 int nDelete = (int)strlen(zDelete);
1539 for(pOld=pTab->pFirstEntry; 1; pOld=pOld->pNext){
1540 if( zipfileComparePath(pOld->cds.zFile, zDelete, nDelete)==0 ){
1541 break;
1543 assert( pOld->pNext );
1547 if( nVal>1 ){
1548 /* Check that "sz" and "rawdata" are both NULL: */
1549 if( sqlite3_value_type(apVal[5])!=SQLITE_NULL ){
1550 zipfileTableErr(pTab, "sz must be NULL");
1551 rc = SQLITE_CONSTRAINT;
1553 if( sqlite3_value_type(apVal[6])!=SQLITE_NULL ){
1554 zipfileTableErr(pTab, "rawdata must be NULL");
1555 rc = SQLITE_CONSTRAINT;
1558 if( rc==SQLITE_OK ){
1559 if( sqlite3_value_type(apVal[7])==SQLITE_NULL ){
1560 /* data=NULL. A directory */
1561 bIsDir = 1;
1562 }else{
1563 /* Value specified for "data", and possibly "method". This must be
1564 ** a regular file or a symlink. */
1565 const u8 *aIn = sqlite3_value_blob(apVal[7]);
1566 int nIn = sqlite3_value_bytes(apVal[7]);
1567 int bAuto = sqlite3_value_type(apVal[8])==SQLITE_NULL;
1569 iMethod = sqlite3_value_int(apVal[8]);
1570 sz = nIn;
1571 pData = aIn;
1572 nData = nIn;
1573 if( iMethod!=0 && iMethod!=8 ){
1574 zipfileTableErr(pTab, "unknown compression method: %d", iMethod);
1575 rc = SQLITE_CONSTRAINT;
1576 }else{
1577 if( bAuto || iMethod ){
1578 int nCmp;
1579 rc = zipfileDeflate(aIn, nIn, &pFree, &nCmp, &pTab->base.zErrMsg);
1580 if( rc==SQLITE_OK ){
1581 if( iMethod || nCmp<nIn ){
1582 iMethod = 8;
1583 pData = pFree;
1584 nData = nCmp;
1588 iCrc32 = crc32(0, aIn, nIn);
1593 if( rc==SQLITE_OK ){
1594 rc = zipfileGetMode(apVal[3], bIsDir, &mode, &pTab->base.zErrMsg);
1597 if( rc==SQLITE_OK ){
1598 zPath = (const char*)sqlite3_value_text(apVal[2]);
1599 nPath = (int)strlen(zPath);
1600 mTime = zipfileGetTime(apVal[4]);
1603 if( rc==SQLITE_OK && bIsDir ){
1604 /* For a directory, check that the last character in the path is a
1605 ** '/'. This appears to be required for compatibility with info-zip
1606 ** (the unzip command on unix). It does not create directories
1607 ** otherwise. */
1608 if( zPath[nPath-1]!='/' ){
1609 zFree = sqlite3_mprintf("%s/", zPath);
1610 if( zFree==0 ){ rc = SQLITE_NOMEM; }
1611 zPath = (const char*)zFree;
1612 nPath++;
1616 /* Check that we're not inserting a duplicate entry */
1617 if( pOld==0 && rc==SQLITE_OK ){
1618 ZipfileEntry *p;
1619 for(p=pTab->pFirstEntry; p; p=p->pNext){
1620 if( zipfileComparePath(p->cds.zFile, zPath, nPath)==0 ){
1621 switch( sqlite3_vtab_on_conflict(pTab->db) ){
1622 case SQLITE_IGNORE: {
1623 goto zipfile_update_done;
1625 case SQLITE_REPLACE: {
1626 pOld = p;
1627 break;
1629 default: {
1630 zipfileTableErr(pTab, "duplicate name: \"%s\"", zPath);
1631 rc = SQLITE_CONSTRAINT;
1632 break;
1635 break;
1640 if( rc==SQLITE_OK ){
1641 /* Create the new CDS record. */
1642 pNew = zipfileNewEntry(zPath);
1643 if( pNew==0 ){
1644 rc = SQLITE_NOMEM;
1645 }else{
1646 pNew->cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY;
1647 pNew->cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED;
1648 pNew->cds.flags = ZIPFILE_NEWENTRY_FLAGS;
1649 pNew->cds.iCompression = (u16)iMethod;
1650 zipfileMtimeToDos(&pNew->cds, mTime);
1651 pNew->cds.crc32 = iCrc32;
1652 pNew->cds.szCompressed = nData;
1653 pNew->cds.szUncompressed = (u32)sz;
1654 pNew->cds.iExternalAttr = (mode<<16);
1655 pNew->cds.iOffset = (u32)pTab->szCurrent;
1656 pNew->cds.nFile = (u16)nPath;
1657 pNew->mUnixTime = (u32)mTime;
1658 rc = zipfileAppendEntry(pTab, pNew, pData, nData);
1659 zipfileAddEntry(pTab, pOld, pNew);
1664 if( rc==SQLITE_OK && pOld ){
1665 ZipfileEntry **pp;
1666 ZipfileCsr *pCsr;
1667 for(pCsr=pTab->pCsrList; pCsr; pCsr=pCsr->pCsrNext){
1668 if( pCsr->pCurrent==pOld ){
1669 pCsr->pCurrent = pOld->pNext;
1670 pCsr->bNoop = 1;
1673 for(pp=&pTab->pFirstEntry; (*pp)!=pOld; pp=&((*pp)->pNext));
1674 *pp = (*pp)->pNext;
1675 zipfileEntryFree(pOld);
1678 zipfile_update_done:
1679 sqlite3_free(pFree);
1680 sqlite3_free(zFree);
1681 return rc;
1684 static int zipfileSerializeEOCD(ZipfileEOCD *p, u8 *aBuf){
1685 u8 *a = aBuf;
1686 zipfileWrite32(a, ZIPFILE_SIGNATURE_EOCD);
1687 zipfileWrite16(a, p->iDisk);
1688 zipfileWrite16(a, p->iFirstDisk);
1689 zipfileWrite16(a, p->nEntry);
1690 zipfileWrite16(a, p->nEntryTotal);
1691 zipfileWrite32(a, p->nSize);
1692 zipfileWrite32(a, p->iOffset);
1693 zipfileWrite16(a, 0); /* Size of trailing comment in bytes*/
1695 return a-aBuf;
1698 static int zipfileAppendEOCD(ZipfileTab *pTab, ZipfileEOCD *p){
1699 int nBuf = zipfileSerializeEOCD(p, pTab->aBuffer);
1700 assert( nBuf==ZIPFILE_EOCD_FIXED_SZ );
1701 return zipfileAppendData(pTab, pTab->aBuffer, nBuf);
1705 ** Serialize the CDS structure into buffer aBuf[]. Return the number
1706 ** of bytes written.
1708 static int zipfileSerializeCDS(ZipfileEntry *pEntry, u8 *aBuf){
1709 u8 *a = aBuf;
1710 ZipfileCDS *pCDS = &pEntry->cds;
1712 if( pEntry->aExtra==0 ){
1713 pCDS->nExtra = 9;
1716 zipfileWrite32(a, ZIPFILE_SIGNATURE_CDS);
1717 zipfileWrite16(a, pCDS->iVersionMadeBy);
1718 zipfileWrite16(a, pCDS->iVersionExtract);
1719 zipfileWrite16(a, pCDS->flags);
1720 zipfileWrite16(a, pCDS->iCompression);
1721 zipfileWrite16(a, pCDS->mTime);
1722 zipfileWrite16(a, pCDS->mDate);
1723 zipfileWrite32(a, pCDS->crc32);
1724 zipfileWrite32(a, pCDS->szCompressed);
1725 zipfileWrite32(a, pCDS->szUncompressed);
1726 assert( a==&aBuf[ZIPFILE_CDS_NFILE_OFF] );
1727 zipfileWrite16(a, pCDS->nFile);
1728 zipfileWrite16(a, pCDS->nExtra);
1729 zipfileWrite16(a, pCDS->nComment);
1730 zipfileWrite16(a, pCDS->iDiskStart);
1731 zipfileWrite16(a, pCDS->iInternalAttr);
1732 zipfileWrite32(a, pCDS->iExternalAttr);
1733 zipfileWrite32(a, pCDS->iOffset);
1735 memcpy(a, pCDS->zFile, pCDS->nFile);
1736 a += pCDS->nFile;
1738 if( pEntry->aExtra ){
1739 int n = (int)pCDS->nExtra + (int)pCDS->nComment;
1740 memcpy(a, pEntry->aExtra, n);
1741 a += n;
1742 }else{
1743 assert( pCDS->nExtra==9 );
1744 zipfileWrite16(a, ZIPFILE_EXTRA_TIMESTAMP);
1745 zipfileWrite16(a, 5);
1746 *a++ = 0x01;
1747 zipfileWrite32(a, pEntry->mUnixTime);
1750 return a-aBuf;
1753 static int zipfileCommit(sqlite3_vtab *pVtab){
1754 ZipfileTab *pTab = (ZipfileTab*)pVtab;
1755 int rc = SQLITE_OK;
1756 if( pTab->pWriteFd ){
1757 i64 iOffset = pTab->szCurrent;
1758 ZipfileEntry *p;
1759 ZipfileEOCD eocd;
1760 int nEntry = 0;
1762 /* Write out all entries */
1763 for(p=pTab->pFirstEntry; rc==SQLITE_OK && p; p=p->pNext){
1764 int n = zipfileSerializeCDS(p, pTab->aBuffer);
1765 rc = zipfileAppendData(pTab, pTab->aBuffer, n);
1766 nEntry++;
1769 /* Write out the EOCD record */
1770 eocd.iDisk = 0;
1771 eocd.iFirstDisk = 0;
1772 eocd.nEntry = (u16)nEntry;
1773 eocd.nEntryTotal = (u16)nEntry;
1774 eocd.nSize = (u32)(pTab->szCurrent - iOffset);
1775 eocd.iOffset = (u32)iOffset;
1776 rc = zipfileAppendEOCD(pTab, &eocd);
1778 zipfileCleanupTransaction(pTab);
1780 return rc;
1783 static int zipfileRollback(sqlite3_vtab *pVtab){
1784 return zipfileCommit(pVtab);
1787 static ZipfileCsr *zipfileFindCursor(ZipfileTab *pTab, i64 iId){
1788 ZipfileCsr *pCsr;
1789 for(pCsr=pTab->pCsrList; pCsr; pCsr=pCsr->pCsrNext){
1790 if( iId==pCsr->iId ) break;
1792 return pCsr;
1795 static void zipfileFunctionCds(
1796 sqlite3_context *context,
1797 int argc,
1798 sqlite3_value **argv
1800 ZipfileCsr *pCsr;
1801 ZipfileTab *pTab = (ZipfileTab*)sqlite3_user_data(context);
1802 assert( argc>0 );
1804 pCsr = zipfileFindCursor(pTab, sqlite3_value_int64(argv[0]));
1805 if( pCsr ){
1806 ZipfileCDS *p = &pCsr->pCurrent->cds;
1807 char *zRes = sqlite3_mprintf("{"
1808 "\"version-made-by\" : %u, "
1809 "\"version-to-extract\" : %u, "
1810 "\"flags\" : %u, "
1811 "\"compression\" : %u, "
1812 "\"time\" : %u, "
1813 "\"date\" : %u, "
1814 "\"crc32\" : %u, "
1815 "\"compressed-size\" : %u, "
1816 "\"uncompressed-size\" : %u, "
1817 "\"file-name-length\" : %u, "
1818 "\"extra-field-length\" : %u, "
1819 "\"file-comment-length\" : %u, "
1820 "\"disk-number-start\" : %u, "
1821 "\"internal-attr\" : %u, "
1822 "\"external-attr\" : %u, "
1823 "\"offset\" : %u }",
1824 (u32)p->iVersionMadeBy, (u32)p->iVersionExtract,
1825 (u32)p->flags, (u32)p->iCompression,
1826 (u32)p->mTime, (u32)p->mDate,
1827 (u32)p->crc32, (u32)p->szCompressed,
1828 (u32)p->szUncompressed, (u32)p->nFile,
1829 (u32)p->nExtra, (u32)p->nComment,
1830 (u32)p->iDiskStart, (u32)p->iInternalAttr,
1831 (u32)p->iExternalAttr, (u32)p->iOffset
1834 if( zRes==0 ){
1835 sqlite3_result_error_nomem(context);
1836 }else{
1837 sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT);
1838 sqlite3_free(zRes);
1844 ** xFindFunction method.
1846 static int zipfileFindFunction(
1847 sqlite3_vtab *pVtab, /* Virtual table handle */
1848 int nArg, /* Number of SQL function arguments */
1849 const char *zName, /* Name of SQL function */
1850 void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */
1851 void **ppArg /* OUT: User data for *pxFunc */
1853 if( sqlite3_stricmp("zipfile_cds", zName)==0 ){
1854 *pxFunc = zipfileFunctionCds;
1855 *ppArg = (void*)pVtab;
1856 return 1;
1858 return 0;
1861 typedef struct ZipfileBuffer ZipfileBuffer;
1862 struct ZipfileBuffer {
1863 u8 *a; /* Pointer to buffer */
1864 int n; /* Size of buffer in bytes */
1865 int nAlloc; /* Byte allocated at a[] */
1868 typedef struct ZipfileCtx ZipfileCtx;
1869 struct ZipfileCtx {
1870 int nEntry;
1871 ZipfileBuffer body;
1872 ZipfileBuffer cds;
1875 static int zipfileBufferGrow(ZipfileBuffer *pBuf, int nByte){
1876 if( pBuf->n+nByte>pBuf->nAlloc ){
1877 u8 *aNew;
1878 int nNew = pBuf->n ? pBuf->n*2 : 512;
1879 int nReq = pBuf->n + nByte;
1881 while( nNew<nReq ) nNew = nNew*2;
1882 aNew = sqlite3_realloc(pBuf->a, nNew);
1883 if( aNew==0 ) return SQLITE_NOMEM;
1884 pBuf->a = aNew;
1885 pBuf->nAlloc = nNew;
1887 return SQLITE_OK;
1891 ** xStep() callback for the zipfile() aggregate. This can be called in
1892 ** any of the following ways:
1894 ** SELECT zipfile(name,data) ...
1895 ** SELECT zipfile(name,mode,mtime,data) ...
1896 ** SELECT zipfile(name,mode,mtime,data,method) ...
1898 void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
1899 ZipfileCtx *p; /* Aggregate function context */
1900 ZipfileEntry e; /* New entry to add to zip archive */
1902 sqlite3_value *pName = 0;
1903 sqlite3_value *pMode = 0;
1904 sqlite3_value *pMtime = 0;
1905 sqlite3_value *pData = 0;
1906 sqlite3_value *pMethod = 0;
1908 int bIsDir = 0;
1909 u32 mode;
1910 int rc = SQLITE_OK;
1911 char *zErr = 0;
1913 int iMethod = -1; /* Compression method to use (0 or 8) */
1915 const u8 *aData = 0; /* Possibly compressed data for new entry */
1916 int nData = 0; /* Size of aData[] in bytes */
1917 int szUncompressed = 0; /* Size of data before compression */
1918 u8 *aFree = 0; /* Free this before returning */
1919 u32 iCrc32 = 0; /* crc32 of uncompressed data */
1921 char *zName = 0; /* Path (name) of new entry */
1922 int nName = 0; /* Size of zName in bytes */
1923 char *zFree = 0; /* Free this before returning */
1924 int nByte;
1926 memset(&e, 0, sizeof(e));
1927 p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx));
1928 if( p==0 ) return;
1930 /* Martial the arguments into stack variables */
1931 if( nVal!=2 && nVal!=4 && nVal!=5 ){
1932 zErr = sqlite3_mprintf("wrong number of arguments to function zipfile()");
1933 rc = SQLITE_ERROR;
1934 goto zipfile_step_out;
1936 pName = apVal[0];
1937 if( nVal==2 ){
1938 pData = apVal[1];
1939 }else{
1940 pMode = apVal[1];
1941 pMtime = apVal[2];
1942 pData = apVal[3];
1943 if( nVal==5 ){
1944 pMethod = apVal[4];
1948 /* Check that the 'name' parameter looks ok. */
1949 zName = (char*)sqlite3_value_text(pName);
1950 nName = sqlite3_value_bytes(pName);
1951 if( zName==0 ){
1952 zErr = sqlite3_mprintf("first argument to zipfile() must be non-NULL");
1953 rc = SQLITE_ERROR;
1954 goto zipfile_step_out;
1957 /* Inspect the 'method' parameter. This must be either 0 (store), 8 (use
1958 ** deflate compression) or NULL (choose automatically). */
1959 if( pMethod && SQLITE_NULL!=sqlite3_value_type(pMethod) ){
1960 iMethod = (int)sqlite3_value_int64(pMethod);
1961 if( iMethod!=0 && iMethod!=8 ){
1962 zErr = sqlite3_mprintf("illegal method value: %d", iMethod);
1963 rc = SQLITE_ERROR;
1964 goto zipfile_step_out;
1968 /* Now inspect the data. If this is NULL, then the new entry must be a
1969 ** directory. Otherwise, figure out whether or not the data should
1970 ** be deflated or simply stored in the zip archive. */
1971 if( sqlite3_value_type(pData)==SQLITE_NULL ){
1972 bIsDir = 1;
1973 iMethod = 0;
1974 }else{
1975 aData = sqlite3_value_blob(pData);
1976 szUncompressed = nData = sqlite3_value_bytes(pData);
1977 iCrc32 = crc32(0, aData, nData);
1978 if( iMethod<0 || iMethod==8 ){
1979 int nOut = 0;
1980 rc = zipfileDeflate(aData, nData, &aFree, &nOut, &zErr);
1981 if( rc!=SQLITE_OK ){
1982 goto zipfile_step_out;
1984 if( iMethod==8 || nOut<nData ){
1985 aData = aFree;
1986 nData = nOut;
1987 iMethod = 8;
1988 }else{
1989 iMethod = 0;
1994 /* Decode the "mode" argument. */
1995 rc = zipfileGetMode(pMode, bIsDir, &mode, &zErr);
1996 if( rc ) goto zipfile_step_out;
1998 /* Decode the "mtime" argument. */
1999 e.mUnixTime = zipfileGetTime(pMtime);
2001 /* If this is a directory entry, ensure that there is exactly one '/'
2002 ** at the end of the path. Or, if this is not a directory and the path
2003 ** ends in '/' it is an error. */
2004 if( bIsDir==0 ){
2005 if( zName[nName-1]=='/' ){
2006 zErr = sqlite3_mprintf("non-directory name must not end with /");
2007 rc = SQLITE_ERROR;
2008 goto zipfile_step_out;
2010 }else{
2011 if( zName[nName-1]!='/' ){
2012 zName = zFree = sqlite3_mprintf("%s/", zName);
2013 nName++;
2014 if( zName==0 ){
2015 rc = SQLITE_NOMEM;
2016 goto zipfile_step_out;
2018 }else{
2019 while( nName>1 && zName[nName-2]=='/' ) nName--;
2023 /* Assemble the ZipfileEntry object for the new zip archive entry */
2024 e.cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY;
2025 e.cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED;
2026 e.cds.flags = ZIPFILE_NEWENTRY_FLAGS;
2027 e.cds.iCompression = (u16)iMethod;
2028 zipfileMtimeToDos(&e.cds, (u32)e.mUnixTime);
2029 e.cds.crc32 = iCrc32;
2030 e.cds.szCompressed = nData;
2031 e.cds.szUncompressed = szUncompressed;
2032 e.cds.iExternalAttr = (mode<<16);
2033 e.cds.iOffset = p->body.n;
2034 e.cds.nFile = (u16)nName;
2035 e.cds.zFile = zName;
2037 /* Append the LFH to the body of the new archive */
2038 nByte = ZIPFILE_LFH_FIXED_SZ + e.cds.nFile + 9;
2039 if( (rc = zipfileBufferGrow(&p->body, nByte)) ) goto zipfile_step_out;
2040 p->body.n += zipfileSerializeLFH(&e, &p->body.a[p->body.n]);
2042 /* Append the data to the body of the new archive */
2043 if( (rc = zipfileBufferGrow(&p->body, nData)) ) goto zipfile_step_out;
2044 memcpy(&p->body.a[p->body.n], aData, nData);
2045 p->body.n += nData;
2047 /* Append the CDS record to the directory of the new archive */
2048 nByte = ZIPFILE_CDS_FIXED_SZ + e.cds.nFile + 9;
2049 if( (rc = zipfileBufferGrow(&p->cds, nByte)) ) goto zipfile_step_out;
2050 p->cds.n += zipfileSerializeCDS(&e, &p->cds.a[p->cds.n]);
2052 /* Increment the count of entries in the archive */
2053 p->nEntry++;
2055 zipfile_step_out:
2056 sqlite3_free(aFree);
2057 sqlite3_free(zFree);
2058 if( rc ){
2059 if( zErr ){
2060 sqlite3_result_error(pCtx, zErr, -1);
2061 }else{
2062 sqlite3_result_error_code(pCtx, rc);
2065 sqlite3_free(zErr);
2069 ** xFinalize() callback for zipfile aggregate function.
2071 void zipfileFinal(sqlite3_context *pCtx){
2072 ZipfileCtx *p;
2073 ZipfileEOCD eocd;
2074 int nZip;
2075 u8 *aZip;
2077 p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx));
2078 if( p==0 ) return;
2079 if( p->nEntry>0 ){
2080 memset(&eocd, 0, sizeof(eocd));
2081 eocd.nEntry = (u16)p->nEntry;
2082 eocd.nEntryTotal = (u16)p->nEntry;
2083 eocd.nSize = p->cds.n;
2084 eocd.iOffset = p->body.n;
2086 nZip = p->body.n + p->cds.n + ZIPFILE_EOCD_FIXED_SZ;
2087 aZip = (u8*)sqlite3_malloc(nZip);
2088 if( aZip==0 ){
2089 sqlite3_result_error_nomem(pCtx);
2090 }else{
2091 memcpy(aZip, p->body.a, p->body.n);
2092 memcpy(&aZip[p->body.n], p->cds.a, p->cds.n);
2093 zipfileSerializeEOCD(&eocd, &aZip[p->body.n + p->cds.n]);
2094 sqlite3_result_blob(pCtx, aZip, nZip, zipfileFree);
2098 sqlite3_free(p->body.a);
2099 sqlite3_free(p->cds.a);
2104 ** Register the "zipfile" virtual table.
2106 static int zipfileRegister(sqlite3 *db){
2107 static sqlite3_module zipfileModule = {
2108 1, /* iVersion */
2109 zipfileConnect, /* xCreate */
2110 zipfileConnect, /* xConnect */
2111 zipfileBestIndex, /* xBestIndex */
2112 zipfileDisconnect, /* xDisconnect */
2113 zipfileDisconnect, /* xDestroy */
2114 zipfileOpen, /* xOpen - open a cursor */
2115 zipfileClose, /* xClose - close a cursor */
2116 zipfileFilter, /* xFilter - configure scan constraints */
2117 zipfileNext, /* xNext - advance a cursor */
2118 zipfileEof, /* xEof - check for end of scan */
2119 zipfileColumn, /* xColumn - read data */
2120 0, /* xRowid - read data */
2121 zipfileUpdate, /* xUpdate */
2122 zipfileBegin, /* xBegin */
2123 0, /* xSync */
2124 zipfileCommit, /* xCommit */
2125 zipfileRollback, /* xRollback */
2126 zipfileFindFunction, /* xFindMethod */
2127 0, /* xRename */
2130 int rc = sqlite3_create_module(db, "zipfile" , &zipfileModule, 0);
2131 if( rc==SQLITE_OK ) rc = sqlite3_overload_function(db, "zipfile_cds", -1);
2132 if( rc==SQLITE_OK ){
2133 rc = sqlite3_create_function(db, "zipfile", -1, SQLITE_UTF8, 0, 0,
2134 zipfileStep, zipfileFinal
2137 return rc;
2139 #else /* SQLITE_OMIT_VIRTUALTABLE */
2140 # define zipfileRegister(x) SQLITE_OK
2141 #endif
2143 #ifdef _WIN32
2144 __declspec(dllexport)
2145 #endif
2146 int sqlite3_zipfile_init(
2147 sqlite3 *db,
2148 char **pzErrMsg,
2149 const sqlite3_api_routines *pApi
2151 SQLITE_EXTENSION_INIT2(pApi);
2152 (void)pzErrMsg; /* Unused parameter */
2153 return zipfileRegister(db);