diff options
Diffstat (limited to 'zip')
| -rw-r--r-- | zip/README | 4 | ||||
| l--------- | zip/tuxcmd-error.h | 1 | ||||
| -rw-r--r-- | zip/zip.cpp | 329 |
3 files changed, 257 insertions, 77 deletions
@@ -1,8 +1,6 @@ ZIP plugin for Tux Commander - Version: 0.7 - Release date: 2023-Dec-17 -Copyright (C) 2004-2023 Tomas Bzatek <tbzatek@users.sourceforge.net> +Copyright (C) 2004-2024 Tomas Bzatek <tbzatek@users.sourceforge.net> http://tuxcmd.sourceforge.net This plugin uses ZipArchive library v4.6.9 diff --git a/zip/tuxcmd-error.h b/zip/tuxcmd-error.h new file mode 120000 index 0000000..5025579 --- /dev/null +++ b/zip/tuxcmd-error.h @@ -0,0 +1 @@ +../common/tuxcmd-error.h
\ No newline at end of file diff --git a/zip/zip.cpp b/zip/zip.cpp index b33cf2d..c6db221 100644 --- a/zip/zip.cpp +++ b/zip/zip.cpp @@ -1,5 +1,5 @@ /* ZIP plugin for Tux Commander - * version 0.7.1, designed for ZipArchive v4.6.9 + * version 0.8, designed for ZipArchive v4.6.9 * Copyright (C) 2004-2024 Tomas Bzatek <tbzatek@users.sourceforge.net> * Check for updates on tuxcmd.sourceforge.net * @@ -42,6 +42,7 @@ #include "logutils.h" #include "filelist.h" #include "filelist-vfs-intf.h" +#include "tuxcmd-error.h" #include "ZipArchive.h" #include "ZipPlatform.h" @@ -49,8 +50,8 @@ -#define VERSION "0.7.1" -#define BUILD_DATE "2024-01-19" +#define VERSION "0.8" +#define BUILD_DATE "2024-10-25" #define DEFAULT_BLOCK_SIZE 65536 @@ -929,38 +930,7 @@ VFSChangeTimes (struct TVFSGlobs *globs, const char *APath, guint32 mtime, guint //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////// -#if 0 -TVFSFileDes VFSOpenFile(struct TVFSGlobs *globs, const char *APath, int Mode, int *Error) -{ - *Error = cVFS_Not_Supported; - return (TVFSFileDes)0; -} - -TVFSResult VFSCloseFile(struct TVFSGlobs *globs, TVFSFileDes FileDescriptor) -{ - return cVFS_Not_Supported; -} - -u_int64_t VFSFileSeek(struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, u_int64_t AbsoluteOffset, int *Error) -{ - *Error = cVFS_Not_Supported; - return 0; -} - -int VFSReadFile(struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, void *Buffer, int ABlockSize, int *Error) -{ - *Error = cVFS_Not_Supported; - return 0; -} - -int VFSWriteFile(struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, void *Buffer, int BytesCount, int *Error) -{ - *Error = cVFS_Not_Supported; - return 0; -} -#endif - -void +void VFSSetBlockSize (struct TVFSGlobs *globs, guint32 Value) { if (globs) @@ -1013,6 +983,33 @@ VFSStopCopyOperation (struct TVFSGlobs *globs, GError **error) return TRUE; } +/* returns TRUE if password has been set and to try again */ +static gboolean +handle_password_prompt (struct TVFSGlobs *globs, const gchar *log_prefix, GError **error) +{ + gchar *passwd = NULL; + gboolean res; + + if (globs->callback_ask_password) { + res = globs->callback_ask_password ("The archive is encrypted and requires a 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) { + log_debug ("%s: setting password to '%s'", log_prefix, passwd); + globs->zip->SetPassword (passwd); + g_free (passwd); + return TRUE; + } else { + g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_CANCELLED, "Operation has been cancelled."); + return FALSE; + } + } + + g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_SOURCE_READ, "An incorrect password set for the file being decrypted."); + return FALSE; +} + /* Known issues: * - crashes when no space left on NFS mounts, probably unhandled exception in further ZipArchive code (repro: Gentoo, Ubuntu) @@ -1026,8 +1023,6 @@ VFSCopyToLocal (struct TVFSGlobs *globs, const char *sSrcName, const char *sDstN char *s; char *dest_path; char *dest_filename; - char *passwd; - gboolean res; if (sSrcName == NULL || sDstName == NULL || strlen (sSrcName) < 1 || strlen (sDstName) < 1) { log_error ("VFSCopyToLocal: The value of 'sSrcName' or 'sDstName' is NULL or empty"); @@ -1063,27 +1058,15 @@ VFSCopyToLocal (struct TVFSGlobs *globs, const char *sSrcName, const char *sDstN log_debug ("VFSCopyToLocal: copy OK, archive closed = %d.", globs->zip->IsClosed ()); } catch (CZipException& e) { - globs->zip->CloseFile (NULL, true); log_error ("VFSCopyToLocal: Error while copying out: [%d] %s, archive closed = %d.", e.m_iCause, (LPCTSTR)e.GetErrorDescription(), globs->zip->IsClosed()); + globs->zip->CloseFile (NULL, true); switch (e.m_iCause) { case CZipException::badPassword: - if (globs->callback_ask_password) { - passwd = NULL; - res = globs->callback_ask_password ("The archive is encrypted and requires a 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) { - log_debug ("VFSCopyToLocal: setting password to '%s'", passwd); - globs->zip->SetPassword (passwd); - try_again = TRUE; - break; - } else { - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CANCELLED, "Operation has been cancelled."); - return FALSE; - } - } + if (! handle_password_prompt (globs, "VFSCopyToLocal", error)) + return FALSE; + try_again = TRUE; + break; default: zip_error_to_gerror (e, error); return FALSE; @@ -1095,6 +1078,7 @@ VFSCopyToLocal (struct TVFSGlobs *globs, const char *sSrcName, const char *sDstN { log_error ("VFSCopyToLocal: Fatal error while copying out..., archive closed = %d.", globs->zip->IsClosed()); g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Fatal error while copying out."); + globs->zip->CloseFile (NULL, true); return FALSE; } g_free (dest_path); @@ -1113,8 +1097,6 @@ VFSCopyFromLocal (struct TVFSGlobs *globs, const char *sSrcName, const char *sDs { gboolean try_again; char *s; - char *passwd; - gboolean res; if (sSrcName == NULL || sDstName == NULL || strlen (sSrcName) < 1 || strlen (sDstName) < 1) { log_error ("VFSCopyFromLocal: The value of 'sSrcName' or 'sDstName' is NULL or empty"); @@ -1137,6 +1119,7 @@ VFSCopyFromLocal (struct TVFSGlobs *globs, const char *sSrcName, const char *sDs return FALSE; } + globs->zip->CloseNewFile (); log_debug ("VFSCopyFromLocal: copy OK, archive closed = %d.", globs->zip->IsClosed ()); globs->archive_modified = TRUE; @@ -1157,28 +1140,16 @@ VFSCopyFromLocal (struct TVFSGlobs *globs, const char *sSrcName, const char *sDs g_free (s); } catch (CZipException& e) { - globs->zip->CloseNewFile (true); - globs->zip->CloseFile (NULL, true); log_error ("VFSCopyFromLocal: Error while copying in: [%d] %s, archive closed = %d.", e.m_iCause, (LPCTSTR)e.GetErrorDescription(), globs->zip->IsClosed()); + globs->zip->CloseNewFile (true); + globs->zip->CloseFile (NULL, true); switch (e.m_iCause) { case CZipException::badPassword: - if (globs->callback_ask_password) { - passwd = NULL; - res = globs->callback_ask_password ("The archive is encrypted and requires a 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) { - log_debug ("VFSCopyFromLocal: setting password to '%s'", passwd); - globs->zip->SetPassword (passwd); - try_again = TRUE; - break; - } else { - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CANCELLED, "Operation has been cancelled."); - return FALSE; - } - } + if (! handle_password_prompt (globs, "VFSCopyFromLocal", error)) + return FALSE; + try_again = TRUE; + break; default: zip_error_to_gerror (e, error); return FALSE; @@ -1189,12 +1160,222 @@ VFSCopyFromLocal (struct TVFSGlobs *globs, const char *sSrcName, const char *sDs catch (...) { log_error ("VFSCopyFromLocal: Fatal error while copying in..., archive closed = %d.", globs->zip->IsClosed()); g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Fatal error while copying in."); + globs->zip->CloseNewFile (true); + globs->zip->CloseFile (NULL, true); + return FALSE; + } + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////// + +TVFSFileDes +VFSOpenFile (struct TVFSGlobs *globs, const char *APath, int Mode, GError **error) +{ + gboolean try_again; + long int file_no; + GError *local_error = NULL; + + switch (Mode) { + case cVFS_OpenRead: + /* OK, break */ + break; + case cVFS_OpenWrite: + case cVFS_OpenAppend: + g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_OPEN_FILE, "Writing files in the archive is not supported"); + return NULL; + default: + g_set_error (error, TUXCMD_ERROR, TUXCMD_ERROR_OPEN_FILE, "Invalid file open mode %d", Mode); + return NULL; + } + + log_notice ("VFSOpenFile: Opening file '%s'", APath); + + file_no = filelist_find_original_index_by_path (globs->files, APath) - 1; + if (file_no < 0) { + log_error ("VFSOpenFile: can't find file '%s'", APath); + g_set_error (error, TUXCMD_ERROR, TUXCMD_ERROR_OPEN_FILE, "Cannot find file '%s'", APath); + return NULL; + } + + try { + do { + try { + try_again = FALSE; + if (! globs->zip->OpenFile (file_no)) { + log_error ("VFSOpenFile: Error opening file, archive closed = %d.", globs->zip->IsClosed ()); + g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_OPEN_FILE, "Error opening file."); + return NULL; + } + } + catch (CZipException& e) { + log_error ("VFSOpenFile: Error opening file: [%d] %s, archive closed = %d.", + e.m_iCause, (LPCTSTR)e.GetErrorDescription(), globs->zip->IsClosed()); + globs->zip->CloseFile (NULL, true); + switch (e.m_iCause) { + case CZipException::badPassword: + if (! handle_password_prompt (globs, "VFSOpenFile", &local_error)) { + if (g_error_matches (local_error, TUXCMD_ERROR, TUXCMD_ERROR_CANCELLED)) + g_propagate_error (error, local_error); + else { + g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_OPEN_FILE, local_error->message); + g_error_free (local_error); + } + return NULL; + } + try_again = TRUE; + break; + default: + zip_error_to_gerror (e, &local_error); + g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_OPEN_FILE, local_error->message); + g_error_free (local_error); + return NULL; + } + } + } while (try_again); + } + catch (...) + { + log_error ("VFSCopyToLocal: Fatal error while opening file..., archive closed = %d.", globs->zip->IsClosed()); + g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_OPEN_FILE, "Fatal error while opening file."); + globs->zip->CloseFile (NULL, true); + return NULL; + } + + return (TVFSFileDes)(file_no + 1); /* FIXME: what to use as a filedescriptor? */ +} + +gboolean +VFSCloseFile (struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, GError **error) +{ + GError *local_error = NULL; + int r; + + try { + try { + /* FIXME: cannot distinguish between clean close and close after exception */ + r = globs->zip->CloseFile (); + if (r != 1) { + /* Returns one of the following values: + * 1 : The operation was successful. + * 0 : There is no file opened. + * -1 : Some bytes were left to uncompress - probably due to a bad password or a corrupted archive. + * -2 : Setting extracted file date and attributes was not successful. + */ + log_error ("VFSCloseFile: Error closing file, archive closed = %d.", globs->zip->IsClosed ()); + switch (r) { + case 0: g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_CLOSE_FILE, + "There is no file opened."); + break; + case -1: g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_CLOSE_FILE, + "Some bytes were left to uncompress - probably due to a bad password or a corrupted archive."); + break; + case -2: g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_CLOSE_FILE, + "Setting extracted file date and attributes was not successful."); + break; + default: + g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_CLOSE_FILE, "Error closing file."); + } + globs->zip->CloseFile (NULL, true); + return FALSE; + } + } + catch (CZipException& e) { + log_error ("VFSCloseFile: Error closing file: [%d] %s, archive closed = %d.", + e.m_iCause, (LPCTSTR)e.GetErrorDescription(), globs->zip->IsClosed()); + zip_error_to_gerror (e, &local_error); + g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_CLOSE_FILE, local_error->message); + g_error_free (local_error); + globs->zip->CloseFile (NULL, true); + return FALSE; + } + } + catch (...) + { + log_error ("VFSCloseFile: Fatal error while closing file..., archive closed = %d.", globs->zip->IsClosed()); + g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_CLOSE_FILE, "Fatal error while closing file."); + globs->zip->CloseFile (NULL, true); return FALSE; } return TRUE; } +gint64 +VFSReadFile (struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, gpointer Buffer, guint64 ABlockSize, GError **error) +{ + gboolean try_again; + GError *local_error = NULL; + + try { + do { + try { + DWORD r; + + try_again = FALSE; + + /* no file handle, only a global archive state (no multithreading) */ + r = globs->zip->ReadFile (Buffer, ABlockSize); + /* returns 0 on EOF */ + /* no error state available */ + return r; + } + catch (CZipException& e) { + log_error ("VFSReadFile: Error reading file: [%d] %s, archive closed = %d.", + e.m_iCause, (LPCTSTR)e.GetErrorDescription(), globs->zip->IsClosed()); + globs->zip->CloseFile (NULL, true); + switch (e.m_iCause) { + case CZipException::badPassword: + if (! handle_password_prompt (globs, "VFSReadFile", &local_error)) { + if (g_error_matches (local_error, TUXCMD_ERROR, TUXCMD_ERROR_CANCELLED)) + g_propagate_error (error, local_error); + else { + g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_OPEN_FILE, local_error->message); + g_error_free (local_error); + } + globs->zip->CloseFile (NULL, true); + return -1; + } + try_again = TRUE; + break; + default: + zip_error_to_gerror (e, &local_error); + g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_OPEN_FILE, local_error->message); + g_error_free (local_error); + globs->zip->CloseFile (NULL, true); + return -1; + } + } + } while (try_again); + } + catch (...) + { + log_error ("VFSCopyToLocal: Fatal error while opening file..., archive closed = %d.", globs->zip->IsClosed()); + g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_OPEN_FILE, "Fatal error while opening file."); + globs->zip->CloseFile (NULL, true); + return -1; + } + + g_warn_if_reached (); + return -1; +} + +gint64 +VFSWriteFile (struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, gpointer Buffer, guint64 BytesCount, GError **error) +{ + g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_WRITE_FILE, "Writing files in the archive is not supported"); + return -1; +} + +guint64 +VFSFileSeek (struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, guint64 AbsoluteOffset, GError **error) +{ + g_set_error_literal (error, TUXCMD_ERROR, TUXCMD_ERROR_SEEK, "Seeking in compressed data is not supported"); + return 0; +} + /////////////////////////////// // end of extern "C" |
