| API Plans |
| ========= |
| |
| Encryption |
| ---------- |
| * struct zip *zip_open_encrypted(const char *path, int flags, const char *password, int *errorp); |
| * int zip_set_encryption(struct zip *archive, zip_uint64_t idx, zip_uint16_t method, const char *password); |
| * void zip_set_archive_encryption(struct zip *archive, zip_uint16_t method, const char *password); |
| |
| Prefixes |
| -------- |
| For example for adding extractors for self-extracting zip archives. |
| * zip_set_archive_prefix(struct zip *za, const zip_uint8_t *data, zip_uint64_t length); |
| * const zip_uint8_t *zip_get_archive_prefix(struct zip *za, zip_uint64_t *lengthp); |
| |
| Progress Callback |
| ----------------- |
| Register callback; will be called from zip_close() after each file has been processed. |
| typedef void (*zip_progress_callback_t)(double); |
| void zip_register_progress_callback(zip_t *, zip_progress_callback_t); |
| |
| API Issues |
| ========== |
| ! D zip_get_archive_comment has int *lenp argument. Cleaner would be zip_uint32_t *. |
| rename and fix. which other functions for naming consistency? |
| ! D rename remaining zip_XXX_{file,archive}_* to zip_{file,archive}_XXX_*? |
| * compression/crypt implementations: how to set error code on failure |
| * compression/crypt error messages a la ZIP_ER_ZLIB (no detailed info passing) |
| * check arguments for every entry point into libzip |
| |
| |
| Features |
| ======== |
| * function to copy file from one archive to another |
| * set O_CLOEXEC flag after fopen and mkstemp |
| * Windows specific I/O source (to be written by a Windows expert) |
| |
| * I/O methods |
| * support streaming output (creating new archive to e.g. stdout) |
| * add functions to: |
| . read/set ASCII file flag? (wiz: more general options?) |
| * zip_commit (to finish changes without closing archive) |
| * add custom compression function support |
| * zip_fseek |
| * zip_source_zip: allow rewinding |
| * zipcmp: add option for file content comparison |
| * zipcmp: compare bit flags if paranoid |
| * zipcmp: compare external attributes/opsys if paranoid |
| * zipcmp: compare last_mod if paranoid (or with separate flag?) |
| * consistency |
| . for stored files, test compressed = uncompressed |
| . data descriptor |
| . local headers come before central dir |
| |
| - support for old compression methods????? |
| |
| |
| Bugs |
| ==== |
| * support InfoZIP encryption header extension |
| * embed stripped down old zlib for torrentzip |
| ! ensure that nentries is small enough not to cause overflow (size_t for entry, uint64 for CD on disk) |
| * Xcode 32bit build uses 64bit config.h |
| * fix OpenSUSE i686 regression failures |
| * fix open_filename_duplicate_consistency.test to fail |
| * split zip archive torrentzip state from user requested torrentzip state |
| * check for limits imposed by format (central dir size, file size, extra fields, ...) |
| * _zip_u2d_time: handle localtime(3) failure |
| * POSIX: zip_open: check whether file can be created and fail if not |
| * fix inconsistent usage of valid flags (not checked in many places) |
| * cdr == NULL -> ER_NOENT vs. idx > cdir->nentry -> ER_INVAL inconsistent (still there?) |
| * torrentzip broken on NetBSD/amd64 6.99 |
| * torrentzip: check behaviour of files with empty name (size 0; file size > 0) |
| |
| |
| Cleanup |
| ======= |
| * move compat refs from zipint.h to own file, and include that in zipint.h and src |
| * get rid of zip_get_{compression,encryption}_implementation |
| * use zip_*int*_t internally |
| * clean up lint(1) warnings? |
| |
| |
| Test Case Issues |
| ================ |
| * add test case for ZIP_CM_DEFAULT -> stored (edge cases) |
| * add test case to change values for newly added files (name, compression method, comment, mtime, . . .) |
| * replace Text::Diff with own implementation |
| * use zipcmp -p? |
| * zip_open file less than EOCDLEN bytes long |
| * test calls against old API |
| * run regression tests also from CMake framework |
| * rename file to dir/ and vice versa (fails) |
| * fix comment test to be newline insensitive |
| * check if http://bugs.python.org/issue20078 provides ideas for new tests |
| |
| * (add, replace) |
| add to empty zip |
| add to existing zip |
| add w/ existing file name [E] |
| replace ok |
| replace w/ illegal index [E] |
| replace w/ deleted name [E] |
| unchange added/replaced file |
| * (close) |
| copy zip file |
| open copy |
| rename, delete, replace, add w/ new name, add w/ deleted name |
| close |
| zipcmp copy expected |
| remove copy |
| * (error_get) |
| * (error_get_sys_type) |
| * (error_to_str) |
| * (extra_fields) |
| * (file_error_get) |
| * (file_strerror) |
| * (replace) |
| * (source_buffer) |
| * (source_file) |
| * (source_filep) |
| * (source_free) |
| * (source_function) |
| * (source_zip) |
| * (strerror) |
| * (unchange) |
| * (unchange_all) |
| * open(ZIP_RDONLY) |
| * I/O abstraction layer |
| zip_open_from_source |
| * read two zip entries interleaved |
| |
| |
| I/O Methods |
| =========== |
| One major headache for libzip portability (especially to Windows) is |
| I/O, i.e. reading and writing from the file system. Also, there |
| have been requests to open zip archives from a memory buffer. To |
| address these issues, we'll introduce an I/O abstraction layer. |
| |
| We'll reuse zip_source, since it already provides support for |
| the reading part, adding high level abstraction of the additional |
| operations needed. This way, newly written zip_sources can be used |
| both for adding files into an archive as well as for accessing archives |
| themselves. |
| |
| Specifically, we'll add these commands: |
| |
| ZIP_SOURCE_BEGIN_WRITE |
| Prepare for writing. The written data will replace all |
| original data. The file position is reset to 0. (On POSIX |
| systems, this will create a temporary file and open it for |
| writing.) |
| |
| ZIP_SOURCE_WRITE |
| Write bytes of data, a la fwrite(3) (does not need to know |
| anything about the zip archive structure). |
| |
| ZIP_SOURCE_COMMIT_WRITE |
| Used after all data has been written successfully. (On |
| POSIX systems, this will replace the original file with |
| the temporary file, adapting permissions etc.) |
| |
| ZIP_SOURCE_REMOVE |
| Zip archive is empty. Is responsible for removing file, if |
| appropriate. |
| |
| ZIP_SOURCE_ROLLBACK_WRITE |
| Used to reset the zip archive to the previous state (e.g. |
| because writing failed) to restore original data if possible; |
| return an error otherwise. (On POSIX systems, this will |
| delete the temporary file.) |
| |
| ZIP_SOURCE_SEEK |
| Set position for next read or write, a la fseek(3). |
| |
| ZIP_SOURCE_TELL |
| Report current position, a la ftell(3). |
| |
| ZIP_SOURCE_SUPPORTS |
| Query which commands are supported for this stream. If a |
| file cannot be written to, this will report ZIP_SOURCE_BEGIN_WRITE |
| as not supported, even if the source type would support |
| write. (This is used in zip_open to set global flags like |
| ZIP_AFL_RDONLY.) |
| |
| We'll provide a zip_open variant that takes a zip_source argument |
| used for reading/writing archives. Using an enhanced version of |
| zip_source_buffer, this can be used to read zip archives from memory. |
| |
| zip_open itself will create a source from the file using a |
| port-specific default implementation (POSIX vs. Windows vs. ...). |
| |
| Once the details are finalized, we'll ask for volunteers for writing |
| a Windows specific implementation. |
| |
| zip_source_XXX -> [I] |
| [I] -> OPEN -> [R] |
| [R] -> (SEEK|TELL|READ|STAT)* -> [R] |
| [R] -> CLOSE -> [I] |
| [I] -> BEGIN_WRITE -> [W] |
| [W] -> (SEEK|TELL|WRITE)* -> [W] |
| [W] -> (COMMIT_WRITE|ROLLBACK_WRITE) -> [I] |
| [IR] -> REMOVE -> [X] |
| [I] -> STAT -> [I] |
| |
| (no state change in case of error) |
| |
| always: |
| * -> ERROR -> \1 |
| * -> SUPPORTS -> \1 |
| * -> FREE |
| |
| |
| [-,-] |
| [R,-] |
| [-,W] |
| [R,W] |
| |
| zip_source_XXX -> [-,-] |
| [-,y] -> OPEN -> [R,y] |
| [R,y] -> (SEEK|TELL|READ|STAT)* -> [R,y] |
| [R,y] -> CLOSE -> [-,y] |
| [x,-] -> BEGIN_WRITE -> [x,W] |
| [x,W] -> (SEEK_WRITE|TELL_WRITE|WRITE)* -> [x,W] |
| [x,W] -> (COMMIT_WRITE|ROLLBACK_WRITE) -> [x,-] |
| [x,y] -> REMOVE -> [-,-] |
| [x,y] -> STAT -> [x,y] |
| [x,y] -> ERROR -> [x,y] |
| [x,y] -> SUPPORTS -> [x,y] |
| [x,y] -> FREE |
| |
| - document: zip_source_write: length can't be > ZIP_INT64_MAX |
| - document: ZIP_SOURCE_CLOSE implementation can't return error |
| |
| |
| - check for INT_MAX, UINT_MAX |
| |
| plan for merge: |
| |
| after merge: |
| - direct reference to source and from upper layer are equivalent: only close/free if all are gone. |
| - only allow multiple upper layers for sources that support seek |
| - cache supported state in struct zip_source and check in _zip_source_call before calling |
| D re-implement fix for OS X sandboxing (zip_archive_set_tempdir). |
| - find out FSEEK_MAX/FTELL_MAX and use it |
| - adapt man pages |
| - document ZIP_RDONLY |
| - keep error codes in man pages in sync |
| - document ZIP_SOURCE_GET_ARGS(type, data, len, error) ((len) < sizeof(type) ? zip_error_set((error), ZIP_ER_INVAL, 0), NULL : (type *)(data)) |
| - document new functions |
| ** zip_error_t *zip_get_error(zip_t *); |
| ** int zip_error_code_zip(const zip_error_t *); |
| ** int zip_error_code_system(const zip_error_t *); |
| ** void zip_error_fini(zip_error_t *); |
| ** void zip_error_init(zip_error_t *); |
| ** void zip_error_set(zip_error_t *, int, int); |
| ** const char *zip_error_strerror(zip_error_t *); |
| ** int zip_error_system_type(const zip_error_t *); |
| ** zip_int64_t zip_error_to_data(const zip_error_t *, void *, zip_uint64_t); |
| ** zip_error_t *zip_file_get_error(zip_file_t *); |
| ** zip_t *zip_open_from_source(zip_source_t *, int, zip_error_t *); |
| ** zip_source_t *zip_source_buffer_create(const void *, zip_uint64_t, int, zip_error_t *); |
| ** int zip_source_close(zip_source_t *); |
| ** zip_error_t *zip_source_error(zip_source_t *src); |
| ** zip_source_t *zip_source_file_create(const char *, zip_uint64_t, zip_int64_t, zip_error_t *); |
| ** zip_source_t *zip_source_filep_create(FILE *, zip_uint64_t, zip_int64_t, zip_error_t *); |
| ** zip_source_t *zip_source_function_create(zip_source_callback, void *, zip_error_t *); |
| ** int zip_source_is_deleted(zip_source_t *); |
| ** void zip_source_keep(zip_source_t *); |
| ** zip_int64_t zip_source_make_command_bitmap(zip_source_cmd_t, ...); |
| ** int zip_source_open(zip_source_t *); |
| ** zip_int64_t zip_source_read(zip_source_t *, void *, zip_uint64_t); |
| ** int zip_source_stat(zip_source_t *, zip_stat_t *); |
| - document deprecations |
| ** int zip_error_get_sys_type(int); /* use zip_error_system_type */ |
| ** void zip_error_get(zip_t *, int *, int *); /* use zip_get_error, zip_error_code_zip / zip_error_code_system */ |
| ** void zip_file_error_get(zip_file_t *, int *, int *); /* use zip_file_get_error, zip_error_code_zip / zip_error_code_system */ |