From da1cdfc3ada7109330a92955239bdc7981e95430 Mon Sep 17 00:00:00 2001 From: Tomas Bzatek Date: Tue, 28 Oct 2008 17:10:07 +0100 Subject: Password callback support from all VFS modules --- .gitignore | 12 +++ common/vfs_types.h | 12 ++- gvfs/gvfs.c | 80 ++++++---------- libarchive/libarchive.c | 54 ++++++----- unrar/unrar.c | 199 ++++++++++++++++++++++++++-------------- zip/zip.cpp | 238 ++++++++++++++++++++++++++++++------------------ 6 files changed, 360 insertions(+), 235 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d3dcca6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +*.o +*.lo +*.a +*.*~ +*.so +*.ppu +*.dcu +.project +.cproject + +UVFSCore.pas +uVFSprototypes.pas diff --git a/common/vfs_types.h b/common/vfs_types.h index 99334f9..aced4d3 100644 --- a/common/vfs_types.h +++ b/common/vfs_types.h @@ -37,7 +37,8 @@ typedef enum { VFS_ASK_PASSWORD_NEED_DOMAIN = 1<<2, VFS_ASK_PASSWORD_SAVING_SUPPORTED = 1<<3, VFS_ASK_PASSWORD_ANONYMOUS_SUPPORTED = 1<<4, - VFS_ASK_PASSWORD_SAVE_INTERNAL = 1<<15 + VFS_ASK_PASSWORD_SAVE_INTERNAL = 1<<14, + VFS_ASK_PASSWORD_ARCHIVE_MODE = 1<<15 } TVFSAskPasswordFlags; /* Compatible with gio/GPasswordSave */ @@ -49,9 +50,15 @@ typedef enum { typedef void (* TVFSLogFunc)(char *s); -typedef int (* TVFSCopyCallBackFunc)(u_int64_t iPos, u_int64_t iMax, void *data); typedef void *TVFSFileDes; + +/* Return FALSE to break the operation */ +typedef int (* TVFSProgressCallback) + (u_int64_t position, + u_int64_t max, + void *user_data); + /* Return index of the choice selected or negative number when dialog has been cancelled */ typedef void (* TVFSAskQuestionCallback) (const char *message, @@ -64,6 +71,7 @@ typedef int (* TVFSAskPasswordCallback) (const char *message, const char *default_user, const char *default_domain, + const char *default_password, TVFSAskPasswordFlags flags, char **username, char **password, diff --git a/gvfs/gvfs.c b/gvfs/gvfs.c index 557f08c..a5734cf 100644 --- a/gvfs/gvfs.c +++ b/gvfs/gvfs.c @@ -31,8 +31,8 @@ -#define VERSION "0.1.3" -#define BUILD_DATE "2008-10-12" +#define VERSION "0.1.4" +#define BUILD_DATE "2008-10-28" #define DEFAULT_BLOCK_SIZE 0x10000 /* 64kB */ #define CONST_DEFAULT_QUERY_INFO_ATTRIBUTES G_FILE_ATTRIBUTE_STANDARD_TYPE "," G_FILE_ATTRIBUTE_STANDARD_NAME "," \ @@ -46,6 +46,7 @@ struct TVFSGlobs { TVFSLogFunc log_func; GFile *file; GFileEnumerator *enumerator; + GCancellable *cancellable; GMainLoop *mount_main_loop; TVFSResult mount_result; @@ -57,7 +58,8 @@ struct TVFSGlobs { TVFSAskQuestionCallback callback_ask_question; TVFSAskPasswordCallback callback_ask_password; - void *callbacks_data; + TVFSProgressCallback callback_progress; + void *callback_data; }; @@ -167,9 +169,9 @@ ask_password_cb (GMountOperation *op, if (globs->callback_ask_password) { fprintf (stderr, " (II) Spawning callback_ask_password (0x%.16llX)...\n", (unsigned long long) globs->callback_ask_password); - result = globs->callback_ask_password (message, default_user, default_domain, flags, + result = globs->callback_ask_password (message, default_user, default_domain, NULL, flags, &username, &password, &anonymous, &domain, &password_save, - globs->callbacks_data); + globs->callback_data); fprintf (stderr, " (II) Received result = %d\n", result); if (result) { if (flags & G_ASK_PASSWORD_NEED_USERNAME) @@ -217,7 +219,7 @@ ask_question_cb (GMountOperation *op, if (globs->callback_ask_question) { fprintf (stderr, " (II) Spawning callback_ask_question (0x%.16llX)...\n", (unsigned long long) globs->callback_ask_question); /* At this moment, only SFTP uses ask_question and the second button is cancellation */ - globs->callback_ask_question (message, choices, &choice, 1, globs->callbacks_data); + globs->callback_ask_question (message, choices, &choice, 1, globs->callback_data); fprintf (stderr, " (II) Received choice = %d\n", choice); if (choice >= 0) { @@ -298,13 +300,15 @@ VFSNew (TVFSLogFunc log_func) globs->file = NULL; globs->enumerator = NULL; + globs->cancellable = NULL; globs->break_get_dir_size = FALSE; globs->block_size = DEFAULT_BLOCK_SIZE; - globs->callbacks_data = NULL; + globs->callback_data = NULL; globs->callback_ask_question = NULL; globs->callback_ask_password = NULL; + globs->callback_progress = NULL; return globs; } @@ -313,11 +317,13 @@ void VFSSetCallbacks (struct TVFSGlobs *globs, TVFSAskQuestionCallback ask_question_callback, TVFSAskPasswordCallback ask_password_callback, + TVFSProgressCallback progress_func, void *data) { globs->callback_ask_question = ask_question_callback; globs->callback_ask_password = ask_password_callback; - globs->callbacks_data = data; + globs->callback_progress = progress_func; + globs->callback_data = data; } void @@ -599,17 +605,6 @@ VFSChangeDir (struct TVFSGlobs *globs, char *NewPath) return res; } -int -VFSLogin (struct TVFSGlobs *globs, char *user, char *pass) -{ - g_print ("(II) VFSLogin: logging in with '%s'/'%s'\n", user, pass); - - /* FIXME: add auth code */ - - return cVFS_Not_Supported; -} - - /**************************************************************************************************************************************/ /**************************************************************************************************************************************/ @@ -1275,41 +1270,31 @@ VFSTwoSameFiles (struct TVFSGlobs *globs, const char *Path1, const char *Path2) /**************************************************************************************************************************************/ /**************************************************************************************************************************************/ - -struct CopyJobRef { - struct TVFSGlobs *globs; - TVFSCopyCallBackFunc callback_func; - void *callback_data; - - GCancellable *cancellable; -}; - static void vfs_copy_progress_callback (goffset current_num_bytes, goffset total_num_bytes, gpointer user_data) { - struct CopyJobRef *ref; + struct TVFSGlobs *globs; // g_print ("(II) vfs_copy_progress_callback spawned: current_num_bytes = %lu, total_num_bytes = %lu\n", current_num_bytes, total_num_bytes); if (! user_data) return; - ref = (struct CopyJobRef*) user_data; + globs = (struct TVFSGlobs *)user_data; - if (ref->callback_func) { - if (! ref->callback_func (current_num_bytes, total_num_bytes, ref->callback_data)) - g_cancellable_cancel (ref->cancellable); + if (globs->callback_progress) { + if (! globs->callback_progress (current_num_bytes, total_num_bytes, globs->callback_data)) + g_cancellable_cancel (globs->cancellable); } } TVFSResult -VFSCopyOut (struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, TVFSCopyCallBackFunc pCallBackProgress, void *data, gboolean Append) +VFSCopyOut (struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, gboolean Append) { GFile *src, *dst; GError *error; - struct CopyJobRef *ref; TVFSResult res; @@ -1331,15 +1316,11 @@ VFSCopyOut (struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, return cVFS_Failed; } - ref = g_slice_new0 (struct CopyJobRef); - ref->globs = globs; - ref->callback_func = pCallBackProgress; - ref->callback_data = data; - ref->cancellable = g_cancellable_new (); + globs->cancellable = g_cancellable_new (); res = cVFS_OK; error = NULL; - g_file_copy (src, dst, G_FILE_COPY_OVERWRITE | G_FILE_COPY_NOFOLLOW_SYMLINKS, ref->cancellable, vfs_copy_progress_callback, ref, &error); + g_file_copy (src, dst, G_FILE_COPY_OVERWRITE | G_FILE_COPY_NOFOLLOW_SYMLINKS, globs->cancellable, vfs_copy_progress_callback, globs, &error); if (error) { g_print ("(EE) VFSCopyOut: g_file_copy() error: %s\n", error->message); // res = g_error_to_TVFSResult (error); @@ -1349,19 +1330,17 @@ VFSCopyOut (struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, g_error_free (error); } - g_object_unref (ref->cancellable); - g_slice_free (struct CopyJobRef, ref); + g_object_unref (globs->cancellable); g_object_unref (src); g_object_unref (dst); return res; } TVFSResult -VFSCopyIn (struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, TVFSCopyCallBackFunc pCallBackProgress, void *data, gboolean Append) +VFSCopyIn (struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, gboolean Append) { GFile *src, *dst; GError *error; - struct CopyJobRef *ref; TVFSResult res; @@ -1383,16 +1362,12 @@ VFSCopyIn (struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, return cVFS_Failed; } - ref = g_slice_new0 (struct CopyJobRef); - ref->globs = globs; - ref->callback_func = pCallBackProgress; - ref->callback_data = data; - ref->cancellable = g_cancellable_new (); + globs->cancellable = g_cancellable_new (); res = cVFS_OK; error = NULL; /* FIXME: Appending not supported */ - g_file_copy (src, dst, G_FILE_COPY_NOFOLLOW_SYMLINKS, ref->cancellable, vfs_copy_progress_callback, ref, &error); + g_file_copy (src, dst, G_FILE_COPY_NOFOLLOW_SYMLINKS, globs->cancellable, vfs_copy_progress_callback, globs, &error); if (error) { g_print ("(EE) VFSCopyIn: g_file_copy() error: %s\n", error->message); // res = g_error_to_TVFSResult (error); @@ -1402,8 +1377,7 @@ VFSCopyIn (struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, g_error_free (error); } - g_object_unref (ref->cancellable); - g_slice_free (struct CopyJobRef, ref); + g_object_unref (globs->cancellable); g_object_unref (src); g_object_unref (dst); return res; diff --git a/libarchive/libarchive.c b/libarchive/libarchive.c index 4a360bd..be6326b 100644 --- a/libarchive/libarchive.c +++ b/libarchive/libarchive.c @@ -1,5 +1,5 @@ /* libarchive plugin for Tux Commander - * version 0.1.0, designed for libarchive 2.5.5 + * version 0.1.1, designed for libarchive 2.5.5 * Copyright (C) 2008 Tomas Bzatek * Check for updates on tuxcmd.sourceforge.net * @@ -47,8 +47,8 @@ -#define VERSION "0.1.0" -#define BUILD_DATE "2008-10-05" +#define VERSION "0.1.1" +#define BUILD_DATE "2008-10-28" #define DEFAULT_BLOCK_SIZE 65536 @@ -73,6 +73,11 @@ struct TVFSGlobs { struct VfsFilelistData *vfs_filelist; u_int64_t total_size; + + TVFSAskQuestionCallback callback_ask_question; + TVFSAskPasswordCallback callback_ask_password; + TVFSProgressCallback callback_progress; + void *callback_data; }; @@ -92,12 +97,31 @@ VFSNew (TVFSLogFunc log_func) memset (globs, 0, sizeof (struct TVFSGlobs)); globs->block_size = DEFAULT_BLOCK_SIZE; + + globs->callback_data = NULL; + globs->callback_ask_question = NULL; + globs->callback_ask_password = NULL; + globs->callback_progress = NULL; + globs->log_func = log_func; if (globs->log_func != NULL) globs->log_func((char*)"libarchive plugin: VFSInit"); return globs; } +void +VFSSetCallbacks (struct TVFSGlobs *globs, + TVFSAskQuestionCallback ask_question_callback, + TVFSAskPasswordCallback ask_password_callback, + TVFSProgressCallback progress_func, + void *data) +{ + globs->callback_ask_question = ask_question_callback; + globs->callback_ask_password = ask_password_callback; + globs->callback_progress = progress_func; + globs->callback_data = data; +} + void VFSFree (struct TVFSGlobs *globs) { @@ -297,18 +321,6 @@ TVFSResult VFSChangeDir(struct TVFSGlobs *globs, char *NewPath) else return cVFS_Failed; } - -int VFSLogin(struct TVFSGlobs *globs, char *user, char *pass) -{ - return cVFS_Not_Supported; -} - -int VFSSetPassword(struct TVFSGlobs *globs, char *pass) -{ - printf("(WW) VFSSetPassword: Not supported in libarchive plugin.\n"); - return cVFS_Not_Supported; -} - int VFSGetPasswordRequired(struct TVFSGlobs *globs) { return FALSE; @@ -480,7 +492,7 @@ int VFSTwoSameFiles(struct TVFSGlobs *globs, const char *Path1, const char *Path * Quote: "This implementation minimizes copying of data and is sparse-file aware." **/ static TVFSResult -my_archive_read_data_into_fd(struct archive *a, struct archive_entry *entry, const char *sDstName, size_t max_block, TVFSCopyCallBackFunc pCallBackProgress, void *data, int Append) +my_archive_read_data_into_fd(struct TVFSGlobs *globs, struct archive *a, struct archive_entry *entry, const char *sDstName, size_t max_block, int Append) { int r; int fd; @@ -529,8 +541,8 @@ my_archive_read_data_into_fd(struct archive *a, struct archive_entry *entry, con size -= bytes_written; log(" (II) my_archive_read_data_into_fd: bytes_written = %u, total_written = %u\n", bytes_written, total_written); - if (pCallBackProgress) { - if (! pCallBackProgress(total_written, file_size, data)) { + if (globs->callback_progress) { + if (! globs->callback_progress(total_written, file_size, globs->callback_data)) { cancel = TRUE; break; } @@ -553,7 +565,7 @@ my_archive_read_data_into_fd(struct archive *a, struct archive_entry *entry, con } -TVFSResult VFSCopyOut(struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, TVFSCopyCallBackFunc pCallBackProgress, void *data, int Append) +TVFSResult VFSCopyOut(struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, int Append) { if ((sSrcName == NULL) || (sDstName == NULL) || (strlen(sSrcName) < 1) || (strlen(sDstName) < 1)) { printf("(EE) VFSCopyOut: The value of 'sSrcName' or 'sDstName' is NULL or empty\n"); @@ -602,7 +614,7 @@ TVFSResult VFSCopyOut(struct TVFSGlobs *globs, const char *sSrcName, const char // printf("--> found file, extracting\n"); fprintf(stderr, "(II) VFSCopyOut: extract_file_path(sDstName) = '%s', extract_file_name(sDstName) = '%s' \n", extract_file_path(sDstName), extract_file_name(sDstName)); - Result = my_archive_read_data_into_fd(a, entry, sDstName, globs->block_size, pCallBackProgress, data, Append); + Result = my_archive_read_data_into_fd(globs, a, entry, sDstName, globs->block_size, Append); break; } } @@ -615,7 +627,7 @@ TVFSResult VFSCopyOut(struct TVFSGlobs *globs, const char *sSrcName, const char return Result; } -TVFSResult VFSCopyIn(struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, TVFSCopyCallBackFunc pCallBackProgress, void *data, int Append) +TVFSResult VFSCopyIn(struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, int Append) { printf("(WW) VFSCopyIn: Not supported in libarchive plugin.\n"); return cVFS_Not_Supported; diff --git a/unrar/unrar.c b/unrar/unrar.c index 8793dc4..22d5497 100644 --- a/unrar/unrar.c +++ b/unrar/unrar.c @@ -1,5 +1,5 @@ /* UNRAR plugin for Tux Commander - * version 0.3.0, designed for unrar v3.8.2 + * version 0.3.2, designed for unrar v3.8.2 * Copyright (C) 2008 Tomas Bzatek * Check for updates on tuxcmd.sourceforge.net * @@ -55,19 +55,14 @@ enum HOST_SYSTEM { }; -#define VERSION "0.3.0" -#define BUILD_DATE "2008-10-05" +#define VERSION "0.3.2" +#define BUILD_DATE "2008-10-28" #define DEFAULT_BLOCK_SIZE 65536 -/******************************************************************************************************/ -/** Auxiliary classes */ -/************** ****************/ - - // Declaration of the global plugin object struct TVFSGlobs { @@ -86,11 +81,14 @@ struct TVFSGlobs { u_int64_t total_size; - void *extract_callback_data; - TVFSCopyCallBackFunc extract_callback_func; u_int64_t extract_file_size; u_int64_t extract_done; gboolean extract_cancelled; + + TVFSAskQuestionCallback callback_ask_question; + TVFSAskPasswordCallback callback_ask_password; + TVFSProgressCallback callback_progress; + void *callback_data; }; @@ -110,10 +108,14 @@ VFSNew (TVFSLogFunc log_func) memset (globs, 0, sizeof (struct TVFSGlobs)); globs->block_size = DEFAULT_BLOCK_SIZE; - globs->extract_callback_data = NULL; - globs->extract_callback_func = NULL; globs->need_password = FALSE; globs->passwd_callback = FALSE; + globs->password = NULL; + + globs->callback_data = NULL; + globs->callback_ask_question = NULL; + globs->callback_ask_password = NULL; + globs->callback_progress = NULL; globs->log_func = log_func; if (globs->log_func != NULL) globs->log_func((char*)"unrar plugin: VFSInit"); @@ -121,6 +123,19 @@ VFSNew (TVFSLogFunc log_func) return globs; } +void +VFSSetCallbacks (struct TVFSGlobs *globs, + TVFSAskQuestionCallback ask_question_callback, + TVFSAskPasswordCallback ask_password_callback, + TVFSProgressCallback progress_func, + void *data) +{ + globs->callback_ask_question = ask_question_callback; + globs->callback_ask_password = ask_password_callback; + globs->callback_progress = progress_func; + globs->callback_data = data; +} + void VFSFree (struct TVFSGlobs *globs) { @@ -167,6 +182,11 @@ char *VFSGetExts() int unrar_callback(UINT msg, LONG UserData, LONG P1, LONG P2) { // fprintf(stderr, "(II) unrar_callback called: msg = %d, UserData = %lx, sizeof(UserData) = %ld, P1 = %ld, P2 = %ld\n", msg, UserData, sizeof(UserData), P1, P2); + if (! UserData) { + fprintf(stderr, "(WW) unrar_callback: UserData == NULL, exiting!\n"); + return 0; + } + struct TVFSGlobs *globs = (struct TVFSGlobs *)UserData; // >= 0 => Weiter, -1 => Stop switch(msg) @@ -174,11 +194,35 @@ int unrar_callback(UINT msg, LONG UserData, LONG P1, LONG P2) case UCM_CHANGEVOLUME: { if (P2 == RAR_VOL_ASK) { fprintf(stderr, " (II) unrar_callback: UCM_CHANGEVOLUME message, RAR_VOL_ASK, P1 = %ld, (char*)P1 = '%s' \n", P1, (char*)P1); - if (P1) + if (P1) { + if (globs->callback_ask_question) { + static const char *choices[] = { + "Cancel", + "Continue", + NULL + }; + char *message; + int choice = 2; + + message = g_strdup_printf ("volume missing: %s", (char *)P1); + globs->callback_ask_question (message, choices, &choice, 0, + globs->callback_data); + g_free (message); + switch (choice) { + case 0: /* Cancel */ + return -1; + case 1: /* Continue */ + return 0; + /* Any other options? */ + } + } +/* if (access((char*)P1, R_OK) != 0) { fprintf(stderr, "(EE) unrar_callback: UCM_CHANGEVOLUME message, RAR_VOL_ASK: access test failed - missing part? Error = %s \n", strerror(errno)); return -1; } +*/ + } } else if (P2 == RAR_VOL_NOTIFY) { fprintf(stderr, " (II) unrar_callback: UCM_CHANGEVOLUME message, RAR_VOL_NOTIFY, P1 = %ld, (char*)P1 = '%s' \n", P1, (char*)P1); @@ -188,20 +232,19 @@ int unrar_callback(UINT msg, LONG UserData, LONG P1, LONG P2) case UCM_PROCESSDATA: { fprintf(stderr, " (II) unrar_callback: UCM_PROCESSDATA message, P1 = %ld, P2 = %ld \n", P1, P2); - struct TVFSGlobs *globs = (struct TVFSGlobs *)UserData; // printf(" (II) unrar_callback: globs = 0x%lX, UserData = 0x%lX \n", (unsigned long int)globs, UserData); - if ((globs) && (globs->extract_callback_func != NULL)) { + if ((globs) && (globs->callback_progress)) { // printf(" (II) unrar_callback: globs->extract_callback_func = 0x%lX, globs->extract_callback_data = 0x%lX \n", (unsigned long int)globs->extract_callback_func, (unsigned long int)globs->extract_callback_data); // long int res = globs->extract_callback_func((u_int64_t)P1, (u_int64_t)((u_int64_t)P1 + (u_int64_t)P2), globs->extract_callback_data); globs->extract_done += P2; - int res = globs->extract_callback_func(globs->extract_done, globs->extract_file_size, globs->extract_callback_data); + int res = globs->callback_progress(globs->extract_done, globs->extract_file_size, globs->callback_data); // fprintf(stderr, " (II) unrar_callback: res = %d \n", res); if (! res ) { - globs->extract_cancelled = TRUE; - fprintf(stderr, "(WW) unrar_callback: received cancellation result\n"); - return -1; // Cancel operation + globs->extract_cancelled = TRUE; + fprintf(stderr, "(WW) unrar_callback: received cancellation result\n"); + return -1; // Cancel operation } } break; @@ -209,9 +252,32 @@ int unrar_callback(UINT msg, LONG UserData, LONG P1, LONG P2) case UCM_NEEDPASSWORD: { fprintf(stderr, " (II) unrar_callback: UCM_NEEDPASSWORD message, P1 = %ld, P2 = %ld, (char*)P1 = '%s', maxlen = %ld \n", P1, P2, (char*)P1, P2); - struct TVFSGlobs *globs = (struct TVFSGlobs *)UserData; - if (globs) globs->passwd_callback = TRUE; - break; + + char *passwd = NULL; + int res = FALSE; + + globs->passwd_callback = TRUE; + if (globs->callback_ask_password) { + res = globs->callback_ask_password ("The archive is encrypted and requires password", + NULL, NULL, NULL, VFS_ASK_PASSWORD_NEED_PASSWORD | VFS_ASK_PASSWORD_ARCHIVE_MODE, + NULL, &passwd, NULL, NULL, NULL, + globs->callback_data); + if (res && passwd) { + fprintf(stderr, " (II) unrar_callback: setting password to '%s'\n", passwd); + if (strlen (passwd) > 0) { + strncpy((char *)P1, passwd, P2); + if (globs->password) g_free (globs->password); + globs->password = g_strdup (passwd); + } + g_free (passwd); + } + } + if (res) + return 0; + else { + globs->extract_cancelled = TRUE; + return -1; + } } } @@ -407,20 +473,6 @@ TVFSResult VFSChangeDir(struct TVFSGlobs *globs, char *NewPath) else return cVFS_Failed; } - -int VFSLogin(struct TVFSGlobs *globs, char *user, char *pass) -{ - return cVFS_Not_Supported; -} - -int VFSSetPassword(struct TVFSGlobs *globs, char *pass) -{ - printf ("(II) VFSSetPassword: Going to set the password...\n"); - if (globs->password) free(globs->password); - globs->password = strdup(pass); - return cVFS_OK; -} - int VFSGetPasswordRequired(struct TVFSGlobs *globs) { if (globs) return globs->need_password; @@ -577,7 +629,7 @@ int VFSIsOnSameFS(struct TVFSGlobs *globs, const char *Path1, const char *Path2) int VFSTwoSameFiles(struct TVFSGlobs *globs, const char *Path1, const char *Path2) { - printf("(WW) VFSTwoSameFiles: Not supported in ZIP archives, comparing by paths.\n"); + printf("(WW) VFSTwoSameFiles: Not supported in RAR archives, comparing by paths.\n"); return compare_two_same_files(Path1, Path2); } @@ -586,7 +638,7 @@ int VFSTwoSameFiles(struct TVFSGlobs *globs, const char *Path1, const char *Path //////////////////////// -TVFSResult VFSCopyOut(struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, TVFSCopyCallBackFunc pCallBackProgress, void *data, int Append) +TVFSResult VFSCopyOut(struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, int Append) { if ((sSrcName == NULL) || (sDstName == NULL) || (strlen(sSrcName) < 1) || (strlen(sDstName) < 1)) { printf("(EE) VFSCopyOut: The value of 'sSrcName' or 'sDstName' is NULL or empty\n"); @@ -603,10 +655,6 @@ TVFSResult VFSCopyOut(struct TVFSGlobs *globs, const char *sSrcName, const char printf("(II) VFSCopyOut: new src path: '%s'\n", src); -// printf("(II) VFSCopyOut: pCallBackProgress = 0x%lX, data = 0x%lX\n", (unsigned long int)pCallBackProgress, (unsigned long int)data); - globs->extract_callback_data = data; - globs->extract_callback_func = pCallBackProgress; - HANDLE PASCAL handle; struct RAROpenArchiveDataEx *archive_data; @@ -658,7 +706,10 @@ TVFSResult VFSCopyOut(struct TVFSGlobs *globs, const char *sSrcName, const char int res2 = RARProcessFile(handle, RAR_EXTRACT, NULL, (char *)sDstName); - if (globs->extract_cancelled) Result = cVFS_Cancelled; + if (globs->extract_cancelled) { + fprintf(stderr, "(WW) VFSCopyOut: cancelled !\n"); + Result = cVFS_Cancelled; + } else if (res2) { fprintf(stderr, "(EE) VFSCopyOut: RARProcessFile result = %d\n", res2); @@ -675,32 +726,39 @@ TVFSResult VFSCopyOut(struct TVFSGlobs *globs, const char *sSrcName, const char } if ((res != ERAR_END_ARCHIVE) && (res)) { - fprintf(stderr, "(EE) VFSCopyOut: RARReadHeader result = %d\n", res); - switch (res) { - case ERAR_NO_MEMORY: - case ERAR_SMALL_BUF: - Result = cVFS_mallocFailed; - break; - case ERAR_BAD_DATA: - case ERAR_BAD_ARCHIVE: - case ERAR_UNKNOWN_FORMAT: - case ERAR_EOPEN: - case ERAR_ECLOSE: - case ERAR_EREAD: - Result = cVFS_ReadErr; - break; - case ERAR_ECREATE: - case ERAR_EWRITE: - Result = cVFS_WriteErr; - break; - case ERAR_MISSING_PASSWORD: - Result = cVFS_BadPassword; - break; - case ERAR_UNKNOWN: - default: - Result = cVFS_WriteErr; - break; - } + if (globs->extract_cancelled) { + fprintf(stderr, "(WW) VFSCopyOut: cancelled !\n"); + Result = cVFS_Cancelled; + } + else { + fprintf(stderr, "(EE) VFSCopyOut: RARReadHeader result = %d\n", res); + switch (res) { + case ERAR_NO_MEMORY: + case ERAR_SMALL_BUF: + Result = cVFS_mallocFailed; + break; + case ERAR_BAD_DATA: + case ERAR_BAD_ARCHIVE: + case ERAR_UNKNOWN_FORMAT: + case ERAR_EOPEN: + case ERAR_ECLOSE: + case ERAR_EREAD: + Result = cVFS_ReadErr; + break; + case ERAR_ECREATE: + case ERAR_EWRITE: + Result = cVFS_WriteErr; + break; + case ERAR_MISSING_PASSWORD: + Result = cVFS_BadPassword; + if (globs->password) g_free (globs->password); + break; + case ERAR_UNKNOWN: + default: + Result = cVFS_WriteErr; + break; + } + } } free(header); @@ -722,7 +780,7 @@ TVFSResult VFSCopyOut(struct TVFSGlobs *globs, const char *sSrcName, const char return Result; } -TVFSResult VFSCopyIn(struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, TVFSCopyCallBackFunc pCallBackProgress, void *data, int Append) +TVFSResult VFSCopyIn(struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, int Append) { printf("(WW) VFSCopyIn: Not supported in UNRAR plugin.\n"); return cVFS_Not_Supported; @@ -735,6 +793,7 @@ TVFSResult VFSCopyIn(struct TVFSGlobs *globs, const char *sSrcName, const char * * TODO: * * - UTF-8, FName/FDisplayName and absolute/relative paths revision needed! + * - find a reliable way to catch bad password errors and free the cached invalid password * - no error reporting when archive is corrupted * - archive testing (needs new VFS API) * diff --git a/zip/zip.cpp b/zip/zip.cpp index 8b61068..2f87778 100644 --- a/zip/zip.cpp +++ b/zip/zip.cpp @@ -1,5 +1,5 @@ /* ZIP plugin for Tux Commander - * version 0.5.0, designed for ZipArchive v3.2.0 + * version 0.5.1, designed for ZipArchive v3.2.0 * Copyright (C) 2008 Tomas Bzatek * Check for updates on tuxcmd.sourceforge.net * @@ -47,8 +47,8 @@ -#define VERSION "0.5.0" -#define BUILD_DATE "2008-10-05" +#define VERSION "0.5.1" +#define BUILD_DATE "2008-10-28" #define DEFAULT_BLOCK_SIZE 65536 @@ -120,6 +120,31 @@ TVFSResult get_vfs_errorcode(int m_iCause) /** Auxiliary classes */ /************** ****************/ +struct ZIP_API CVFSZipActionCallback; + +struct TVFSGlobs { + TVFSLogFunc log_func; + char *curr_dir; + char *archive_path; + + gboolean need_password; + + CZipArchive *zip; + CVFSZipActionCallback *extract_callback; + + bool archive_opened; + unsigned long block_size; + bool archive_modified; + + struct PathTree *files; + struct VfsFilelistData *vfs_filelist; + + TVFSAskQuestionCallback callback_ask_question; + TVFSAskPasswordCallback callback_ask_password; + TVFSProgressCallback callback_progress; + void *callback_data; +}; + // Define the progress class and the class methods struct ZIP_API CVFSZipActionCallback : public CZipActionCallback { @@ -127,12 +152,10 @@ struct ZIP_API CVFSZipActionCallback : public CZipActionCallback { m_uTotalToProcess = 0; m_uProcessed = 0; - pCallBackProgress = NULL; - data = NULL; + globs = NULL; } - TVFSCopyCallBackFunc pCallBackProgress; - void *data; + struct TVFSGlobs *globs; virtual bool Callback(ZIP_SIZE_TYPE uProgress) { @@ -140,7 +163,8 @@ struct ZIP_API CVFSZipActionCallback : public CZipActionCallback uProgress, m_uTotalToProcess, m_uProcessed); bool ret = true; try { - if (pCallBackProgress != NULL) ret = pCallBackProgress(m_uProcessed, m_uTotalToProcess, data); + if (globs && globs->callback_progress) + ret = globs->callback_progress (m_uProcessed, m_uTotalToProcess, globs->callback_data); } catch (...) { fprintf(stderr, "(EE) extract_callback: Fatal error occured when calling pCallBackProgress\n"); @@ -150,24 +174,6 @@ struct ZIP_API CVFSZipActionCallback : public CZipActionCallback }; -struct TVFSGlobs { - TVFSLogFunc log_func; - char *curr_dir; - char *archive_path; - - gboolean need_password; - - CZipArchive *zip; - CVFSZipActionCallback *extract_callback; - - bool archive_opened; - unsigned long block_size; - bool archive_modified; - - struct PathTree *files; - struct VfsFilelistData *vfs_filelist; -}; - /*********************************************************************************************************************** @@ -241,12 +247,30 @@ VFSNew (TVFSLogFunc log_func) globs->archive_modified = false; globs->need_password = FALSE; + globs->callback_data = NULL; + globs->callback_ask_question = NULL; + globs->callback_ask_password = NULL; + globs->callback_progress = NULL; + globs->log_func = log_func; if (globs->log_func != NULL) globs->log_func((char*)"zip plugin: VFSInit"); return globs; } +void +VFSSetCallbacks (struct TVFSGlobs *globs, + TVFSAskQuestionCallback ask_question_callback, + TVFSAskPasswordCallback ask_password_callback, + TVFSProgressCallback progress_func, + void *data) +{ + globs->callback_ask_question = ask_question_callback; + globs->callback_ask_password = ask_password_callback; + globs->callback_progress = progress_func; + globs->callback_data = data; +} + void VFSFree (struct TVFSGlobs *globs) { @@ -331,6 +355,7 @@ TVFSResult VFSOpen(struct TVFSGlobs *globs, char *sName) // Set the progress callback globs->extract_callback = new CVFSZipActionCallback; + globs->extract_callback->globs = globs; globs->zip->SetCallback(globs->extract_callback, CZipActionCallback::cbExtract); globs->zip->SetCallback(globs->extract_callback, CZipActionCallback::cbAdd); @@ -428,11 +453,7 @@ TVFSResult VFSChangeDir(struct TVFSGlobs *globs, char *NewPath) else return cVFS_Failed; } -int VFSLogin(struct TVFSGlobs *globs, char *user, char *pass) -{ - return cVFS_Not_Supported; -} - +/* int VFSSetPassword(struct TVFSGlobs *globs, char *pass) { printf ("(II) VFSSetPassword: Going to set the password...\n"); @@ -446,6 +467,7 @@ int VFSSetPassword(struct TVFSGlobs *globs, char *pass) } return cVFS_OK; } +*/ int VFSGetPasswordRequired(struct TVFSGlobs *globs) { @@ -846,8 +868,10 @@ int VFSTwoSameFiles(struct TVFSGlobs *globs, const char *Path1, const char *Path // Known issues: - crashes when no space left on NFS mounts, probably unhandled exception in further ZipArchive code (repro: Gentoo, Ubuntu) -TVFSResult VFSCopyOut(struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, TVFSCopyCallBackFunc pCallBackProgress, void *data, int Append) +TVFSResult VFSCopyOut(struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, int Append) { + gboolean try_again; + if ((sSrcName == NULL) || (sDstName == NULL) || (strlen(sSrcName) < 1) || (strlen(sDstName) < 1)) { printf("(EE) VFSCopyOut: The value of 'sSrcName' or 'sDstName' is NULL or empty\n"); return cVFS_Failed; @@ -866,26 +890,43 @@ TVFSResult VFSCopyOut(struct TVFSGlobs *globs, const char *sSrcName, const char char *dest_filename = extract_file_name(s); free(s); - // Set callback data - globs->extract_callback->data = data; - globs->extract_callback->pCallBackProgress = pCallBackProgress; - // Perform extract try { - try { - if (! globs->zip->ExtractFile(file_no, dest_path, false, dest_filename, globs->block_size)) { + do { + try { + try_again = FALSE; + if (! globs->zip->ExtractFile(file_no, dest_path, false, dest_filename, globs->block_size)) { + globs->zip->CloseFile(NULL, true); + fprintf(stderr, "(EE) VFSCopyOut: Error while copying out, archive closed = %d.\n", globs->zip->IsClosed()); + return cVFS_WriteErr; + } + fprintf(stderr, "(II) VFSCopyOut: copy OK, archive closed = %d.\n", globs->zip->IsClosed()); + } + catch (CZipException e) { globs->zip->CloseFile(NULL, true); - fprintf(stderr, "(EE) VFSCopyOut: Error while copying out, archive closed = %d.\n", globs->zip->IsClosed()); - return cVFS_WriteErr; - } - fprintf(stderr, "(II) VFSCopyOut: copy OK, archive closed = %d.\n", globs->zip->IsClosed()); - } - catch (CZipException e) { - globs->zip->CloseFile(NULL, true); - fprintf(stderr, "(EE) VFSCopyOut: Error while copying out: [%d] %s, archive closed = %d.\n", - e.m_iCause, (LPCTSTR)e.GetErrorDescription(), globs->zip->IsClosed()); - return get_vfs_errorcode(e.m_iCause); - } + fprintf(stderr, "(EE) VFSCopyOut: Error while copying out: [%d] %s, archive closed = %d.\n", + e.m_iCause, (LPCTSTR)e.GetErrorDescription(), globs->zip->IsClosed()); + switch (e.m_iCause) { + case CZipException::badPassword: + if (globs->callback_ask_password) { + char *passwd = NULL; + int res = globs->callback_ask_password ("The archive is encrypted and requires password", + NULL, NULL, NULL, (TVFSAskPasswordFlags)(VFS_ASK_PASSWORD_NEED_PASSWORD | VFS_ASK_PASSWORD_ARCHIVE_MODE), + NULL, &passwd, NULL, NULL, NULL, + globs->callback_data); + if (res && passwd) { + fprintf(stderr, " (II) VFSCopyOut: setting password to '%s'\n", passwd); + globs->zip->SetPassword(passwd); + try_again = TRUE; + break; + } else + return cVFS_Cancelled; + } + default: + return get_vfs_errorcode(e.m_iCause); + } + } + } while (try_again); } catch (...) { @@ -900,8 +941,10 @@ TVFSResult VFSCopyOut(struct TVFSGlobs *globs, const char *sSrcName, const char // Known issues: - archive corruption when no space left on device // - encrypted files are unreadable after copy in -TVFSResult VFSCopyIn(struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, TVFSCopyCallBackFunc pCallBackProgress, void *data, int Append) +TVFSResult VFSCopyIn(struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, int Append) { + gboolean try_again; + if ((sSrcName == NULL) || (sDstName == NULL) || (strlen(sSrcName) < 1) || (strlen(sDstName) < 1)) { printf("(EE) VFSCopyIn: The value of 'sSrcName' or 'sDstName' is NULL or empty\n"); return cVFS_Failed; @@ -909,50 +952,67 @@ TVFSResult VFSCopyIn(struct TVFSGlobs *globs, const char *sSrcName, const char * printf("(II) VFSCopyIn: copying file '%s' in to '%s'\n", sSrcName, sDstName); - // Set callback data - globs->extract_callback->data = data; - globs->extract_callback->pCallBackProgress = pCallBackProgress; - try { - try { - char *s = exclude_leading_path_sep(sDstName); - if (! globs->zip->AddNewFile(sSrcName, s, -1, CZipArchive::zipsmSafeSmart, globs->block_size)) { + do { + try { + try_again = FALSE; + char *s = exclude_leading_path_sep(sDstName); + if (! globs->zip->AddNewFile(sSrcName, s, -1, CZipArchive::zipsmSafeSmart, globs->block_size)) { + globs->zip->CloseNewFile(true); + globs->zip->CloseFile(NULL, true); + build_global_filelist(globs); + fprintf(stderr, "(EE) VFSCopyIn: Error while copying in, archive closed = %d.\n", globs->zip->IsClosed()); + return cVFS_WriteErr; + } + + globs->zip->Flush(); + printf("(II) VFSCopyIn: copy OK, archive closed = %d.\n", globs->zip->IsClosed()); + build_global_filelist(globs); + globs->archive_modified = true; + + /* + // Encrypt the file if archive contains any encrypted files + if (globs->need_password) { + unsigned long int file_no = filelist_find_index_by_path(globs->files, s) - 1; + if (file_no < 0) { + printf("(EE) VFSCopyIn: unable to find index for newly written file '%s'\n", sSrcName); + return cVFS_WriteErr; + } + printf("(II) VFSCopyIn: Encrypting the newly written file...\n"); + if (! globs->zip->EncryptFile(file_no)) + printf("(EE) VFSCopyIn: Unable to encrypt the newly written file\n"); + } + */ + + free(s); + } + catch (CZipException e) { globs->zip->CloseNewFile(true); globs->zip->CloseFile(NULL, true); build_global_filelist(globs); - fprintf(stderr, "(EE) VFSCopyIn: Error while copying in, archive closed = %d.\n", globs->zip->IsClosed()); - return cVFS_WriteErr; + fprintf(stderr, "(EE) VFSCopyIn: Error while copying in: [%d] %s, archive closed = %d.\n", + e.m_iCause, (LPCTSTR)e.GetErrorDescription(), globs->zip->IsClosed()); + switch (e.m_iCause) { + case CZipException::badPassword: + if (globs->callback_ask_password) { + char *passwd = NULL; + int res = globs->callback_ask_password ("The archive is encrypted and requires password", + NULL, NULL, NULL, (TVFSAskPasswordFlags)(VFS_ASK_PASSWORD_NEED_PASSWORD | VFS_ASK_PASSWORD_ARCHIVE_MODE), + NULL, &passwd, NULL, NULL, NULL, + globs->callback_data); + if (res && passwd) { + fprintf(stderr, " (II) VFSCopyIn: setting password to '%s'\n", passwd); + globs->zip->SetPassword(passwd); + try_again = TRUE; + break; + } else + return cVFS_Cancelled; + } + default: + return get_vfs_errorcode(e.m_iCause); + } } - - globs->zip->Flush(); - printf("(II) VFSCopyIn: copy OK, archive closed = %d.\n", globs->zip->IsClosed()); - build_global_filelist(globs); - globs->archive_modified = true; - -/* - // Encrypt the file if archive contains any encrypted files - if (globs->need_password) { - unsigned long int file_no = filelist_find_index_by_path(globs->files, s) - 1; - if (file_no < 0) { - printf("(EE) VFSCopyIn: unable to find index for newly written file '%s'\n", sSrcName); - return cVFS_WriteErr; - } - printf("(II) VFSCopyIn: Encrypting the newly written file...\n"); - if (! globs->zip->EncryptFile(file_no)) - printf("(EE) VFSCopyIn: Unable to encrypt the newly written file\n"); - } - */ - - free(s); - } - catch (CZipException e) { - globs->zip->CloseNewFile(true); - globs->zip->CloseFile(NULL, true); - build_global_filelist(globs); - fprintf(stderr, "(EE) VFSCopyIn: Error while copying in: [%d] %s, archive closed = %d.\n", - e.m_iCause, (LPCTSTR)e.GetErrorDescription(), globs->zip->IsClosed()); - return get_vfs_errorcode(e.m_iCause); - } + } while (try_again); } catch (...) { -- cgit v1.2.3