xref: /sqlite-3.40.0/test/zipfile2.test (revision 6ab91a7a)
12f7260deSdan# 2018 January 30
22f7260deSdan#
32f7260deSdan# The author disclaims copyright to this source code.  In place of
42f7260deSdan# a legal notice, here is a blessing:
52f7260deSdan#
62f7260deSdan#    May you do good and not evil.
72f7260deSdan#    May you find forgiveness for yourself and forgive others.
82f7260deSdan#    May you share freely, never taking more than you give.
92f7260deSdan#
102f7260deSdan#***********************************************************************
112f7260deSdan#
122f7260deSdan
13b5a4a705Smistachkinpackage require Tcl 8.6
14b5a4a705Smistachkin
152f7260deSdanset testdir [file dirname $argv0]
162f7260deSdansource $testdir/tester.tcl
172f7260deSdanset testprefix zipfile2
182f7260deSdan
192f7260deSdanifcapable !vtab {
202f7260deSdan  finish_test; return
212f7260deSdan}
222f7260deSdanif {[catch {load_static_extension db zipfile} error]} {
232f7260deSdan  puts "Skipping zipfile2 tests, hit load error: $error"
242f7260deSdan  finish_test; return
252f7260deSdan}
262f7260deSdan
272f7260deSdanproc blobliteral {str} {
282f7260deSdan  set concat [string map {" " "" "\n" ""} $str]
292f7260deSdan  return "X'$concat'"
302f7260deSdan}
312f7260deSdan
322f7260deSdanproc blob {str} {
332f7260deSdan  binary decode hex $str
342f7260deSdan}
352f7260deSdan
362f7260deSdanproc findall {needle haystack} {
372f7260deSdan  set L [list]
382f7260deSdan  set start 0
392f7260deSdan  while { [set idx [string first $needle $haystack $start]]>=0 } {
402f7260deSdan    lappend L $idx
412f7260deSdan    set start [expr $idx+1]
422f7260deSdan  }
432f7260deSdan  set L
442f7260deSdan}
452f7260deSdan
462f7260deSdando_execsql_test 1.0 {
472f7260deSdan  CREATE VIRTUAL TABLE aaa USING zipfile('testzip');
482f7260deSdan  CREATE VIRTUAL TABLE bbb USING zipfile("testzip");
492f7260deSdan  CREATE VIRTUAL TABLE ccc USING zipfile(`testzip`);
502f7260deSdan  CREATE VIRTUAL TABLE ddd USING zipfile([testzip]);
512f7260deSdan  CREATE VIRTUAL TABLE eee USING zipfile(testzip);
522f7260deSdan  CREATE VIRTUAL TABLE fff USING zipfile('test''zip');
532f7260deSdan}
542f7260deSdan
552f7260deSdando_test 2.0 {
562f7260deSdan  forcedelete testdir
572f7260deSdan  file mkdir testdir
582f7260deSdan  execsql { CREATE VIRTUAL TABLE hhh USING zipfile('testdir') }
59*a67d02f5Sdan  lindex [catchsql {
60*a67d02f5Sdan    SELECT * FROM hhh;
61*a67d02f5Sdan    INSERT INTO hhh(name, data) VALUES('1.txt', 'file data');
62*a67d02f5Sdan  }] 0
63*a67d02f5Sdan} 1
642f7260deSdan
652f7260deSdan
662f7260deSdanset archive {
672f7260deSdan  504B0304140000080000D4A52BEC09F3B6E0110000001100000005000900612E
682f7260deSdan  747874555405000140420F00636F6E74656E7473206F6620612E747874504B03
692f7260deSdan  04140000080000D4A52BECD98916A7110000001100000005000900622E747874
702f7260deSdan  555405000140420F00636F6E74656E7473206F6620622E747874504B01021E03
712f7260deSdan  140000080000D4A52BEC09F3B6E0110000001100000005000900000000000000
722f7260deSdan  0000A48100000000612E747874555405000140420F00504B01021E0314000008
732f7260deSdan  0000D4A52BECD98916A71100000011000000050009000000000000000000A481
742f7260deSdan  3D000000622E747874555405000140420F00504B050600000000020002007800
752f7260deSdan  00007A0000000000
762f7260deSdan}
772f7260deSdan
7844091ed3Sdanif 0 {
7944091ed3Sdan  # This test is broken - the archive generated is slightly different
8044091ed3Sdan  # depending on the zlib version used.
812f7260deSdan  do_execsql_test 3.1 {
822f7260deSdan    WITH contents(name,mtime,data) AS (
832f7260deSdan        VALUES('a.txt', 1000000, 'contents of a.txt') UNION ALL
842f7260deSdan        VALUES('b.txt', 1000000, 'contents of b.txt')
852f7260deSdan    ) SELECT quote( zipfile(name,NULL,mtime,data) ) FROM contents;
862f7260deSdan  } [blobliteral $archive]
8744091ed3Sdan}
8844091ed3Sdan
892f7260deSdan
902f7260deSdanset blob [blob $archive]
912f7260deSdando_execsql_test 3.2 {
922f7260deSdan  SELECT name,mtime,data FROM zipfile($blob)
932f7260deSdan} {
942f7260deSdan  a.txt 1000000 {contents of a.txt}
952f7260deSdan  b.txt 1000000 {contents of b.txt}
962f7260deSdan}
972f7260deSdan
982f7260deSdan# Corrupt each of the 0x50 0x4B (ascii "PK") headers in the file
992f7260deSdan# Test that in each case this causes an error.
1002f7260deSdan#
1012f7260deSdanset L [findall 504B $archive]
1022f7260deSdanfor {set i 0} {$i < [llength $L]} {incr i} {
1032f7260deSdan  set idx [lindex $L $i]
1042f7260deSdan  set a [string replace $archive $idx [expr $idx+3] 0000]
1052f7260deSdan  set blob [blob $a]
1062f7260deSdan  do_catchsql_test 3.3.$i {
1072f7260deSdan    SELECT name,mtime,data FROM zipfile($blob)
1082f7260deSdan  } {/1 .*/}
1092f7260deSdan}
1102f7260deSdan
11144091ed3Sdan# Change the "extra info id" for all extended-timestamp fields.
1122f7260deSdanset L [findall 5554 $archive]
1132f7260deSdanfor {set i 0} {$i < [llength $L]} {incr i} {
1142f7260deSdan  set idx [lindex $L $i]
1152f7260deSdan  set a [string replace $archive $idx [expr $idx+3] 1234]
1162f7260deSdan  set blob [blob $a]
1172f7260deSdan  do_execsql_test 3.4.$i {
1182f7260deSdan    SELECT name,data FROM zipfile($blob)
1192f7260deSdan  } {
1202f7260deSdan    a.txt {contents of a.txt}
1212f7260deSdan    b.txt {contents of b.txt}
1222f7260deSdan  }
1232f7260deSdan}
1242f7260deSdan
1252f7260deSdanfor {set i 0} {$i < [llength $L]} {incr i} {
1262f7260deSdan  set idx [lindex $L $i]
1272f7260deSdan  set a [string replace $archive [expr $idx+8] [expr $idx+9] 00]
1282f7260deSdan  set blob [blob $a]
1292f7260deSdan  do_execsql_test 3.5.$i {
1302f7260deSdan    SELECT name,data FROM zipfile($blob)
1312f7260deSdan  } {
1322f7260deSdan    a.txt {contents of a.txt}
1332f7260deSdan    b.txt {contents of b.txt}
1342f7260deSdan  }
1352f7260deSdan}
1362f7260deSdan
13744091ed3Sdan# set blob [db one {
13844091ed3Sdan#   WITH contents(name,mtime,data) AS (
13944091ed3Sdan#     VALUES('a.txt', 1000000, 'aaaaaaaaaaaaaaaaaaaaaaa')
14044091ed3Sdan#   ) SELECT quote( zipfile(name,NULL,mtime,data) ) FROM contents;
14144091ed3Sdan# }]
14244091ed3Sdan# set blob [string range $blob 2 end]
14344091ed3Sdan# set blob [string range $blob 0 end-1]
14444091ed3Sdan# while {[string length $blob]>0} {
14544091ed3Sdan#   puts [string range $blob 0 63]
14644091ed3Sdan#   set blob [string range $blob 64 end]
14744091ed3Sdan# }
14844091ed3Sdan# exit
1492f7260deSdan
1502f7260deSdanset archive2 {
1512f7260deSdan  504B0304140000080800D4A52BEC08F54C6E050000001700000005000900612E
1522f7260deSdan  747874555405000140420F004B4CC40A00504B01021E03140000080800D4A52B
1532f7260deSdan  EC08F54C6E0500000017000000050009000000000000000000A4810000000061
1542f7260deSdan  2E747874555405000140420F00504B050600000000010001003C000000310000
1552f7260deSdan  000000
1562f7260deSdan}
1572f7260deSdanset blob [blob $archive2]
1582f7260deSdando_execsql_test 4.0 {
1592f7260deSdan  SELECT name,mtime,data,method FROM zipfile($blob)
1602f7260deSdan} {
1612f7260deSdan  a.txt 1000000 aaaaaaaaaaaaaaaaaaaaaaa 8
1622f7260deSdan}
1632f7260deSdan
1642f7260deSdanset L [findall 17000000 $archive2]
1652f7260deSdanset a $archive2
1662f7260deSdanforeach i $L { set a [string replace $a $i [expr $i+7] 16000000] }
1672f7260deSdanset blob [blob $a]
1682f7260deSdando_catchsql_test 4.1 {
1692f7260deSdan  SELECT name,mtime,data,method FROM zipfile($blob)
170099fa847Sdan} {1 {inflate() failed (0)}}
1712f7260deSdan
17215daa6b5Sdan# Check the response to an unknown compression method (set data to NULL).
17315daa6b5Sdanset blob [blob [string map {0800 0900} $archive2]]
17415daa6b5Sdando_execsql_test 4.2 {
17515daa6b5Sdan  SELECT name,mtime,data IS NULL,method FROM zipfile($blob)
17615daa6b5Sdan} {a.txt 1000000 1 9}
17715daa6b5Sdan
17815daa6b5Sdan# Corrupt the EOCDS signature bytes in various ways.
17915daa6b5Sdanforeach {tn sub} {
18015daa6b5Sdan  1 {504B0500}
18115daa6b5Sdan  2 {504B0006}
18215daa6b5Sdan  3 {50000506}
18315daa6b5Sdan  4 {004B0506}
18415daa6b5Sdan} {
18515daa6b5Sdan  set blob [blob [string map [list 504B0506 $sub] $archive2]]
18615daa6b5Sdan  do_catchsql_test 4.3.$tn {
18715daa6b5Sdan    SELECT * FROM zipfile($blob)
18815daa6b5Sdan  } {1 {cannot find end of central directory record}}
18915daa6b5Sdan}
19015daa6b5Sdan
19115daa6b5Sdan#-------------------------------------------------------------------------
19215daa6b5Sdan# Test that a zero-length file with a '/' at the end is treated as
19315daa6b5Sdan# a directory (data IS NULL). Even if the mode doesn't indicate
19415daa6b5Sdan# that it is a directory.
19515daa6b5Sdan
19615daa6b5Sdando_test 5.0 {
19715daa6b5Sdan  set blob [db one {
19815daa6b5Sdan    WITH c(n, d) AS (
19915daa6b5Sdan      SELECT 'notadir', ''
20015daa6b5Sdan    )
20115daa6b5Sdan    SELECT zipfile(n, d) FROM c
20215daa6b5Sdan }]
20315daa6b5Sdan
20415daa6b5Sdan  set hex [binary encode hex $blob]
20515daa6b5Sdan  set hex [string map {6e6f7461646972 6e6f746164692f} $hex]
20615daa6b5Sdan  set blob2 [binary decode hex $hex]
20715daa6b5Sdan
20815daa6b5Sdan  execsql { SELECT name, data IS NULL FROM zipfile($blob2) }
20915daa6b5Sdan} {notadi/ 1}
2102f7260deSdan
211d30830e4Sdan#-------------------------------------------------------------------------
212d30830e4Sdan# Test that duplicate entries may not be created using UPDATE
213d30830e4Sdan# statements.
214d30830e4Sdan#
215d30830e4Sdanforcedelete test.zip
216d30830e4Sdando_execsql_test 6.0 {
217d30830e4Sdan  CREATE VIRTUAL TABLE temp.zip USING zipfile('test.zip');
218d30830e4Sdan  INSERT INTO temp.zip (name,data) VALUES ('test1','test');
219d30830e4Sdan  INSERT INTO temp.zip (name,data) VALUES ('test2','test');
220d30830e4Sdan}
221d30830e4Sdando_catchsql_test 6.1 {
222d30830e4Sdan  UPDATE temp.zip SET name='test1' WHERE name='test2'
223d30830e4Sdan} {1 {duplicate name: "test1"}}
224d30830e4Sdan
225d30830e4Sdanforcedelete test.zip
226d30830e4Sdando_catchsql_test 6.2 {
227d30830e4Sdan  DROP TABLE zip;
228d30830e4Sdan  CREATE VIRTUAL TABLE temp.zip USING zipfile('test.zip');
229d30830e4Sdan  INSERT INTO temp.zip (name,data) VALUES ('test','test');
230d30830e4Sdan  UPDATE  temp.zip set name=name||'new' where name='test';
231d30830e4Sdan  INSERT INTO temp.zip (name,data) VALUES ('test','test');
232d30830e4Sdan  UPDATE  temp.zip set name=name||'new' where name='test';
233d30830e4Sdan} {1 {duplicate name: "testnew"}}
234d30830e4Sdan
23593c803e9Sdanforcedelete test.zip
23693c803e9Sdando_execsql_test 6.3 {
23793c803e9Sdan  INSERT INTO temp.zip (name,data) VALUES ('test1','test');
23893c803e9Sdan  INSERT INTO temp.zip (name,data) VALUES ('test2','test');
23993c803e9Sdan  UPDATE OR REPLACE zip SET name='test2' WHERE name='test1';
24093c803e9Sdan  SELECT name FROM zip;
24193c803e9Sdan} {test2}
24244091ed3Sdan
2432f7260deSdanfinish_test
244