Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Improved error messages from the zipfile extension. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
f634a7e386918b829389f20c330d3123 |
User & Date: | drh 2018-03-10 13:21:41.393 |
Context
2018-03-10
| ||
14:17 | Add support for INSERT OR REPLACE and INSERT OR IGNORE on the zipfile extension. (check-in: 8ad35d483e user: drh tags: trunk) | |
13:21 | Improved error messages from the zipfile extension. (check-in: f634a7e386 user: drh tags: trunk) | |
12:53 | Avoid harmless left-shifts of negative numbers in the zipfile extension when building ZIP archives of files with pre-DOS dates. (check-in: 16bba8650c user: drh tags: trunk) | |
Changes
Changes to ext/misc/zipfile.c.
︙ | ︙ | |||
469 470 471 472 473 474 475 | return SQLITE_OK; } /* ** Set the error message for the virtual table associated with cursor ** pCsr to the results of vprintf(zFmt, ...). */ | > > > > > > > | > | 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 | return SQLITE_OK; } /* ** Set the error message for the virtual table associated with cursor ** pCsr to the results of vprintf(zFmt, ...). */ static void zipfileTableErr(ZipfileTab *pTab, const char *zFmt, ...){ va_list ap; va_start(ap, zFmt); sqlite3_free(pTab->base.zErrMsg); pTab->base.zErrMsg = sqlite3_vmprintf(zFmt, ap); va_end(ap); } static void zipfileCursorErr(ZipfileCsr *pCsr, const char *zFmt, ...){ va_list ap; va_start(ap, zFmt); sqlite3_free(pCsr->base.pVtab->zErrMsg); pCsr->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap); va_end(ap); } /* ** Read nRead bytes of data from offset iOff of file pFile into buffer ** aRead[]. Return SQLITE_OK if successful, or an SQLite error code |
︙ | ︙ | |||
1234 1235 1236 1237 1238 1239 1240 | int bInMemory = 0; /* True for an in-memory zipfile */ zipfileResetCursor(pCsr); if( pTab->zFile ){ zFile = pTab->zFile; }else if( idxNum==0 ){ | | | | 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 | int bInMemory = 0; /* True for an in-memory zipfile */ zipfileResetCursor(pCsr); if( pTab->zFile ){ zFile = pTab->zFile; }else if( idxNum==0 ){ zipfileCursorErr(pCsr, "zipfile() function requires an argument"); return SQLITE_ERROR; }else if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){ const u8 *aBlob = (const u8*)sqlite3_value_blob(argv[0]); int nBlob = sqlite3_value_bytes(argv[0]); assert( pTab->pFirstEntry==0 ); rc = zipfileLoadDirectory(pTab, aBlob, nBlob); pCsr->pFreeEntry = pTab->pFirstEntry; pTab->pFirstEntry = pTab->pLastEntry = 0; if( rc!=SQLITE_OK ) return rc; bInMemory = 1; }else{ zFile = (const char*)sqlite3_value_text(argv[0]); } if( 0==pTab->pWriteFd && 0==bInMemory ){ pCsr->pFile = fopen(zFile, "rb"); if( pCsr->pFile==0 ){ zipfileCursorErr(pCsr, "cannot open file: %s", zFile); rc = SQLITE_ERROR; }else{ rc = zipfileReadEOCD(pTab, 0, 0, pCsr->pFile, &pCsr->eocd); if( rc==SQLITE_OK ){ if( pCsr->eocd.nEntry==0 ){ pCsr->bEof = 1; }else{ |
︙ | ︙ | |||
1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 | if( z[i]==zTemplate[i] ) mode |= 1 << (9-i); else if( z[i]!='-' ) goto parse_error; } } if( ((mode & S_IFDIR)==0)==bIsDir ){ /* The "mode" attribute is a directory, but data has been specified. ** Or vice-versa - no data but "mode" is a file or symlink. */ return SQLITE_CONSTRAINT; } *pMode = mode; return SQLITE_OK; parse_error: *pzErr = sqlite3_mprintf("zipfile: parse error in mode: %s", z); | > | 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 | if( z[i]==zTemplate[i] ) mode |= 1 << (9-i); else if( z[i]!='-' ) goto parse_error; } } if( ((mode & S_IFDIR)==0)==bIsDir ){ /* The "mode" attribute is a directory, but data has been specified. ** Or vice-versa - no data but "mode" is a file or symlink. */ *pzErr = sqlite3_mprintf("zipfile: mode does not match data"); return SQLITE_CONSTRAINT; } *pMode = mode; return SQLITE_OK; parse_error: *pzErr = sqlite3_mprintf("zipfile: parse error in mode: %s", z); |
︙ | ︙ | |||
1531 1532 1533 1534 1535 1536 1537 | } assert( pOld->pNext ); } } if( nVal>1 ){ /* Check that "sz" and "rawdata" are both NULL: */ | | > > > | < > > | 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 | } assert( pOld->pNext ); } } if( nVal>1 ){ /* Check that "sz" and "rawdata" are both NULL: */ if( sqlite3_value_type(apVal[5])!=SQLITE_NULL ){ zipfileTableErr(pTab, "sz must be NULL"); rc = SQLITE_CONSTRAINT; } if( sqlite3_value_type(apVal[6])!=SQLITE_NULL ){ zipfileTableErr(pTab, "rawdata must be NULL"); rc = SQLITE_CONSTRAINT; } if( rc==SQLITE_OK ){ if( sqlite3_value_type(apVal[7])==SQLITE_NULL ){ /* data=NULL. A directory */ bIsDir = 1; }else{ /* Value specified for "data", and possibly "method". This must be ** a regular file or a symlink. */ const u8 *aIn = sqlite3_value_blob(apVal[7]); int nIn = sqlite3_value_bytes(apVal[7]); int bAuto = sqlite3_value_type(apVal[8])==SQLITE_NULL; iMethod = sqlite3_value_int(apVal[8]); sz = nIn; pData = aIn; nData = nIn; if( iMethod!=0 && iMethod!=8 ){ zipfileTableErr(pTab, "unknown compression method: %d", iMethod); rc = SQLITE_CONSTRAINT; }else{ if( bAuto || iMethod ){ int nCmp; rc = zipfileDeflate(aIn, nIn, &pFree, &nCmp, &pTab->base.zErrMsg); if( rc==SQLITE_OK ){ if( iMethod || nCmp<nIn ){ |
︙ | ︙ | |||
1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 | } /* Check that we're not inserting a duplicate entry */ if( pOld==0 && rc==SQLITE_OK ){ ZipfileEntry *p; for(p=pTab->pFirstEntry; p; p=p->pNext){ if( zipfileComparePath(p->cds.zFile, zPath, nPath)==0 ){ rc = SQLITE_CONSTRAINT; break; } } } if( rc==SQLITE_OK ){ | > | 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 | } /* Check that we're not inserting a duplicate entry */ if( pOld==0 && rc==SQLITE_OK ){ ZipfileEntry *p; for(p=pTab->pFirstEntry; p; p=p->pNext){ if( zipfileComparePath(p->cds.zFile, zPath, nPath)==0 ){ zipfileTableErr(pTab, "duplicate name: \"%s\"", zPath); rc = SQLITE_CONSTRAINT; break; } } } if( rc==SQLITE_OK ){ |
︙ | ︙ |
Changes to test/zipfile.test.
︙ | ︙ | |||
146 147 148 149 150 151 152 | 5 data {} 0 {} 0 6 method {} 0 {} 0 } do_catchsql_test 1.1.0.1 { INSERT INTO zz(name, mode, mtime, sz, rawdata, method) VALUES('f.txt', '-rw-r--r--', 1000000000, 5, 'abcde', 0); | | | | | | 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | 5 data {} 0 {} 0 6 method {} 0 {} 0 } do_catchsql_test 1.1.0.1 { INSERT INTO zz(name, mode, mtime, sz, rawdata, method) VALUES('f.txt', '-rw-r--r--', 1000000000, 5, 'abcde', 0); } {1 {rawdata must be NULL}} do_catchsql_test 1.1.0.2 { INSERT INTO zz(name, mtime, sz, data, method) VALUES('g.txt', 1000000002, 5, '12345', 0); } {1 {sz must be NULL}} do_catchsql_test 1.1.0.3 { INSERT INTO zz(name, mtime, rawdata, method) VALUES('g.txt', 1000000002, '12345', 0); } {1 {rawdata must be NULL}} do_catchsql_test 1.1.0.4 { INSERT INTO zz(name, data, method) VALUES('g.txt', '12345', 7); } {1 {unknown compression method: 7}} do_execsql_test 1.1.1 { INSERT INTO zz(name, mode, mtime, data, method) VALUES('f.txt', '-rw-r--r--', 1000000000, 'abcde', 0); } do_execsql_test 1.1.2 { INSERT INTO zz(name, mode, mtime, data, method) |
︙ | ︙ | |||
283 284 285 286 287 288 289 | blue.txt/ 16877 1000000000 {} 0 h.txt 33189 1000000004 aaaaaaaaaabbbbbbbbbb 8 i.txt 33188 4 zxcvb 0 } do_catchsql_test 1.6.7 { UPDATE zz SET data=NULL WHERE name='i.txt' | | | 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 | blue.txt/ 16877 1000000000 {} 0 h.txt 33189 1000000004 aaaaaaaaaabbbbbbbbbb 8 i.txt 33188 4 zxcvb 0 } do_catchsql_test 1.6.7 { UPDATE zz SET data=NULL WHERE name='i.txt' } {1 {zipfile: mode does not match data}} do_execsql_test 1.6.8 { SELECT name, mode, mtime, data, method FROM zipfile('test.zip'); } { blue.txt/ 16877 1000000000 {} 0 h.txt 33189 1000000004 aaaaaaaaaabbbbbbbbbb 8 i.txt 33188 4 zxcvb 0 } |
︙ | ︙ | |||
394 395 396 397 398 399 400 | foreach {tn fname} { 1 dir1 2 file1 3 dir1/file2 } { do_catchsql_test 3.1.$tn.0 { INSERT INTO x1(name, data) VALUES($fname, NULL); | | | | | 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 | foreach {tn fname} { 1 dir1 2 file1 3 dir1/file2 } { do_catchsql_test 3.1.$tn.0 { INSERT INTO x1(name, data) VALUES($fname, NULL); } [list 1 "duplicate name: \"$fname/\""] do_catchsql_test 3.1.$tn.1 { INSERT INTO x1(name, data) VALUES($fname || '/', NULL); } [list 1 "duplicate name: \"$fname/\""] do_catchsql_test 3.1.$tn.2 { INSERT INTO x1(name, data) VALUES($fname, 'abcd'); } [list 1 "duplicate name: \"$fname\""] } do_catchsql_test 3.2 { SELECT rowid FROM x1 } {1 {no such column: rowid}} #------------------------------------------------------------------------- |
︙ | ︙ | |||
633 634 635 636 637 638 639 | VALUES('dir3//') UNION ALL VALUES('dir4///') UNION ALL VALUES('/') ) SELECT name FROM zipfile((SELECT zipfile(nm, NULL) FROM src)) } {dir1/ dir2/ dir3/ dir4/ /} finish_test | < | 633 634 635 636 637 638 639 | VALUES('dir3//') UNION ALL VALUES('dir4///') UNION ALL VALUES('/') ) SELECT name FROM zipfile((SELECT zipfile(nm, NULL) FROM src)) } {dir1/ dir2/ dir3/ dir4/ /} finish_test |