if not modules then modules = { } end modules ['data-zip'] = { version = 1.001, comment = "companion to luat-lib.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", license = "see context related readme files" } local format, find, match = string.format, string.find, string.match local unpack = unpack or table.unpack local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end) -- zip:///oeps.zip?name=bla/bla.tex -- zip:///oeps.zip?tree=tex/texmf-local -- zip:///texmf.zip?tree=/tex/texmf -- zip:///texmf.zip?tree=/tex/texmf-local -- zip:///texmf-mine.zip?tree=/tex/texmf-projects zip = zip or { } zip.archives = zip.archives or { } zip.registeredfiles = zip.registeredfiles or { } local finders, openers, loaders = resolvers.finders, resolvers.openers, resolvers.loaders local locators, hashers, concatinators = resolvers.locators, resolvers.hashers, resolvers.concatinators local archives = zip.archives local function validzip(str) -- todo: use url splitter if not find(str,"^zip://") then return "zip:///" .. str else return str end end function zip.openarchive(name) if not name or name == "" then return nil else local arch = archives[name] if not arch then local full = resolvers.find_file(name) or "" arch = (full ~= "" and zip.open(full)) or false archives[name] = arch end return arch end end function zip.closearchive(name) if not name or (name == "" and archives[name]) then zip.close(archives[name]) archives[name] = nil end end function locators.zip(specification) -- where is this used? startup zips (untested) specification = resolvers.splitmethod(specification) local zipfile = specification.path local zfile = zip.openarchive(name) -- tricky, could be in to be initialized tree if trace_locating then if zfile then logs.report("fileio","zip locator, archive '%s' found",specification.original) else logs.report("fileio","zip locator, archive '%s' not found",specification.original) end end end function hashers.zip(tag,name) if trace_locating then logs.report("fileio","loading zip file '%s' as '%s'",name,tag) end resolvers.usezipfile(format("%s?tree=%s",tag,name)) end function concatinators.zip(tag,path,name) if not path or path == "" then return format('%s?name=%s',tag,name) else return format('%s?name=%s/%s',tag,path,name) end end function resolvers.isreadable.zip(name) return true end function finders.zip(specification,filetype) specification = resolvers.splitmethod(specification) if specification.path then local q = url.query(specification.query) if q.name then local zfile = zip.openarchive(specification.path) if zfile then if trace_locating then logs.report("fileio","zip finder, archive '%s' found",specification.path) end local dfile = zfile:open(q.name) if dfile then dfile = zfile:close() if trace_locating then logs.report("fileio","zip finder, file '%s' found",q.name) end return specification.original elseif trace_locating then logs.report("fileio","zip finder, file '%s' not found",q.name) end elseif trace_locating then logs.report("fileio","zip finder, unknown archive '%s'",specification.path) end end end if trace_locating then logs.report("fileio","zip finder, '%s' not found",filename) end return unpack(finders.notfound) end function openers.zip(specification) local zipspecification = resolvers.splitmethod(specification) if zipspecification.path then local q = url.query(zipspecification.query) if q.name then local zfile = zip.openarchive(zipspecification.path) if zfile then if trace_locating then logs.report("fileio","zip opener, archive '%s' opened",zipspecification.path) end local dfile = zfile:open(q.name) if dfile then logs.show_open(specification) if trace_locating then logs.report("fileio","zip opener, file '%s' found",q.name) end return openers.text_opener(specification,dfile,'zip') elseif trace_locating then logs.report("fileio","zip opener, file '%s' not found",q.name) end elseif trace_locating then logs.report("fileio","zip opener, unknown archive '%s'",zipspecification.path) end end end if trace_locating then logs.report("fileio","zip opener, '%s' not found",filename) end return unpack(openers.notfound) end function loaders.zip(specification) specification = resolvers.splitmethod(specification) if specification.path then local q = url.query(specification.query) if q.name then local zfile = zip.openarchive(specification.path) if zfile then if trace_locating then logs.report("fileio","zip loader, archive '%s' opened",specification.path) end local dfile = zfile:open(q.name) if dfile then logs.show_load(filename) if trace_locating then logs.report("fileio","zip loader, file '%s' loaded",filename) end local s = dfile:read("*all") dfile:close() return true, s, #s elseif trace_locating then logs.report("fileio","zip loader, file '%s' not found",q.name) end elseif trace_locating then logs.report("fileio","zip loader, unknown archive '%s'",specification.path) end end end if trace_locating then logs.report("fileio","zip loader, '%s' not found",filename) end return unpack(openers.notfound) end -- zip:///somefile.zip -- zip:///somefile.zip?tree=texmf-local -> mount function resolvers.usezipfile(zipname) zipname = validzip(zipname) local specification = resolvers.splitmethod(zipname) local zipfile = specification.path if zipfile and not zip.registeredfiles[zipname] then local tree = url.query(specification.query).tree or "" local z = zip.openarchive(zipfile) if z then local instance = resolvers.instance if trace_locating then logs.report("fileio","zip registering, registering archive '%s'",zipname) end statistics.starttiming(instance) resolvers.prepend_hash('zip',zipname,zipfile) resolvers.extend_texmf_var(zipname) -- resets hashes too zip.registeredfiles[zipname] = z instance.files[zipname] = resolvers.register_zip_file(z,tree or "") statistics.stoptiming(instance) elseif trace_locating then logs.report("fileio","zip registering, unknown archive '%s'",zipname) end elseif trace_locating then logs.report("fileio","zip registering, '%s' not found",zipname) end end function resolvers.register_zip_file(z,tree) local files, filter = { }, "" if tree == "" then filter = "^(.+)/(.-)$" else filter = format("^%s/(.+)/(.-)$",tree) end if trace_locating then logs.report("fileio","zip registering, using filter '%s'",filter) end local register, n = resolvers.register_file, 0 for i in z:files() do local path, name = match(i.filename,filter) if path then if name and name ~= '' then register(files, name, path) n = n + 1 else -- directory end else register(files, i.filename, '') n = n + 1 end end logs.report("fileio","zip registering, %s files registered",n) return files end