/ Check-in [cf640872]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix a zipfile problem with extracting zero length files compressed using deflate.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256:cf64087224aff1a2fe169d23996d9e5ed8d86459c655eb5d0bace0466a557ec6
User & Date: dan 2018-01-15 15:49:46
Context
2018-01-15
19:00
Fix a problem in the zipfile module causing it to generate incorrect checksums. Remove the ability to insert compressed data into a zip archive. check-in: b0b7d036 user: dan tags: trunk
15:49
Fix a zipfile problem with extracting zero length files compressed using deflate. check-in: cf640872 user: dan tags: trunk
14:32
Fix an error in the setDeviceCharacteristics() procedure for the (unsupported) QNX code in os_unix.c. check-in: 8151913a user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/misc/zipfile.c.

    60     60       "name PRIMARY KEY,"  /* 0: Name of file in zip archive */
    61     61       "mode,"              /* 1: POSIX mode for file */
    62     62       "mtime,"             /* 2: Last modification time (secs since 1970)*/
    63     63       "sz,"                /* 3: Size of object */
    64     64       "rawdata,"           /* 4: Raw data */
    65     65       "data,"              /* 5: Uncompressed data */
    66     66       "method,"            /* 6: Compression method (integer) */
    67         -    "file HIDDEN"        /* 7: Name of zip file */
           67  +    "z HIDDEN"           /* 7: Name of zip file */
    68     68     ") WITHOUT ROWID;";
    69     69   
    70     70   #define ZIPFILE_F_COLUMN_IDX 7    /* Index of column "file" in the above */
    71     71   #define ZIPFILE_BUFFER_SIZE (64*1024)
    72     72   
    73     73   
    74     74   /*
................................................................................
   231    231   
   232    232   /* 
   233    233   ** Cursor type for recursively iterating through a directory structure.
   234    234   */
   235    235   typedef struct ZipfileCsr ZipfileCsr;
   236    236   struct ZipfileCsr {
   237    237     sqlite3_vtab_cursor base;  /* Base class - must be first */
          238  +  i64 iId;                   /* Cursor ID */
   238    239     int bEof;                  /* True when at EOF */
   239    240   
   240    241     /* Used outside of write transactions */
   241    242     FILE *pFile;               /* Zip file */
   242    243     i64 iNextOff;              /* Offset of next record in central directory */
   243    244     ZipfileEOCD eocd;          /* Parse of central directory record */
   244    245   
................................................................................
   260    261   
   261    262   typedef struct ZipfileTab ZipfileTab;
   262    263   struct ZipfileTab {
   263    264     sqlite3_vtab base;         /* Base class - must be first */
   264    265     char *zFile;               /* Zip file this table accesses (may be NULL) */
   265    266     u8 *aBuffer;               /* Temporary buffer used for various tasks */
   266    267   
   267         -  /* The following are used by write transactions only */
   268    268     ZipfileCsr *pCsrList;      /* List of cursors */
          269  +  i64 iNextCsrid;
          270  +
          271  +  /* The following are used by write transactions only */
   269    272     ZipfileEntry *pFirstEntry; /* Linked list of all files (if pWriteFd!=0) */
   270    273     ZipfileEntry *pLastEntry;  /* Last element in pFirstEntry list */
   271    274     FILE *pWriteFd;            /* File handle open on zip archive */
   272    275     i64 szCurrent;             /* Current size of zip archive */
   273    276     i64 szOrig;                /* Size of archive at start of transaction */
   274    277   };
   275    278   
................................................................................
   340    343     return SQLITE_OK;
   341    344   }
   342    345   
   343    346   /*
   344    347   ** Constructor for a new ZipfileCsr object.
   345    348   */
   346    349   static int zipfileOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCsr){
          350  +  ZipfileTab *pTab = (ZipfileTab*)p;
   347    351     ZipfileCsr *pCsr;
   348    352     pCsr = sqlite3_malloc(sizeof(*pCsr));
   349    353     *ppCsr = (sqlite3_vtab_cursor*)pCsr;
   350    354     if( pCsr==0 ){
   351    355       return SQLITE_NOMEM;
   352    356     }
   353    357     memset(pCsr, 0, sizeof(*pCsr));
          358  +  pCsr->iId = ++pTab->iNextCsrid;
          359  +  pCsr->pCsrNext = pTab->pCsrList;
          360  +  pTab->pCsrList = pCsr;
   354    361     return SQLITE_OK;
   355    362   }
   356    363   
   357    364   /*
   358    365   ** Reset a cursor back to the state it was in when first returned
   359    366   ** by zipfileOpen().
   360    367   */
   361    368   static void zipfileResetCursor(ZipfileCsr *pCsr){
   362         -  ZipfileTab *pTab = (ZipfileTab*)(pCsr->base.pVtab);
   363         -  ZipfileCsr **pp;
   364         -
   365         -  /* Remove this cursor from the ZipfileTab.pCsrList list. */
   366         -  for(pp=&pTab->pCsrList; *pp; pp=&((*pp)->pCsrNext)){
   367         -    if( *pp==pCsr ) *pp = pCsr->pCsrNext;
   368         -  }
   369         -
   370    369     sqlite3_free(pCsr->cds.zFile);
   371    370     pCsr->cds.zFile = 0;
   372    371     pCsr->bEof = 0;
   373    372     if( pCsr->pFile ){
   374    373       fclose(pCsr->pFile);
   375    374       pCsr->pFile = 0;
   376    375     }
................................................................................
   377    376   }
   378    377   
   379    378   /*
   380    379   ** Destructor for an ZipfileCsr.
   381    380   */
   382    381   static int zipfileClose(sqlite3_vtab_cursor *cur){
   383    382     ZipfileCsr *pCsr = (ZipfileCsr*)cur;
          383  +  ZipfileTab *pTab = (ZipfileTab*)(pCsr->base.pVtab);
          384  +  ZipfileCsr **pp;
   384    385     zipfileResetCursor(pCsr);
          386  +
          387  +  /* Remove this cursor from the ZipfileTab.pCsrList list. */
          388  +  for(pp=&pTab->pCsrList; *pp; pp=&((*pp)->pCsrNext)){
          389  +    if( *pp==pCsr ){ 
          390  +      *pp = pCsr->pCsrNext;
          391  +      break;
          392  +    }
          393  +  }
          394  +
   385    395     sqlite3_free(pCsr);
   386    396     return SQLITE_OK;
   387    397   }
   388    398   
   389    399   /*
   390    400   ** Set the error message for the virtual table associated with cursor
   391    401   ** pCsr to the results of vprintf(zFmt, ...).
................................................................................
   819    829         sqlite3_result_int64(ctx, pCsr->cds.szUncompressed);
   820    830         break;
   821    831       }
   822    832       case 4:   /* rawdata */
   823    833       case 5: { /* data */
   824    834         if( i==4 || pCsr->cds.iCompression==0 || pCsr->cds.iCompression==8 ){
   825    835           int sz = pCsr->cds.szCompressed;
   826         -        if( sz>0 ){
          836  +        int szFinal = pCsr->cds.szUncompressed;
          837  +        if( szFinal>0 ){
   827    838             u8 *aBuf = sqlite3_malloc(sz);
   828    839             if( aBuf==0 ){
   829    840               rc = SQLITE_NOMEM;
   830    841             }else{
   831    842               FILE *pFile = zipfileGetFd(pCsr);
   832    843               rc = zipfileReadData(pFile, aBuf, sz, pCsr->iDataOff,
   833    844                   &pCsr->base.pVtab->zErrMsg
   834    845               );
   835    846             }
   836    847             if( rc==SQLITE_OK ){
   837    848               if( i==5 && pCsr->cds.iCompression ){
   838         -              zipfileInflate(ctx, aBuf, sz, pCsr->cds.szUncompressed);
          849  +              zipfileInflate(ctx, aBuf, sz, szFinal);
   839    850               }else{
   840    851                 sqlite3_result_blob(ctx, aBuf, sz, SQLITE_TRANSIENT);
   841    852               }
   842    853               sqlite3_free(aBuf);
   843    854             }
          855  +        }else{
          856  +          /* Figure out if this is a directory or a zero-sized file. Consider
          857  +          ** it to be a directory either if the mode suggests so, or if
          858  +          ** the final character in the name is '/'.  */
          859  +          u32 mode = pCsr->cds.iExternalAttr >> 16;
          860  +          if( !(mode & S_IFDIR) && pCsr->cds.zFile[pCsr->cds.nFile-1]!='/' ){
          861  +            sqlite3_result_blob(ctx, "", 0, SQLITE_STATIC);
          862  +          }
   844    863           }
   845    864         }
   846    865         break;
   847    866       }
   848    867       case 6:   /* method */
   849    868         sqlite3_result_int(ctx, pCsr->cds.iCompression);
   850    869         break;
          870  +    case 7:   /* z */
          871  +      sqlite3_result_int64(ctx, pCsr->iId);
          872  +      break;
   851    873     }
   852    874   
   853    875     return SQLITE_OK;
   854    876   }
   855    877   
   856    878   /*
   857    879   ** Return the rowid for the current row.
................................................................................
  1548   1570     }
  1549   1571     return rc;
  1550   1572   }
  1551   1573   
  1552   1574   static int zipfileRollback(sqlite3_vtab *pVtab){
  1553   1575     return zipfileCommit(pVtab);
  1554   1576   }
         1577  +
         1578  +static ZipfileCsr *zipfileFindCursor(ZipfileTab *pTab, i64 iId){
         1579  +  ZipfileCsr *pCsr;
         1580  +  for(pCsr=pTab->pCsrList; pCsr; pCsr=pCsr->pCsrNext){
         1581  +    if( iId==pCsr->iId ) break;
         1582  +  }
         1583  +  return pCsr;
         1584  +}
         1585  +
         1586  +static void zipfileFunctionCds(
         1587  +  sqlite3_context *context,
         1588  +  int argc,
         1589  +  sqlite3_value **argv
         1590  +){
         1591  +  ZipfileCsr *pCsr;
         1592  +  ZipfileTab *pTab = (ZipfileTab*)sqlite3_user_data(context);
         1593  +  assert( argc>0 );
         1594  +
         1595  +  pCsr = zipfileFindCursor(pTab, sqlite3_value_int64(argv[0]));
         1596  +  if( pCsr ){
         1597  +    ZipfileCDS *p = &pCsr->cds;
         1598  +    char *zRes = sqlite3_mprintf("{"
         1599  +        "\"version-made-by\" : %u, "
         1600  +        "\"version-to-extract\" : %u, "
         1601  +        "\"flags\" : %u, "
         1602  +        "\"compression\" : %u, "
         1603  +        "\"time\" : %u, "
         1604  +        "\"date\" : %u, "
         1605  +        "\"crc32\" : %u, "
         1606  +        "\"compressed-size\" : %u, "
         1607  +        "\"uncompressed-size\" : %u, "
         1608  +        "\"file-name-length\" : %u, "
         1609  +        "\"extra-field-length\" : %u, "
         1610  +        "\"file-comment-length\" : %u, "
         1611  +        "\"disk-number-start\" : %u, "
         1612  +        "\"internal-attr\" : %u, "
         1613  +        "\"external-attr\" : %u, "
         1614  +        "\"offset\" : %u }",
         1615  +        (u32)p->iVersionMadeBy, (u32)p->iVersionExtract,
         1616  +        (u32)p->flags, (u32)p->iCompression,
         1617  +        (u32)p->mTime, (u32)p->mDate,
         1618  +        (u32)p->crc32, (u32)p->szCompressed,
         1619  +        (u32)p->szUncompressed, (u32)p->nFile,
         1620  +        (u32)p->nExtra, (u32)p->nComment,
         1621  +        (u32)p->iDiskStart, (u32)p->iInternalAttr,
         1622  +        (u32)p->iExternalAttr, (u32)p->iOffset
         1623  +    );
         1624  +
         1625  +    if( zRes==0 ){
         1626  +      sqlite3_result_error_nomem(context);
         1627  +    }else{
         1628  +      sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT);
         1629  +      sqlite3_free(zRes);
         1630  +    }
         1631  +  }
         1632  +}
         1633  +
         1634  +
         1635  +/*
         1636  +** xFindFunction method.
         1637  +*/
         1638  +static int zipfileFindFunction(
         1639  +  sqlite3_vtab *pVtab,            /* Virtual table handle */
         1640  +  int nArg,                       /* Number of SQL function arguments */
         1641  +  const char *zName,              /* Name of SQL function */
         1642  +  void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */
         1643  +  void **ppArg                    /* OUT: User data for *pxFunc */
         1644  +){
         1645  +  if( nArg>0 ){
         1646  +    if( sqlite3_stricmp("zipfile_cds", zName)==0 ){
         1647  +      *pxFunc = zipfileFunctionCds;
         1648  +      *ppArg = (void*)pVtab;
         1649  +      return 1;
         1650  +    }
         1651  +  }
         1652  +
         1653  +  return 0;
         1654  +}
  1555   1655   
  1556   1656   /*
  1557   1657   ** Register the "zipfile" virtual table.
  1558   1658   */
  1559   1659   static int zipfileRegister(sqlite3 *db){
  1560   1660     static sqlite3_module zipfileModule = {
  1561   1661       1,                         /* iVersion */
................................................................................
  1572   1672       zipfileColumn,             /* xColumn - read data */
  1573   1673       zipfileRowid,              /* xRowid - read data */
  1574   1674       zipfileUpdate,             /* xUpdate */
  1575   1675       zipfileBegin,              /* xBegin */
  1576   1676       0,                         /* xSync */
  1577   1677       zipfileCommit,             /* xCommit */
  1578   1678       zipfileRollback,           /* xRollback */
  1579         -    0,                         /* xFindMethod */
         1679  +    zipfileFindFunction,       /* xFindMethod */
  1580   1680       0,                         /* xRename */
  1581   1681     };
  1582   1682   
  1583   1683     int rc = sqlite3_create_module(db, "zipfile"  , &zipfileModule, 0);
         1684  +  if( rc==SQLITE_OK ){
         1685  +    rc = sqlite3_overload_function(db, "zipfile_cds", -1);
         1686  +  }
  1584   1687     return rc;
  1585   1688   }
  1586   1689   #else         /* SQLITE_OMIT_VIRTUALTABLE */
  1587   1690   # define zipfileRegister(x) SQLITE_OK
  1588   1691   #endif
  1589   1692   
  1590   1693   #ifdef _WIN32