included commits to RCS files with non-trunk default branches.
--- /dev/null
+<h2> Configuration </h2> of other projects using zziplib
+
+<!--border--> <date> February 2003 </date>
+
+<P>
+ If using the zziplib with other project then you can use a number
+ of possibility to configure and link. The zziplib had been usually
+ included within the projects that made use of it - some did even
+ pick up the advantage to be allowed to staticlink in a limited
+ set of conditions. Recently however, the zziplib is shipped as a
+ standard library of various linux/freebsd distros - mostly for
+ the usage by the php-zip module. This allows third party software
+ makers to link to the preinstalled library in the system and
+ consequently reduce the memory consumption - even more than now
+ with the zziplib being a lightweight anyway (the i386 .so is
+ usually less than 20k)
+</P>
+
+<h3> pkg-config --libs </h3>
+
+<P>
+ Within modern software development, one should be advised to use
+ pkg-config as soon as it is available. The pkg-config helper can
+ handle a lot of problems that can usually come up with linking
+ to third party libraries in case that those link again dynamically
+ with other libraries themselves. It does correctly order the
+ list of "libs", it can throw away duplicate "-L" hints, and same
+ for cflags "-I" hints, plus it will throw away some sys-includes
+ that gcc3.2 will warn about with a false positive.
+</P>
+<P>
+ There is a number of pkg-config targets installed in the system
+ but the one you want to use is <b>pkg-config zziplib</b>.
+ Therefore, a simple Makefile could read like
+ <pre>
+ PROGRAM = my_prog
+ CFLAGS = -Dhappy `pkg-config zziplib --cflags`
+ LIBS = -Wl,-E `pkg-config zziplib --libs`
+
+ my_prog.o : my_prog.c
+ $(CC) $(CFLAGS) $< -o $@
+ my_prog : my_prog.o
+ $(LINK) $< $(LIBS)
+ </pre>
+</P>
+<P>
+ The `pkg-config zziplibs --libs` will usually expand to
+ something like <code>-lzzip -lz</code> which are the
+ two (!!) libraries that you need to link with - in that
+ order. The zziplib builds on top of the z-lib algorithms
+ for compression of files within the zip-archive. That's
+ the same for other lib-parts of the zziplib project as
+ well, e.g. the sdl-rwops part which does also need to
+ link with the sdl-lib - and that's where the pkg-config
+ infrastructure can be of great help. That's the reason
+ why zziplib installs a few more ".pc" files, you can
+ get a list of them like this:
+ <pre>
+ $ pkg-config --list-all | sort | grep zzip
+ zziplib zziplib - ZZipLib - libZ-based ZIP-access Library
+ zzip-sdl-config zzip-sdl-config - SDL Config (for ZZipLib)
+ zzip-sdl-rwops zzip-sdl-rwops - SDL_rwops for ZZipLib
+ zzipwrap zzipwrap - Callback Wrappers for ZZipLib
+ zzip-zlib-config zzip-zlib-config - ZLib Config (for ZZipLib)
+ </pre>
+ The two entries like "zzip-sdl-config" and "zzip-zlib-config"
+ happen to be ".pc" files for the libz.so and libSDL.so that
+ were seen at configure-time of zziplib - you may want to reuse
+ these in your projects as well whenever you need to link to
+ either of zlib or libsdl even in places where there is no direct
+ need for zziplib. It basically looks like:
+ <pre>
+ $ pkg-config zzip-zlib-config --modversion
+ 1.1.4
+ $ pkg-config zzip-zlib-config --libs
+ -lz
+ </pre>
+</P>
+
+<h3> zzip-config </h3>
+<P>
+ The pkg-config ".pc" files are relativly young in the history of
+ zziplib. A long time before that there was the `zzip-config`
+ script installed in the system. These `*-config` were common
+ before the pkg-config came about, and in fact the pkg-config
+ infrastructure was invented to flatten away the problems of
+ using multiple `*-config` scripts for a project. As long as you
+ do not combine multiple `*-config`s then it should be well okay
+ to use the `zzip-config` directly - it does also kill another
+ dependency on the `pkg-config` tool to build your project, the
+ zziplib is all that's needed.
+</P>
+<P>
+ In its call-structure the `zzip-config` script uses the same
+ options as `pkg-config`, (well they are historic cousins anyway).
+ and that simply means you can replace each call above like
+ `pkg-config zziplib...` with `zzip-config...`.
+
+ <pre>
+ PROGRAM = my_prog
+ CFLAGS = -Dhappy `zzip-config --cflags`
+ LIBS = -Wl,-E `zzip-config --libs`
+
+ my_prog.o : my_prog.c
+ $(CC) $(CFLAGS) $< -o $@
+ my_prog : my_prog.o
+ $(LINK) $< $(LIBS)
+ </pre>
+</P>
+<P>
+ Be informed that the zzip-config script is low-maintained and
+ starting with 2004 it will be replaced with a one-line script
+ that simply reads `pkg-config zziplib $*`. By that time the
+ rpm/deb packages will also list "pkgconfig" as a dependency
+ on the zziplib-devel/zziplib-dev part.
+</P>
+
+<h3> autoconf macro </h3>
+
+<P>
+ There is currently an autoconf macro installed along into
+ the usual /usr/share/aclocal space for making it easier for
+ you to pick up the configure-time cflags/libs needed to
+ build/link with zziplib. In any way it does look like
+ this:
+ <pre>
+ dnl PKG_CHECK_ZZIPLIB(ZSTUFF, min-version, action-if, action-not)
+ AC_DEFUN([PKG_CHECK_ZZIPLIB],[dnl
+ PKG_CHECK_MODULES([$1], [zziplib $2], [$3], [$4])])
+ </pre>
+</P>
+<P>
+ You are strongly advised to take advantage of the pkgconfig's
+ macro directly - you can find the macro in
+ <code>/usr/share/aclocal/pkg.m4</code> and it allows to
+ combine the flags of a list of library modules that you
+ want to have. If it is only zziplib, than you could simply
+ use this in your configure.ac:
+ <pre>
+ PKG_CHECK_MODULES([ZZIP],[zziplib >= 0.10.75])
+ </pre>
+ which will provide you with two autoconf/automake variables
+ named ZZIP_CFLAGS and ZZIP_LIBS respectivly.
+</P>
+<P>
+ Up to 2004, the macro in zziplib.m4 will be however carry
+ a copy of the pkg.m4 so that you do not need another
+ dependency for your software project. The macro is called
+ like shown above PKG_CHECK_ZZIPLIB and you would call it
+ like
+ <pre>PKG_CHECK_ZZIPLIB([ZZIP],[0.10.75])</pre>
+ which will give you the two autoconf/automake variables
+ as well, ZZIP_CFLAGS and ZZIP_LIBS.
+</P>
+
--- /dev/null
+<h2> ZZIP Programmers Interface </h2> The complete API description.
+
+<!--border--> <date> 20. July 2002 </date>
+
+<h3> Basics </h3>
+
+<P>
+ The naming schem of functions in this library follow a simple rule:
+ if you see a function with a <code>zzip_</code> prefix followed by
+ compact name representing otherwise a C library or posix function then
+ it is a magic wrapper that can automagically handle both real
+ files/directories or zip-contained files. This includes:
+</P>
+<table cellpadding=10 width=100%><tr><td><table border=1 width=100%>
+ <tr><td width=50%> zzip_opendir </td><td width=50%> opendir </td></tr>
+ <tr><td width=50%> zzip_readdir </td><td width=50%> readdir </td></tr>
+ <tr><td width=50%> zzip_closedir </td><td width=50%> closedir </td></tr>
+ <tr><td width=50%> zzip_rewinddir </td><td width=50%> rewinddir </td></tr>
+ <tr><td width=50%> zzip_telldir </td><td width=50%> telldir </td></tr>
+ <tr><td width=50%> zzip_seekdir </td><td width=50%> seekdir </td></tr>
+</table></td></tr></table>
+<P>
+ The ZZIP_DIR handle can wrap both a real directory or a zip-file.
+ Note that you can not open a virtual directory <em>within</em> a
+ zip-file, the ZZIP_DIR is either a real DIR-handle of a real
+ directory or the reference of ZIP-file but never a DIR-handle
+ within a ZIP-file - there is no such schema of a SUB-DIR handle
+ implemented in this library. A ZZIP_DIR does actually represent
+ the central directory of a ZIP-file, so that each file entry in
+ this ZZIP-DIR can possibly have a subpath prepended.
+</P>
+
+<P>
+ This form of magic has historic reasons as originally the
+ magic wrappers of this library were not meant to wrap a complete
+ subtree of a real file tree but only a single directory being
+ wrapped with into a zip-file and placed instead. Later proposals
+ and patches were coming in to support subtree wrapping by not
+ only making a split between the dir-part and file-part but
+ going recursivly up through all "/"-dirseparators of a filepath
+ given to <code>zzip_open</code> and looking for zip-file there.
+</P>
+
+<P>
+ To open a zip-file unconditionally one should be using their
+ respective methods that would return a ZZIP_DIR handle being
+ the representant memory instance of a ZIP-DIR, the central
+ directory of a zip-file. From that ZZIP-DIR one can open a
+ compressed file entry which will be returned as a ZZIP_FILE
+ pointer.
+</P>
+<table cellpadding=10 width=100%><tr><td><table border=1 width=100%>
+ <tr><td width=50%> zzip_dir_open </td>
+ <td width=50%> open a zip-file and parse the central directory
+ to a memory shadow</td></tr>
+ <tr><td width=50%> zzip_dir_close </td>
+ <td width=50%> close a zip-file and free the memory shadow</td></tr>
+ <tr><td width=50%> zzip_dir_fdopen </td>
+ <td width=50%> aquire the given posix-file and try to parse it
+ as a zip-file.</td></tr>
+ <tr><td width=50%> zzip_dir_read </td>
+ <td width=50%> return the next info entry of a zip-file's central
+ directory - this would include a possible subpath </td></tr>
+</table></td></tr></table>
+
+<P>
+ To unconditionally access a zipped-file (as the counter-part of a
+ zip-file's directory) you should be using the functions having a
+ <code>zzip_file_</code> prefix which are the methods working on
+ ZZIP_FILE pointers directly and assuming those are references of
+ a zipped file with a ZZIP_DIR.
+</P>
+<table cellpadding=10 width=100%><tr><td><table border=1 width=100%>
+ <tr><td width=50%> zzip_file_open </td>
+ <td width=50%> open a file within a zip and prepare a zlib
+ compressor for it - note the ZZIP_DIR argument,
+ multiple ZZIP_FILE's may share the same central
+ directory shadow.</td></tr>
+ <tr><td width=50%> zzip_file_close </td>
+ <td width=50%> close the handle of zippedfile
+ and free zlib compressor of it</td></tr>
+ <tr><td width=50%> zzip_file_read </td>
+ <td width=50%> decompress the next part of a compressed file
+ within a zip-file</td></tr>
+</table></td></tr></table>
+<P>
+ From here it is only a short step to the magic wrappers for
+ file-access - when being given a filepath to zzip_open then
+ the filepath is checked first for being possibly a real file
+ (we can often do that by a <code>stat</code> call) and if there is
+ a real file under that name then the returned ZZIP_FILE is
+ nothing more than a wrapper around a file-descriptor of the
+ underlying operating system. Any other calls like zzip_read
+ will see the realfd-flag in the ZZIP_FILE and forward the
+ execution to the read() function of the underlying operating system.
+</P>
+
+<P>
+ However if that fails then the filepath is cut at last directory
+ separator, i.e. a filepath of "this/test/README" is cut into the
+ dir-part "this/test" and a file-part "README". Then the possible
+ zip-extensions are attached (".zip" and ".ZIP") and we check if
+ there is a real file under that name. If a file "this/test.zip"
+ does exist then it is given to zzip_dir_open which will create
+ a ZZIP_DIR instance of it, and when that was successul (so it
+ was in zip-format) then we call zzip_file_open which will see
+ two arguments - the just opened ZZIP_DIR and the file-part. The
+ resulting ZZIP_FILE has its own copy of a ZZIP_DIR, so if you
+ open multiple files from the same zip-file than you will also
+ have multiple in-memory copies of the zip's central directory
+ whereas otherwise multiple ZZIP_FILE's may share a common
+ ZZIP_DIR when being opened with zzip_file_open directly - the
+ zzip_file_open's first argument is the ZZIP_DIR and the second
+ one the file-part to be looked up within that zip-directory.
+</P>
+
+<table cellpadding=10 width=100%><tr><td><table border=1 width=100%>
+ <tr><td width=50%> zzip_open </td>
+ <td width=50%> try the file-path as a real-file, and if not
+ there, look for the existance of ZZIP_DIR by
+ applying extensions, and open the file
+ contained within that one.</td></tr>
+ <tr><td width=50%> zzip_close </td>
+ <td width=50%> if the ZZIP_FILE wraps a real-file, then call
+ read(), otherwise call zzip_file_read() </td></tr>
+ <tr><td width=50%> zzip_close </td>
+ <td width=50%> if the ZZIP_FILE wraps a real-file, then call
+ close(), otherwise call zzip_file_close() </td></tr>
+</table></td></tr></table>
+
+<P>
+ Up to here we have the original functionality of the zziplib
+ when I (Guido Draheim) created the magic functions around the work from
+ Tomi Ollila who wrote the routines to read and decompress files from
+ a zip archive - unlike other libraries it was quite readable and
+ intelligible source code (after many changes there is not much
+ left of the original zip08x source code but that's another story).
+ Later however some request and proposals and patches were coming in.
+</P>
+
+<P>
+ Among the first extensions was the recursive zzip_open magic. In
+ the first instance, the library did just do as described above:
+ a file-path of "this/test/README" might be a zip-file known as
+ "this/test.zip" containing a compressed file "README". But if
+ there is neither a real file "this/test/README" and no real
+ zip-file "this/test.zip" then the call would have failed but
+ know the zzip_open call will recursivly check the parent
+ directories - so it can now find a zip-file "this.zip" which
+ contains a file-part "test/README".
+</P>
+
+<P>
+ This dissolves the original meaning of a ZZIP_DIR and it has lead
+ to some confusion later on - you can not create a DIRENT-like handle
+ for "this/test/" being within a "test.zip" file. And actually, I did
+ never see a reason to implement it so far (open "this.zip" and set
+ an initial subpath of "test" and let zzip_readdir skip all entries
+ that do not start with "test/"). This is left for excercie ;-)
+</P>
+
+<h3> Extras </h3>
+
+<P>
+ The next requests circulated around other file-extensions to
+ automagically look inside filetypes that have zip-format too but
+ carry other fileextensions - most famous might be the ".PK3"
+ files of ID's Quake game. There have been a number of these
+ requests and in a lot of cases it dawned to me that those guys
+ may have overlooked the zzip_dir_open functions to travel
+ through documents of zipformat under any name - that is that the
+ "magic" was not actually needed but they just wanted to read
+ files in zipformat with the zziplib.
+</P>
+
+<P>
+ Other requests circulated around encryption but I did reject
+ those bluntly, always. Instead there have been always examples
+ for doing some obfuscation around the zip-format so that the
+ stock zip/unzip tools do not recognize them but a game
+ software developer can pack/unpack his AI scripts and bitmaps
+ into such a zipformat-like file.
+</P>
+
+<P>
+ After some dead-end patches (being shipped along with the
+ zziplib as configure-time compile-options - greetings to
+ Lutz Sammer and Andreas Schiffler), the general approach
+ of _ext_io came up, and finally implemented (greetings go
+ to Mike Nordell). The _open()-calls do now each have a
+ cousin of _open_ext_io() with two/three additional arguments
+ being a set of extensions to loop through our magic testing,
+ a callback-handler plugin-table for obfuscation-means,
+ and (often) a bit-mask for extra-options - this bitmask even
+ has "PREFERZIP" and "ONLYZIP" options to skip the real-file
+ test magic in those <code>zzip_*open</code> functions.
+</P>
+
+<table cellpadding=10 width=100%><tr><td><table border=1 width=100%>
+ <tr><td width=50%> zzip_open(name,flags) </td>
+ <td width=50%> zzip_open_ext_io(name,flags,mode,ext,io) </td></tr>
+ <tr><td width=50%> zzip_opendir(name) </td>
+ <td width=50%> zzip_opendir_ext_io(name,mode,ext,io) </td></tr>
+ <tr><td width=50%> zzip_dir_open(name,errp) </td>
+ <td width=50%> zzip_dir_open_ext_io(name,errp,ext,io) </td></tr>
+ <tr><td width=50%> zzip_dir_fdopen(fd,errp) </td>
+ <td width=50%> zzip_dir_fdopen_ext_io(fd,errp,ext,io) </td></tr>
+ <tr><td width=50%> zzip_file_open(dir,name,mode) </td>
+ <td width=50%> zzip_file_open_ext_io(dir,name,mode,ext,io) </td></tr>
+</table></td></tr></table>
+
+<P>
+ Oh, and note that the mode,ext,io extras are memorized
+ in the respecitive ZZIP_DIR handle attached, so each
+ of the other calls like <code>zzip_file_open()</code>
+ and <code>zzip_read()</code> will be using them. There
+ are a few helper routines to help setup a new io-plugin
+ where the init_io will currently just memcopy the
+ default_io entries into the user-supplied plugin-struct.
+</P>
+
+<table cellpadding=10 width=100%><tr><td><table border=1 width=100%>
+ <tr><td width=50%> zzip_init_io </td>
+ <td width=50%> the recommended way to do things </td></tr>
+ <tr><td width=50%> zzip_get_default_io </td>
+ <td width=50%> used internally whenever you supply a null
+ for the io-argument of a _ext_io()-call </td></tr>
+ <tr><td width=50%> zzip_get_default_ext </td>
+ <td width=50%> used internally but not exported </td></tr>
+</table></td></tr></table>
+
+
+<P>
+ And last some stdio-like replacements were build but these
+ happen to be actually just small wrappers around the other
+ posix-like magic-calls. It just offers some convenience
+ since wrappers like "SDL_rwops" tend to use a stringised
+ open-mode - and I took the occasion to fold the zzip-bits
+ for the _ext_io-calls right in there recognized via
+ special extensions to the openmode-string of zzip_fopen().
+</P>
+
+<table cellpadding=10 width=100%><tr><td><table border=1 width=100%>
+ <tr><td width=50%> zzip_fopen </td>
+ <td width=50%> convert stringmode and call zzip_open_ext_io </td></tr>
+ <tr><td width=50%> zzip_fread </td>
+ <td width=50%> slower way to say zzip_read </td></tr>
+ <tr><td width=50%> zzip_fclose </td>
+ <td width=50%> a synonym of zzip_close </td></tr>
+</table></td></tr></table>
+
+<P>
+ For some reason, people did need the full set of function-calls()
+ to be working on zzip-wrappers too, so here they are - if the
+ ZZIP_FILE instance did wrap a real file, then the real posix-call
+ will be used, otherwise it is simulated on the compressed stream
+ with a zip-contained file - especially <code>seek()</code> can be
+ a slow operation:
+ if the new point is later then just read out more bytes till we
+ hit that position but if it is an earlier point then rewind to the
+ beginning of the compressed data and start reading/decompression
+ until the position is met.
+</P>
+
+<table cellpadding=10 width=100%><tr><td><table border=1 width=100%>
+ <tr><td width=50%> zzip_rewind </td>
+ <td width=50%> magic for rewind() </td></tr>
+ <tr><td width=50%> zzip_tell </td>
+ <td width=50%> magic for tell() </td></tr>
+ <tr><td width=50%> zzip_seek </td>
+ <td width=50%> magic for seek() </td></tr>
+</table></td></tr></table>
+
+<P>
+ And last not least, there are few informative functions to
+ use function-calls to read parts of the opaque structures
+ of zzip-objects and their zzip-factory.
+</P>
+
+<table cellpadding=10 width=100%><tr><td><table border=1 width=100%>
+ <tr><td width=50%> zzip_dir_stat </td>
+ <td width=50%> a stat()-like thing on a file within a ZZIP_DIR </td></tr>
+ <tr><td width=50%> zzip_dir_real </td>
+ <td width=50%> check if ZZIP_DIR wraps a stat'able posix-dirent</td></tr>
+ <tr><td width=50%> zzip_file_real </td>
+ <td width=50%> check if ZZIP_FILE wraps a stat'able posix-file </td></tr>
+ <tr><td width=50%> zzip_realdir </td>
+ <td width=50%> if zzip_dir_real then return the posix-dirent </td></tr>
+ <tr><td width=50%> zzip_realfd </td>
+ <td width=50%> if zzip_file_real then return the posix-file </td></tr>
+ <tr><td width=50%> zzip_dirhandle </td>
+ <td width=50%> the attached ZZIP_DIR of compressed ZZIP_FILE </td></tr>
+ <tr><td width=50%> zzip_dirfd </td>
+ <td width=50%> the attached posix-file of ZZIP_DIR zip-file </td></tr>
+ <tr><td width=50%> zzip_set_error </td>
+ <td width=50%> set the last ZZIP_DIR error-code </td></tr>
+ <tr><td width=50%> zzip_error </td>
+ <td width=50%> get the last ZZIP_DIR error-code </td></tr>
+ <tr><td width=50%> zzip_strerror </td>
+ <td width=50%> convert a zzip_error into a readable string </td></tr>
+ <tr><td width=50%> zzip_strerror_of </td>
+ <td width=50%> combine both above zzip_strerror of zzip_error </td></tr>
+ <tr><td width=50%> zzip_errno </td>
+ <td width=50%> helper to wrap a zzip-error to a posix-errno </td></tr>
+ <tr><td width=50%> zzip_compr_str </td>
+ <td width=50%> helper to wrap a compr-number to a readable string
+ </td></tr>
+ <tr><td width=50%> zzip_dir_free </td>
+ <td width=50%> internally called by zzip_dir_close if the ref-count
+ of the ZZIP_DIR has gone zero</td></tr>
+ <tr><td width=50%> zzip_freopen </td>
+ <td width=50%> to reuse the ZZIP_DIR from another ZZIP_FILE so it does
+ not need to be parsed again </td></tr>
+ <tr><td width=50%> zzip_open_shared_io </td>
+ <td width=50%> the ext/io cousin but it does not close the old ZZIP_FILE
+ and instead just shares the ZZIP_DIR if possible</td></tr>
+</table></td></tr></table>
+
--- /dev/null
+<h2> ZZIP-EXT/IO </h2> Customizing the file access
+
+<!--border--><date>15. July 2002 </date>
+
+<h3> The EXT/IO calls </h3>
+
+<P>
+ There were quite some requests from game developers and graphics-apps
+ developers who wanted various extensions to be included into the
+ <a href="zziplib.html">zziplib library</a>, but most of them were
+ only of specific usage. After some discussions we came up with a
+ model to customize the <a href="zziplib.html">zziplib library</a>
+ calls in a number of ways - and adding two or three arguments to
+ the zzip_* calls. The standard <a href="zziplib.html">zziplib library</a>
+ will actually call these *_ext_io functions with these extra arguments
+ to be set to zero.
+</P><P>
+ The EXT feature describes a way to customize the extensions used in
+ the magic wrapper to find a .ZIP file. It turned out that there are
+ quite a number of applications that did chose the zip file format as
+ their native document format and where just the file extension had
+ been changed. This includes file types like Quake3 ".PK3" files from
+ ID Software, the Java library files called ".JAR", and lately the
+ OpenOffice-6 (resp. StarOffice-6) documents which carry xml-files along.
+ Just build a zero-termined string-list of file-extensions and submit it
+ to the _ext_io calls to let the <a href="zziplib.html">zziplib</a> find
+ parts of those zip-documents automagically.
+</P><P>
+ In quite some of these cases, it is very benefical to make use of the
+ o_modes functionality that allows to submit extra bit-options into
+ the <a href="zziplib.html">zziplib</a> - this includes options like
+ <code>ZZIP_PREFERZIP</code> or even <code>ZZIP_ONLYZIP</code> which
+ modifies the default behaviour of looking for real files first instead
+ of some within a zipped directory tree. Other bit-options include
+ <code>ZZIP_CASELESS</code> to imitate win32-like filematching for a
+ zipped filetree.
+</P><P>
+ Other wishes on <a href="zziplib.html">zziplib</a> circulated around
+ <a href="zzip-xor.html">obfuscation</a> or access to zip-files wrapped
+ in other data areas including encrpyted resources from other applications.
+ This has been adressed with the IO-handlers that you can explicitly
+ submit to the *_ext_io functions - the default will be posix-IO
+ open/read/write and seek/tell. An application using
+ <a href="zziplib.html">zziplib</a> can divert these to its own set of
+ these calls - and it only needs to declare them on opening a zipped file.
+</P>
+
+<h3> The EXT stringlist </h3>
+
+<P>
+ Declaring an EXT stringlist is very simple as it is simply a
+ list of strings, the <a href="zziplib.html">zziplib</a> provides
+ you with a double-const <code>zzip_strings_t</code> type to help
+ you move a global declaration into the writeonly segment of your
+ app - it turned out that about all developers wanted just some
+ extensions on the default and they were fine with having them
+ global-const for their application, nothing like dynamically
+ modifying them. Well, you are still allowed to make it fully
+ dynamic... if you find a use case for that.
+</P><P>
+ Extending the magic zip-extensions is just done by adding the
+ additional extensions to be recognized - just remember to add
+ the uppercased variants too since those will be needed on
+ (unx-like) filesystems that are case-sensitive. In the internet
+ age, quite some downloaded will appear in uppercased format since
+ the other side declared it as that and that other end was happy
+ with it as being a (w32-like) case-insensitive server. Therefore,
+ it should look like <pre>
+ static zzip_strings_t my_ext[] = { ".zip", ".ZIP", ".jar", ".JAR", 0 };
+ </pre>
+</P><P>
+ There is one frequently asked question in this area - how to open
+ a zipped file as "test.zip/README" instead of "test/README". Other
+ than some people might expect, the library will not find it - if
+ you want to have that one needs a fileext list that contains the
+ empty string - not the zero string, an empty string that is. It
+ looks like <pre>
+ static zzip_strings_t my_ext[] = { ".zip", ".ZIP", "", 0 };
+ </pre>
+</P><P>
+ And last not least, people want to tell the libary to not try to
+ open a real file that lives side by side with the same path as the
+ file path that can be matched by the zziplib. Actually, the magic
+ wrappers were never meant to be used like - the developer should
+ have used zzip_dir_* functions to open a zip-file and the
+ zzip_file_* functions to read entries from that zip-file. However,
+ the magic-wrappers look rather more familiar, and so you will find
+ now a bit-option ZZIP_ONLYZIP that can be passed down to the _ext_io
+ variants of the magic-wrapper calls, and a real-file will never get
+ tested for existance. Actually, I would rather recommend that for
+ application data the option ZZIP_PREFERZIP, so that one can enter
+ debugging mode by unpacking the zip-file as a real directory tree
+ in the place of the original zip.
+</P>
+
+<h3> The IO handlers </h3>
+
+<P>
+ While you will find the zzip_plugin_io_t declared in the zziplib
+ headers, you are not advised to make much assumptions about their
+ structure. Still we gone the path of simplicity, so you can use
+ a global static for this struct too just like one can do for the
+ EXT-list. This again mimics the internals of zziplib. There is
+ even a helper function zzip_init_io that will copy the zziplib
+ internal handlers to your own handlers-set. Actually, this is
+ barely needed since the zziplib library will not check for nulls
+ in the plugin_io structure, all handlers must be filled, and the
+ zziplib routines call them unconditionally - that's simply
+ because a conditional-call will be ten times slower than an
+ unconditional call which adds mostly just one or two cpu cycles
+ in the place so you won't ever notice zziplib to be anywhat
+ slower than before adding IO-handlers.
+</P><P>
+ However, you better instantiate your handlers in your application
+ and call that zzip_init_io on that instance to have everything
+ filled, only then modify the entry you actually wish to have
+ modified. For <a href="zzip-xor.html">obfuscation</a> this
+ will mostly be just the <code>read()</code> routine. But one can
+ also use IO-handlers to wrap zip-files into another data part
+ for which one (also) wants to modify the open/close routines
+ as well.
+</P><P>
+ Therefore, you can modify your normal stdio code to start using
+ zipped files by exchaning the fopen/fread/fclose calls by their
+ magic counterparts, i.e. <pre>
+ // FILE* file = fopen ("test/README", "rb");
+ ZZIP_FILE* file = zzip_fopen ("test/README", "rb");
+ // while (0 < fread (buffer, 1, buflen, file)))
+ while (0 < zzip_fread (buffer, 1, buflen, file)))
+ { do something }
+ // fclose (file);
+ zzip_fclose (file);
+ </pre>
+ and you then need to prefix this code with some additional
+ code to support your own EXT/IO set, so the code will finally
+ look like <pre>
+ /* use .DAT extension to find some files */
+ static zzip_strings_t ext[] = { ".dat", ".DAT", "", 0 };
+ /* add obfuscation routine - see zzxorcat.c examples */
+ static zzip_plugin_io_t io;
+ zzip_init_io (& io, 0);
+ io.read = xor_read;
+ /* and the rest of the code, just as above, but with ext/io */
+ ZZIP_FILE* file = zzip_open_ext_io ("test/README", O_RDONLY|O_BINARY,
+ ZZIP_ONLYZIP|ZZIP_CASELESS, ext, io);
+ while (0 < zzip_fread (buffer, 1, buflen, file)))
+ { do something }
+ zzip_fclose (file);
+ </pre>
+</P>
+
+<h3> Finally </h3>
+
+<P>
+ What's more to it? Well, if you have some ideas then please mail me
+ about it - don't worry, I'll probably reject it to be part of the
+ standard zziplib dll, but perhaps it is worth to be added as a
+ configure option and can help others later, and even more perhaps
+ it can be somehow generalized just as the ext/io features have been
+ generalized now. In most respects, this ext/io did not add much
+ code to the <a href="zziplib.html">zziplib</a> - the posix-calls
+ in the implemenation, like <code>"read(file)"</code> were simply
+ exchanged with <code>"zip->io->read(file)"</code>, and the
+ old <code>"zzip_open(name,mode)"</code> call is split up - the old
+ entry still persists but directly calls
+ <code>"zzip_open_ext_io(name,mode,0,0,0)"</code> which has the
+ old implementation code with just one addition: when the ZIP_FILE
+ handle is created, it uses the transferred io-handlers (or the
+ default ones if io==0), and initialized the io-member of that
+ structure for usage within the <code>zzip_read</code> calls.
+</P><P>
+ This adds just a few bytes to the libs and just consumes additional
+ cpu cycles that can be rightfully called to be negligable (unlike
+ most commerical vendors will tell you when they indeed want to
+ tell you that for soooo many new features you have to pay a price).
+ It makes for greater variability without adding fatness to the
+ core in the default case, this is truly efficient I'd say. Well,
+ call this a German desease :-)=) ... and again, if you have another
+ idea, write today... or next week.
+</P>
+
+
+
+
+
--- /dev/null
+<h2> SDL rwops </h2> Example to make an SDL_rwops interface.
+
+<p><small> some <b>MSVC</b> help in
+ <a href="README.MSVC6">README.MSVC6</a> and
+ <a href="README.SDL">README.SDL</a>
+</small></p>
+
+<!--border--> <date> 19. Aug 2001 </date>
+
+<h3> Source </h3>
+
+<P>
+ The example sources of the <a href="zziplib.html">zziplib library</a>
+ are usually put under the <a href="COPYING.ZLIB">ZLIB license</a> so
+ that you can reuse the code freely in your own projects. Here we talk
+ about the example that might be most useful for
+ <a href="http://libsdl.org">SDL</a> based programs.
+ Just copy the two files
+ <a href="SDL_rwops_zzip.h">SDL_rwops_zzip.h</a>
+ and
+ <a href="SDL_rwops_zzip.c">SDL_rwops_zzip.c</a>
+ to the directory with your other project sources, and make sure
+ to link it somehow to your programs. I did not make the effort to
+ create a seperate library out of it - it would just export one
+ single function <tt>SDL_RWFromZZIP</tt> that has the same call-synopsis
+ like <tt>SDL_RWFromFile</tt> (but it can not (yet) write a zip-file).
+</P>
+
+<P>
+ The source file <a href="SDL_rwops_zzip.c">SDL_rwops_zzip.c</a> is
+ quite short - it just stores a ZZIP_FILE handle in the userdata
+ field of the <tt>SDL_rwops</tt> structure. The SDL'rwop calls will then
+ fetch that pointer and call the corresponding functions from the
+ <a href="zziplib.html">zziplib library</a>. Most of the glue code
+ is in the <tt>SDL_RWFromZZIP</tt> function that allocates an
+ <tt>SDL_rwops</tt> structure and fills the handler-functions
+ into the callback fields.
+</P>
+
+<h3> Usage </h3>
+
+<P>
+ If you link this file to your project, remember that your executables
+ do now have additional dependencies - not only -lzzip to link with
+ the <a href="zziplib.html">zziplib library</a> - do not forget to
+ link with zlib library via -lz. Of course, there is a lib-config
+ script that you can use: `zzip-config --libs` will return these
+ linker-infos (unless you have a native-windows system - it is
+ shell-script).
+</P>
+
+<P>
+ As an example, replace that <tt>SDL_RWFromFile</tt> that accesses your
+ game-graphic files - these files are stored in shared/myapp
+ of course where they belong. When you've done that
+ then go to X/share/myapp and
+ <pre>
+ `(cd graphics/ && zip -9r ../graphics.zip .)` </pre>
+ and rename the graphics/ subfolder - and still all your files
+ are found: a filepath like X/shared/graphics/game/greetings.bmp
+ will open X/shared/graphics.zip and return the zipped file
+ game/greetings.bmp in the zip-archive (for reading that is).
+</P>
+
+<h3> Test </h3>
+
+<P>
+ The <a href="zziplib.html">zziplib</a> configure script does not
+ look for <a href="http://libsdl.org">SDL</a>. If you know that
+ you have <a href="http://libsdl.org">SDL</a> installed
+ then you can check this <tt>SDL_rwops</tt> example by using
+ <code><nobr>`make testsdl`</nobr></code>. This will compile the
+ two source files <a href="SDL_rwops_zzip.c">SDL_rwops_zzip.c</a>
+ and <a href="SDL_rwops_zzcat.c">SDL_rwops_zzcat.c</a> to be linked
+ together into an executable called <code>zzcatsdl</code>. The test
+ will continue with a <code><nobr>`zzcatsdl test/README`</nobr></code>
+ - just like it is done for <code><nobr>`make test3`</nobr></code>.
+</P>
+<P>
+ The corresponding section in the <a href="Makefile.am">Makefile.am</a>
+ is also an example how to use lib-config scripts to build files. Here
+ there is no build-processing that had been tweaked much by automake/autoconf.
+ Just use sdl-config and zzip-config to add the needed flags.
+</P>
+