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