dan | 2f7260d | 2018-01-30 17:43:22 +0000 | [diff] [blame] | 1 | # 2018 January 30 |
| 2 | # |
| 3 | # The author disclaims copyright to this source code. In place of |
| 4 | # a legal notice, here is a blessing: |
| 5 | # |
| 6 | # May you do good and not evil. |
| 7 | # May you find forgiveness for yourself and forgive others. |
| 8 | # May you share freely, never taking more than you give. |
| 9 | # |
| 10 | #*********************************************************************** |
| 11 | # |
| 12 | |
mistachkin | b5a4a70 | 2018-03-16 23:54:26 +0000 | [diff] [blame] | 13 | package require Tcl 8.6 |
| 14 | |
dan | 2f7260d | 2018-01-30 17:43:22 +0000 | [diff] [blame] | 15 | set testdir [file dirname $argv0] |
| 16 | source $testdir/tester.tcl |
| 17 | set testprefix zipfile2 |
| 18 | |
| 19 | ifcapable !vtab { |
| 20 | finish_test; return |
| 21 | } |
| 22 | if {[catch {load_static_extension db zipfile} error]} { |
| 23 | puts "Skipping zipfile2 tests, hit load error: $error" |
| 24 | finish_test; return |
| 25 | } |
| 26 | |
| 27 | proc blobliteral {str} { |
| 28 | set concat [string map {" " "" "\n" ""} $str] |
| 29 | return "X'$concat'" |
| 30 | } |
| 31 | |
| 32 | proc blob {str} { |
| 33 | binary decode hex $str |
| 34 | } |
| 35 | |
| 36 | proc findall {needle haystack} { |
| 37 | set L [list] |
| 38 | set start 0 |
| 39 | while { [set idx [string first $needle $haystack $start]]>=0 } { |
| 40 | lappend L $idx |
| 41 | set start [expr $idx+1] |
| 42 | } |
| 43 | set L |
| 44 | } |
| 45 | |
| 46 | do_execsql_test 1.0 { |
| 47 | CREATE VIRTUAL TABLE aaa USING zipfile('testzip'); |
| 48 | CREATE VIRTUAL TABLE bbb USING zipfile("testzip"); |
| 49 | CREATE VIRTUAL TABLE ccc USING zipfile(`testzip`); |
| 50 | CREATE VIRTUAL TABLE ddd USING zipfile([testzip]); |
| 51 | CREATE VIRTUAL TABLE eee USING zipfile(testzip); |
| 52 | CREATE VIRTUAL TABLE fff USING zipfile('test''zip'); |
| 53 | } |
| 54 | |
| 55 | do_test 2.0 { |
| 56 | forcedelete testdir |
| 57 | file mkdir testdir |
| 58 | execsql { CREATE VIRTUAL TABLE hhh USING zipfile('testdir') } |
dan | a67d02f | 2018-04-19 20:06:10 +0000 | [diff] [blame] | 59 | lindex [catchsql { |
| 60 | SELECT * FROM hhh; |
| 61 | INSERT INTO hhh(name, data) VALUES('1.txt', 'file data'); |
| 62 | }] 0 |
| 63 | } 1 |
dan | 2f7260d | 2018-01-30 17:43:22 +0000 | [diff] [blame] | 64 | |
| 65 | |
| 66 | set archive { |
| 67 | 504B0304140000080000D4A52BEC09F3B6E0110000001100000005000900612E |
| 68 | 747874555405000140420F00636F6E74656E7473206F6620612E747874504B03 |
| 69 | 04140000080000D4A52BECD98916A7110000001100000005000900622E747874 |
| 70 | 555405000140420F00636F6E74656E7473206F6620622E747874504B01021E03 |
| 71 | 140000080000D4A52BEC09F3B6E0110000001100000005000900000000000000 |
| 72 | 0000A48100000000612E747874555405000140420F00504B01021E0314000008 |
| 73 | 0000D4A52BECD98916A71100000011000000050009000000000000000000A481 |
| 74 | 3D000000622E747874555405000140420F00504B050600000000020002007800 |
| 75 | 00007A0000000000 |
| 76 | } |
| 77 | |
dan | 44091ed | 2018-01-31 19:13:31 +0000 | [diff] [blame] | 78 | if 0 { |
| 79 | # This test is broken - the archive generated is slightly different |
| 80 | # depending on the zlib version used. |
| 81 | do_execsql_test 3.1 { |
| 82 | WITH contents(name,mtime,data) AS ( |
| 83 | VALUES('a.txt', 1000000, 'contents of a.txt') UNION ALL |
| 84 | VALUES('b.txt', 1000000, 'contents of b.txt') |
| 85 | ) SELECT quote( zipfile(name,NULL,mtime,data) ) FROM contents; |
| 86 | } [blobliteral $archive] |
| 87 | } |
| 88 | |
dan | 2f7260d | 2018-01-30 17:43:22 +0000 | [diff] [blame] | 89 | |
| 90 | set blob [blob $archive] |
| 91 | do_execsql_test 3.2 { |
| 92 | SELECT name,mtime,data FROM zipfile($blob) |
| 93 | } { |
| 94 | a.txt 1000000 {contents of a.txt} |
| 95 | b.txt 1000000 {contents of b.txt} |
| 96 | } |
| 97 | |
| 98 | # Corrupt each of the 0x50 0x4B (ascii "PK") headers in the file |
| 99 | # Test that in each case this causes an error. |
| 100 | # |
| 101 | set L [findall 504B $archive] |
| 102 | for {set i 0} {$i < [llength $L]} {incr i} { |
| 103 | set idx [lindex $L $i] |
| 104 | set a [string replace $archive $idx [expr $idx+3] 0000] |
| 105 | set blob [blob $a] |
| 106 | do_catchsql_test 3.3.$i { |
| 107 | SELECT name,mtime,data FROM zipfile($blob) |
| 108 | } {/1 .*/} |
| 109 | } |
| 110 | |
dan | 44091ed | 2018-01-31 19:13:31 +0000 | [diff] [blame] | 111 | # Change the "extra info id" for all extended-timestamp fields. |
dan | 2f7260d | 2018-01-30 17:43:22 +0000 | [diff] [blame] | 112 | set L [findall 5554 $archive] |
| 113 | for {set i 0} {$i < [llength $L]} {incr i} { |
| 114 | set idx [lindex $L $i] |
| 115 | set a [string replace $archive $idx [expr $idx+3] 1234] |
| 116 | set blob [blob $a] |
| 117 | do_execsql_test 3.4.$i { |
| 118 | SELECT name,data FROM zipfile($blob) |
| 119 | } { |
| 120 | a.txt {contents of a.txt} |
| 121 | b.txt {contents of b.txt} |
| 122 | } |
| 123 | } |
| 124 | |
| 125 | for {set i 0} {$i < [llength $L]} {incr i} { |
| 126 | set idx [lindex $L $i] |
| 127 | set a [string replace $archive [expr $idx+8] [expr $idx+9] 00] |
| 128 | set blob [blob $a] |
| 129 | do_execsql_test 3.5.$i { |
| 130 | SELECT name,data FROM zipfile($blob) |
| 131 | } { |
| 132 | a.txt {contents of a.txt} |
| 133 | b.txt {contents of b.txt} |
| 134 | } |
| 135 | } |
| 136 | |
dan | 44091ed | 2018-01-31 19:13:31 +0000 | [diff] [blame] | 137 | # set blob [db one { |
| 138 | # WITH contents(name,mtime,data) AS ( |
| 139 | # VALUES('a.txt', 1000000, 'aaaaaaaaaaaaaaaaaaaaaaa') |
| 140 | # ) SELECT quote( zipfile(name,NULL,mtime,data) ) FROM contents; |
| 141 | # }] |
| 142 | # set blob [string range $blob 2 end] |
| 143 | # set blob [string range $blob 0 end-1] |
| 144 | # while {[string length $blob]>0} { |
| 145 | # puts [string range $blob 0 63] |
| 146 | # set blob [string range $blob 64 end] |
| 147 | # } |
| 148 | # exit |
dan | 2f7260d | 2018-01-30 17:43:22 +0000 | [diff] [blame] | 149 | |
| 150 | set archive2 { |
| 151 | 504B0304140000080800D4A52BEC08F54C6E050000001700000005000900612E |
| 152 | 747874555405000140420F004B4CC40A00504B01021E03140000080800D4A52B |
| 153 | EC08F54C6E0500000017000000050009000000000000000000A4810000000061 |
| 154 | 2E747874555405000140420F00504B050600000000010001003C000000310000 |
| 155 | 000000 |
| 156 | } |
| 157 | set blob [blob $archive2] |
| 158 | do_execsql_test 4.0 { |
| 159 | SELECT name,mtime,data,method FROM zipfile($blob) |
| 160 | } { |
| 161 | a.txt 1000000 aaaaaaaaaaaaaaaaaaaaaaa 8 |
| 162 | } |
| 163 | |
dan | 2f7260d | 2018-01-30 17:43:22 +0000 | [diff] [blame] | 164 | set L [findall 17000000 $archive2] |
| 165 | set a $archive2 |
| 166 | foreach i $L { set a [string replace $a $i [expr $i+7] 16000000] } |
| 167 | set blob [blob $a] |
| 168 | do_catchsql_test 4.1 { |
| 169 | SELECT name,mtime,data,method FROM zipfile($blob) |
dan | 099fa84 | 2018-01-30 18:33:23 +0000 | [diff] [blame] | 170 | } {1 {inflate() failed (0)}} |
dan | 2f7260d | 2018-01-30 17:43:22 +0000 | [diff] [blame] | 171 | |
dan | 15daa6b | 2018-02-01 19:41:23 +0000 | [diff] [blame] | 172 | # Check the response to an unknown compression method (set data to NULL). |
| 173 | set blob [blob [string map {0800 0900} $archive2]] |
| 174 | do_execsql_test 4.2 { |
| 175 | SELECT name,mtime,data IS NULL,method FROM zipfile($blob) |
| 176 | } {a.txt 1000000 1 9} |
| 177 | |
| 178 | # Corrupt the EOCDS signature bytes in various ways. |
| 179 | foreach {tn sub} { |
| 180 | 1 {504B0500} |
| 181 | 2 {504B0006} |
| 182 | 3 {50000506} |
| 183 | 4 {004B0506} |
| 184 | } { |
| 185 | set blob [blob [string map [list 504B0506 $sub] $archive2]] |
| 186 | do_catchsql_test 4.3.$tn { |
| 187 | SELECT * FROM zipfile($blob) |
| 188 | } {1 {cannot find end of central directory record}} |
| 189 | } |
| 190 | |
| 191 | #------------------------------------------------------------------------- |
| 192 | # Test that a zero-length file with a '/' at the end is treated as |
| 193 | # a directory (data IS NULL). Even if the mode doesn't indicate |
| 194 | # that it is a directory. |
| 195 | |
| 196 | do_test 5.0 { |
| 197 | set blob [db one { |
| 198 | WITH c(n, d) AS ( |
| 199 | SELECT 'notadir', '' |
| 200 | ) |
| 201 | SELECT zipfile(n, d) FROM c |
| 202 | }] |
| 203 | |
| 204 | set hex [binary encode hex $blob] |
| 205 | set hex [string map {6e6f7461646972 6e6f746164692f} $hex] |
| 206 | set blob2 [binary decode hex $hex] |
| 207 | |
| 208 | execsql { SELECT name, data IS NULL FROM zipfile($blob2) } |
| 209 | } {notadi/ 1} |
dan | 2f7260d | 2018-01-30 17:43:22 +0000 | [diff] [blame] | 210 | |
dan | d30830e | 2018-03-20 12:12:06 +0000 | [diff] [blame] | 211 | #------------------------------------------------------------------------- |
| 212 | # Test that duplicate entries may not be created using UPDATE |
| 213 | # statements. |
| 214 | # |
| 215 | forcedelete test.zip |
| 216 | do_execsql_test 6.0 { |
| 217 | CREATE VIRTUAL TABLE temp.zip USING zipfile('test.zip'); |
| 218 | INSERT INTO temp.zip (name,data) VALUES ('test1','test'); |
| 219 | INSERT INTO temp.zip (name,data) VALUES ('test2','test'); |
| 220 | } |
| 221 | do_catchsql_test 6.1 { |
| 222 | UPDATE temp.zip SET name='test1' WHERE name='test2' |
| 223 | } {1 {duplicate name: "test1"}} |
| 224 | |
| 225 | forcedelete test.zip |
| 226 | do_catchsql_test 6.2 { |
| 227 | DROP TABLE zip; |
| 228 | CREATE VIRTUAL TABLE temp.zip USING zipfile('test.zip'); |
| 229 | INSERT INTO temp.zip (name,data) VALUES ('test','test'); |
| 230 | UPDATE temp.zip set name=name||'new' where name='test'; |
| 231 | INSERT INTO temp.zip (name,data) VALUES ('test','test'); |
| 232 | UPDATE temp.zip set name=name||'new' where name='test'; |
| 233 | } {1 {duplicate name: "testnew"}} |
| 234 | |
dan | 93c803e | 2018-03-20 13:26:01 +0000 | [diff] [blame] | 235 | forcedelete test.zip |
| 236 | do_execsql_test 6.3 { |
| 237 | INSERT INTO temp.zip (name,data) VALUES ('test1','test'); |
| 238 | INSERT INTO temp.zip (name,data) VALUES ('test2','test'); |
| 239 | UPDATE OR REPLACE zip SET name='test2' WHERE name='test1'; |
| 240 | SELECT name FROM zip; |
| 241 | } {test2} |
dan | 44091ed | 2018-01-31 19:13:31 +0000 | [diff] [blame] | 242 | |
dan | 2f7260d | 2018-01-30 17:43:22 +0000 | [diff] [blame] | 243 | finish_test |