data-zip.lua /size: 10 Kb    last modification: 2020-07-01 14:35
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
data-zip
'
]
=
{
2
version
=
1
.
001
,
3
comment
=
"
companion to luat-lib.mkiv
"
,
4
author
=
"
Hans Hagen, PRAGMA-ADE, Hasselt NL
"
,
5
copyright
=
"
PRAGMA ADE / ConTeXt Development Team
"
,
6
license
=
"
see context related readme files
"
7
}
8 9
-- real old code ... partly redone .. needs testing due to changes as well as a decent overhaul
10 11
local
format
,
find
,
match
=
string
.
format
,
string
.
find
,
string
.
match
12 13
local
trace_locating
=
false
trackers
.
register
(
"
resolvers.locating
"
,
function
(
v
)
trace_locating
=
v
end
)
14 15
local
report_zip
=
logs
.
reporter
(
"
resolvers
"
,
"
zip
"
)
16 17
--[[ldx-- 18<p>We use a url syntax for accessing the zip file itself and file in it:</p> 19 20<typing> 21zip:///oeps.zip?name=bla/bla.tex 22zip:///oeps.zip?tree=tex/texmf-local 23zip:///texmf.zip?tree=/tex/texmf 24zip:///texmf.zip?tree=/tex/texmf-local 25zip:///texmf-mine.zip?tree=/tex/texmf-projects 26</typing> 27--ldx]]
--
28 29
local
resolvers
=
resolvers
30
local
findfile
=
resolvers
.
findfile
31
local
registerfile
=
resolvers
.
registerfile
32
local
splitmethod
=
resolvers
.
splitmethod
33
local
prependhash
=
resolvers
.
prependhash
34
local
starttiming
=
resolvers
.
starttiming
35
local
extendtexmf
=
resolvers
.
extendtexmfvariable
36
local
stoptiming
=
resolvers
.
stoptiming
37 38
local
urlquery
=
url
.
query
39 40
zip
=
zip
or
{
}
41
local
zip
=
zip
42 43
local
archives
=
zip
.
archives
or
{
}
44
zip
.
archives
=
archives
45 46
local
registeredfiles
=
zip
.
registeredfiles
or
{
}
47
zip
.
registeredfiles
=
registeredfiles
48 49
local
zipfiles
=
utilities
.
zipfiles
50 51
local
openzip
,
closezip
,
validfile
,
wholefile
,
filehandle
,
traversezip
52 53
if
zipfiles
then
54 55
local
ipairs
=
ipairs
56 57
openzip
=
zipfiles
.
open
58
closezip
=
zipfiles
.
close
59
validfile
=
zipfiles
.
found
60
wholefile
=
zipfiles
.
unzip
61 62
local
listzip
=
zipfiles
.
list
63 64
traversezip
=
function
(
zfile
)
65
return
ipairs
(
listzip
(
zfile
)
)
66
end
67 68
local
streams
=
utilities
.
streams
69
local
openstream
=
streams
.
open
70
local
readstring
=
streams
.
readstring
71
local
streamsize
=
streams
.
size
72 73
local
metatable
=
{
74
close
=
streams
.
close
,
75
read
=
function
(
stream
,
n
)
76
readstring
(
stream
,
n
=
=
"
*a
"
and
streamsize
(
stream
)
or
n
)
77
end
78
}
79 80
filehandle
=
function
(
zfile
,
queryname
)
81
local
data
=
wholefile
(
zfile
,
queryname
)
82
if
data
then
83
local
stream
=
openstream
(
data
)
84
if
stream
then
85
return
setmetatableindex
(
stream
,
metatable
)
86
end
87
end
88
end
89 90
else
91 92
openzip
=
zip
.
open
93
closezip
=
zip
.
close
94 95
validfile
=
function
(
zfile
,
queryname
)
96
local
dfile
=
zfile
:
open
(
queryname
)
97
if
dfile
then
98
dfile
:
close
(
)
99
return
true
100
end
101
return
false
102
end
103 104
traversezip
=
function
(
zfile
)
105
return
z
:
files
(
)
106
end
107 108
wholefile
=
function
(
zfile
,
queryname
)
109
local
dfile
=
zfile
:
open
(
queryname
)
110
if
dfile
then
111
local
s
=
dfile
:
read
(
"
*all
"
)
112
dfile
:
close
(
)
113
return
s
114
end
115
end
116 117
filehandle
=
function
(
zfile
,
queryname
)
118
local
dfile
=
zfile
:
open
(
queryname
)
119
if
dfile
then
120
return
dfile
121
end
122
end
123 124
end
125 126
local
function
validzip
(
str
)
-- todo: use url splitter
127
if
not
find
(
str
,
"
^zip://
"
)
then
128
return
"
zip:///
"
.
.
str
129
else
130
return
str
131
end
132
end
133 134
local
function
openarchive
(
name
)
135
if
not
name
or
name
=
=
"
"
then
136
return
nil
137
else
138
local
arch
=
archives
[
name
]
139
if
not
arch
then
140
local
full
=
findfile
(
name
)
or
"
"
141
arch
=
full
~
=
"
"
and
openzip
(
full
)
or
false
142
archives
[
name
]
=
arch
143
end
144
return
arch
145
end
146
end
147 148
local
function
closearchive
(
name
)
149
if
not
name
or
(
name
=
=
"
"
and
archives
[
name
]
)
then
150
closezip
(
archives
[
name
]
)
151
archives
[
name
]
=
nil
152
end
153
end
154 155
zip
.
openarchive
=
openarchive
156
zip
.
closearchive
=
closearchive
157 158
function
resolvers
.
locators
.
zip
(
specification
)
159
local
archive
=
specification
.
filename
160
local
zipfile
=
archive
and
archive
~
=
"
"
and
openarchive
(
archive
)
-- tricky, could be in to be initialized tree
161
if
trace_locating
then
162
if
zipfile
then
163
report_zip
(
"
locator: archive %a found
"
,
archive
)
164
else
165
report_zip
(
"
locator: archive %a not found
"
,
archive
)
166
end
167
end
168
end
169 170
function
resolvers
.
concatinators
.
zip
(
zipfile
,
path
,
name
)
-- ok ?
171
if
not
path
or
path
=
=
"
"
then
172
return
format
(
'
%s?name=%s
'
,
zipfile
,
name
)
173
else
174
return
format
(
'
%s?name=%s/%s
'
,
zipfile
,
path
,
name
)
175
end
176
end
177 178
local
finders
=
resolvers
.
finders
179
local
notfound
=
finders
.
notfound
180 181
function
finders
.
zip
(
specification
)
182
local
original
=
specification
.
original
183
local
archive
=
specification
.
filename
184
if
archive
then
185
local
query
=
urlquery
(
specification
.
query
)
186
local
queryname
=
query
.
name
187
if
queryname
then
188
local
zfile
=
openarchive
(
archive
)
189
if
zfile
then
190
if
trace_locating
then
191
report_zip
(
"
finder: archive %a found
"
,
archive
)
192
end
193
if
validfile
(
zfile
,
queryname
)
then
194
if
trace_locating
then
195
report_zip
(
"
finder: file %a found
"
,
queryname
)
196
end
197
return
specification
.
original
198
elseif
trace_locating
then
199
report_zip
(
"
finder: file %a not found
"
,
queryname
)
200
end
201
elseif
trace_locating
then
202
report_zip
(
"
finder: unknown archive %a
"
,
archive
)
203
end
204
end
205
end
206
if
trace_locating
then
207
report_zip
(
"
finder: %a not found
"
,
original
)
208
end
209
return
notfound
(
)
210
end
211 212
local
openers
=
resolvers
.
openers
213
local
notfound
=
openers
.
notfound
214
local
textopener
=
openers
.
helpers
.
textopener
215 216
function
openers
.
zip
(
specification
)
217
local
original
=
specification
.
original
218
local
archive
=
specification
.
filename
219
if
archive
then
220
local
query
=
urlquery
(
specification
.
query
)
221
local
queryname
=
query
.
name
222
if
queryname
then
223
local
zfile
=
openarchive
(
archive
)
224
if
zfile
then
225
if
trace_locating
then
226
report_zip
(
"
opener; archive %a opened
"
,
archive
)
227
end
228
local
handle
=
filehandle
(
zfile
,
queryname
)
229
if
handle
then
230
if
trace_locating
then
231
report_zip
(
"
opener: file %a found
"
,
queryname
)
232
end
233
return
textopener
(
'
zip
'
,
original
,
handle
)
234
elseif
trace_locating
then
235
report_zip
(
"
opener: file %a not found
"
,
queryname
)
236
end
237
elseif
trace_locating
then
238
report_zip
(
"
opener: unknown archive %a
"
,
archive
)
239
end
240
end
241
end
242
if
trace_locating
then
243
report_zip
(
"
opener: %a not found
"
,
original
)
244
end
245
return
notfound
(
)
246
end
247 248
local
loaders
=
resolvers
.
loaders
249
local
notfound
=
loaders
.
notfound
250 251
function
loaders
.
zip
(
specification
)
252
local
original
=
specification
.
original
253
local
archive
=
specification
.
filename
254
if
archive
then
255
local
query
=
urlquery
(
specification
.
query
)
256
local
queryname
=
query
.
name
257
if
queryname
then
258
local
zfile
=
openarchive
(
archive
)
259
if
zfile
then
260
if
trace_locating
then
261
report_zip
(
"
loader: archive %a opened
"
,
archive
)
262
end
263
local
data
=
wholefile
(
zfile
,
queryname
)
264
if
data
then
265
if
trace_locating
then
266
report_zip
(
"
loader; file %a loaded
"
,
original
)
267
end
268
return
true
,
data
,
#
data
269
elseif
trace_locating
then
270
report_zip
(
"
loader: file %a not found
"
,
queryname
)
271
end
272
elseif
trace_locating
then
273
report_zip
(
"
loader; unknown archive %a
"
,
archive
)
274
end
275
end
276
end
277
if
trace_locating
then
278
report_zip
(
"
loader: %a not found
"
,
original
)
279
end
280
return
notfound
(
)
281
end
282 283
-- zip:///somefile.zip
284
-- zip:///somefile.zip?tree=texmf-local -> mount
285 286
local
function
registerzipfile
(
z
,
tree
)
287
local
names
=
{
}
288
local
files
=
{
}
-- somewhat overkill .. todo
289
local
remap
=
{
}
-- somewhat overkill .. todo
290
local
n
=
0
291
local
filter
=
tree
=
=
"
"
and
"
^(.+)/(.-)$
"
or
format
(
"
^%s/(.+)/(.-)$
"
,
tree
)
292
if
trace_locating
then
293
report_zip
(
"
registering: using filter %a
"
,
filter
)
294
end
295
starttiming
(
)
296
for
i
in
traversezip
(
z
)
do
297
local
filename
=
i
.
filename
298
local
path
,
name
=
match
(
filename
,
filter
)
299
if
not
path
then
300
n
=
n
+
1
301
registerfile
(
names
,
filename
,
"
"
)
302
local
usedname
=
lower
(
filename
)
303
files
[
usedname
]
=
"
"
304
if
usedname
~
=
filename
then
305
remap
[
usedname
]
=
filename
306
end
307
elseif
name
and
name
~
=
"
"
then
308
n
=
n
+
1
309
register
(
names
,
name
,
path
)
310
local
usedname
=
lower
(
name
)
311
files
[
usedname
]
=
path
312
if
usedname
~
=
name
then
313
remap
[
usedname
]
=
name
314
end
315
else
316
-- directory
317
end
318
end
319
stoptiming
(
)
320
report_zip
(
"
registering: %s files registered
"
,
n
)
321
return
{
322
-- metadata = { },
323
files
=
files
,
324
remap
=
remap
,
325
}
326
end
327 328
local
function
usezipfile
(
archive
)
329
local
specification
=
splitmethod
(
archive
)
-- to be sure
330
local
archive
=
specification
.
filename
331
if
archive
and
not
registeredfiles
[
archive
]
then
332
local
z
=
openarchive
(
archive
)
333
if
z
then
334
local
tree
=
urlquery
(
specification
.
query
)
.
tree
or
"
"
335
if
trace_locating
then
336
report_zip
(
"
registering: archive %a
"
,
archive
)
337
end
338
prependhash
(
'
zip
'
,
archive
)
339
extendtexmf
(
archive
)
-- resets hashes too
340
registeredfiles
[
archive
]
=
z
341
registerfilehash
(
archive
,
registerzipfile
(
z
,
tree
)
)
342
elseif
trace_locating
then
343
report_zip
(
"
registering: unknown archive %a
"
,
archive
)
344
end
345
elseif
trace_locating
then
346
report_zip
(
"
registering: archive %a not found
"
,
archive
)
347
end
348
end
349 350
resolvers
.
usezipfile
=
usezipfile
351
resolvers
.
registerzipfile
=
registerzipfile
352 353
function
resolvers
.
hashers
.
zip
(
specification
)
354
local
archive
=
specification
.
filename
355
if
trace_locating
then
356
report_zip
(
"
loading file %a
"
,
archive
)
357
end
358
usezipfile
(
specification
.
original
)
359
end
360