intrface.cpp
资源名称:unzip540.zip [点击查看]
上传用户:andy_li
上传日期:2007-01-06
资源大小:1019k
文件大小:54k
源码类别:
压缩解压
开发平台:
MultiPlatform
- //******************************************************************************
- //
- // File: INTRFACE.CPP
- //
- // Description: This module acts as the interface between the Info-ZIP code and
- // our Windows code in WINMAIN.CPP. We expose the needed
- // functions to query a file list, test file(s), extract file(s),
- // and display a zip file comment. The windows code is never
- // bothered with understanding the Globals structure "Uz_Globs".
- //
- // This module also catches all the callbacks from the Info-ZIP
- // code, cleans up the data provided in the callback, and then
- // forwards the information to the appropriate function in the
- // windows code. These callbacks include status messages, file
- // lists, comments, password prompt, and file overwrite prompts.
- //
- // Finally, this module implements the few functions that the
- // Info-ZIP code expects the port to implement. These functions are
- // OS dependent and are mostly related to validating file names and
- // directoies, and setting file attributes and dates of saved files.
- //
- // Copyright: All the source files for Pocket UnZip, except for components
- // written by the Info-ZIP group, are copyrighted 1997 by Steve P.
- // Miller. The product "Pocket UnZip" itself is property of the
- // author and cannot be altered in any way without written consent
- // from Steve P. Miller.
- //
- // Disclaimer: All project files are provided "as is" with no guarantee of
- // their correctness. The authors are not liable for any outcome
- // that is the result of using this source. The source for Pocket
- // UnZip has been placed in the public domain to help provide an
- // understanding of its implementation. You are hereby granted
- // full permission to use this source in any way you wish, except
- // to alter Pocket UnZip itself. For comments, suggestions, and
- // bug reports, please write to stevemil@pobox.com.
- //
- // Functions: DoListFiles
- // DoExtractOrTestFiles
- // DoGetComment
- // SetExtractToDirectory
- // InitGlobals
- // FreeGlobals
- // IsFileOrDirectory
- // SmartCreateDirectory
- // ExtractOrTestFilesThread
- // CheckForAbort
- // SetCurrentFile
- // UzpMessagePrnt2
- // UzpInput2
- // UzpMorePause
- // UzpPassword
- // UzpReplace
- // UzpSound
- // SendAppMsg
- // win_fprintf
- // mapattr
- // utimeToFileTime
- // GetFileTimes
- // close_outfile
- // do_wild
- // mapname
- // test_NT
- // checkdir
- // match
- // iswild
- // IsOldFileSystem
- //
- //
- // Date Name History
- // -------- ------------ -----------------------------------------------------
- // 02/01/97 Steve Miller Created (Version 1.0 using Info-ZIP UnZip 5.30)
- //
- //******************************************************************************
- //******************************************************************************
- #if 0 // The following information and structure are here just for reference
- //******************************************************************************
- //
- // The Windows CE version of Unzip builds with the following defines set:
- //
- //
- // WIN32
- // _WINDOWS
- // UNICODE
- // _UNICODE
- // WIN32_LEAN_AND_MEAN
- // STRICT
- //
- // POCKET_UNZIP (Main define - Always set)
- //
- // UNZIP_INTERNAL
- // WINDLL
- // DLL
- // REENTRANT
- // USE_EF_UT_TIME
- // NO_ZIPINFO
- // NO_STDDEF_H
- // NO_NTSD_EAS
- //
- // USE_SMITH_CODE (optional - See COPYING document)
- // USE_UNSHRINK (optional - See COPYING document)
- //
- // DEBUG (When building for Debug)
- // _DEBUG (When building for Debug)
- // NDEBUG (When building for Retail)
- // _NDEBUG (When building for Retail)
- //
- // _WIN32_WCE=100 (When building for Windows CE native)
- //
- // This causes our Globals structure to look like the following. The only
- // things we care about is this Globals structure, the process_zipfiles()
- // function, and a few callback functions. The Info-ZIP code has not been
- // been modified in any way.
- //
- typedef struct Globals {
- zvoid *callerglobs; // points to pass-through global vars
- UzpOpts UzO; // command options structure
- int prompt_always; // prompt to overwrite if TRUE
- int noargs; // did true command line have *any* arguments?
- unsigned filespecs; // number of real file specifications to be matched
- unsigned xfilespecs; // number of excluded filespecs to be matched
- int process_all_files;
- int create_dirs; // used by main(), mapname(), checkdir()
- int extract_flag;
- int newzip; // reset in extract.c; used in crypt.c
- LONGINT real_ecrec_offset;
- LONGINT expect_ecrec_offset;
- long csize; // used by decompr. (NEXTBYTE): must be signed
- long ucsize; // used by unReduce(), explode()
- long used_csize; // used by extract_or_test_member(), explode()
- int fValidate; // true if only validating an archive
- int filenotfound;
- int redirect_data; // redirect data to memory buffer
- int redirect_text; // redirect text output to buffer
- int redirect_slide; // redirect decompression area to mem buffer
- unsigned _wsize;
- unsigned redirect_size;
- uch *redirect_buffer;
- uch *redirect_pointer;
- uch *redirect_sldptr; // head of decompression slide buffer
- char **pfnames;
- char **pxnames;
- char sig[4];
- char answerbuf[10];
- min_info info[DIR_BLKSIZ];
- min_info *pInfo;
- union work area; // see unzpriv.h for definition of work
- ZCONST ulg near *crc_32_tab;
- ulg crc32val; // CRC shift reg. (was static in funzip)
- uch *inbuf; // input buffer (any size is OK)
- uch *inptr; // pointer into input buffer
- int incnt;
- ulg bitbuf;
- int bits_left; // unreduce and unshrink only
- int zipeof;
- char *argv0; // used for NT and EXE_EXTENSION
- char *wildzipfn;
- char *zipfn; // GRR: MSWIN: must nuke any malloc'd zipfn...
- int zipfd; // zipfile file handle
- LONGINT ziplen;
- LONGINT cur_zipfile_bufstart; // extract_or_test, readbuf, ReadByte
- LONGINT extra_bytes; // used in unzip.c, misc.c
- uch *extra_field; // Unix, VMS, Mac, OS/2, Acorn, ...
- uch *hold;
- local_file_hdr lrec; // used in unzip.c, extract.c
- cdir_file_hdr crec; // used in unzip.c, extract.c, misc.c
- ecdir_rec ecrec; // used in unzip.c, extract.c
- struct stat statbuf; // used by main, mapname, check_for_newer
- int mem_mode;
- uch *outbufptr; // extract.c static
- ulg outsize; // extract.c static
- int reported_backslash; // extract.c static
- int disk_full;
- int newfile;
- int didCRlast; // fileio static
- ulg numlines; // fileio static: number of lines printed
- int sol; // fileio static: at start of line
- int no_ecrec; // process static
- FILE *outfile;
- uch *outbuf;
- uch *realbuf;
- uch *outbuf2; // main() (never changes); else malloc'd
- uch *outptr;
- ulg outcnt; // number of chars stored in outbuf
- char filename[FILNAMSIZ];
- char *key; // crypt static: decryption password or NULL
- int nopwd; // crypt static
- ulg keys[3]; // crypt static: keys defining pseudo-random sequence
- unsigned hufts; // track memory usage
- struct huft *fixed_tl; // inflate static
- struct huft *fixed_td; // inflate static
- int fixed_bl
- int fixed_bd; // inflate static
- unsigned wp; // inflate static: current position in slide
- ulg bb; // inflate static: bit buffer
- unsigned bk; // inflate static: bits in bit buffer
- MsgFn *message;
- InputFn *input;
- PauseFn *mpause;
- PasswdFn *decr_passwd;
- StatCBFn *statreportcb;
- LPUSERFUNCTIONS lpUserFunctions;
- int incnt_leftover; // so improved NEXTBYTE does not waste input
- uch *inptr_leftover;
- // These are defined in PUNZIP.H.
- char matchname[FILNAMSIZ]; // used by do_wild()
- int notfirstcall; // used by do_wild()
- char *zipfnPtr;
- char *wildzipfnPtr;
- } Uz_Globs;
- #endif // #if 0 - This struct is here just for reference
- //******************************************************************************
- extern "C" {
- #define __INTRFACE_CPP__
- #define UNZIP_INTERNAL
- #include "unzip.h"
- #include "crypt.h" // Needed to pick up CRYPT define
- #include <commctrl.h>
- #include "intrface.h"
- #include "winmain.h"
- #ifndef _WIN32_WCE
- #include <process.h> // _beginthreadex() and _endthreadex()
- #endif
- }
- #include <tchar.h> // Must be outside of extern "C" block
- //******************************************************************************
- //***** "Local" Global Variables
- //******************************************************************************
- static USERFUNCTIONS g_uf;
- static EXTRACT_INFO *g_pExtractInfo = NULL;
- static FILE_NODE *g_pFileLast = NULL;
- static CHAR g_szExtractToDirectory[_MAX_PATH];
- static BOOL g_fOutOfMemory;
- //******************************************************************************
- //***** Local Function Prototypes
- //******************************************************************************
- extern "C" {
- // Our exposed interface functions to the Info-ZIP core.
- BOOL DoListFiles(LPCSTR szZipFile);
- BOOL DoExtractOrTestFiles(LPCSTR szZipFile, EXTRACT_INFO *pei);
- BOOL DoGetComment(LPCSTR szFile);
- BOOL SetExtractToDirectory(LPTSTR szDirectory);
- // Internal functions.
- Uz_Globs* InitGlobals(LPCSTR szZipFile);
- void FreeGlobals(Uz_Globs *pG);
- int IsFileOrDirectory(LPCTSTR szPath);
- BOOL SmartCreateDirectory(Uz_Globs *pG, LPCSTR szDirectory);
- #ifdef _WIN32_WCE
- DWORD WINAPI ExtractOrTestFilesThread(LPVOID lpv);
- #else
- unsigned __stdcall ExtractOrTestFilesThread(void *lpv);
- #endif
- void CheckForAbort(Uz_Globs *pG);
- void SetCurrentFile(Uz_Globs *pG);
- // Callbacks from Info-ZIP code.
- int UzpMessagePrnt2(zvoid *pG, uch *buffer, ulg size, int flag);
- int UzpInput2(zvoid *pG, uch *buffer, int *size, int flag);
- void UzpMorePause(zvoid *pG, const char *szPrompt, int flag);
- int UzpPassword(zvoid *pG, int *pcRetry, char *szPassword, int nSize,
- const char *szZipFile, const char *szFile);
- int WINAPI UzpReplace(char *szFile);
- void WINAPI UzpSound(void);
- void WINAPI SendAppMsg(ulg dwSize, ulg dwCompressedSize, int ratio, int month,
- int day, int year, int hour, int minute, int uppercase,
- char *szPath, char *szMethod, ulg dwCRC);
- int win_fprintf(FILE *file, unsigned int dwCount, char far *buffer);
- // Functions that Info-ZIP expects the port to write and export.
- void utimeToFileTime(time_t ut, FILETIME *pft, BOOL fOldFileSystem);
- int GetFileTimes(Uz_Globs *pG, FILETIME *pftCreated, FILETIME *pftAccessed,
- FILETIME *pftModified);
- int mapattr(Uz_Globs *pG);
- void close_outfile(Uz_Globs *pG);
- char* do_wild(Uz_Globs *pG, char *wildspec);
- int mapname(Uz_Globs *pG, int renamed);
- int test_NT(Uz_Globs *pG, uch *eb, unsigned eb_size);
- int checkdir(Uz_Globs *pG, char *pathcomp, int flag);
- // Check for FAT, VFAT, HPFS, etc.
- BOOL IsOldFileSystem(char *szPath);
- } // extern "C"
- //******************************************************************************
- //***** Our exposed interface functions to the Info-ZIP core
- //******************************************************************************
- int DoListFiles(LPCSTR szZipFile) {
- int result;
- // Create our Globals struct and fill it in whith some default values.
- Uz_Globs *pG = InitGlobals(szZipFile);
- if (!pG) {
- return PK_MEM;
- }
- pG->UzO.vflag = 1; // verbosely: list directory (for WIN32 it is 0 or 1)
- pG->process_all_files = TRUE; // improves speed
- g_pFileLast = NULL;
- g_fOutOfMemory = FALSE;
- // We wrap some exception handling around the entire Info-ZIP engine to be
- // safe. Since we are running on a device with tight memory configurations,
- // all sorts of problems can arise when we run out of memory.
- __try {
- // Call the unzip routine. We will catch the file information in a
- // callback to SendAppMsg().
- result = process_zipfiles(pG);
- // Make sure we didn't run out of memory in the process.
- if (g_fOutOfMemory) {
- result = PK_MEM;
- }
- } __except(EXCEPTION_EXECUTE_HANDLER) {
- // Catch any exception here.
- DebugOut(TEXT("Exception 0x%08X occurred in DoListFiles()"),
- GetExceptionCode());
- result = PK_EXCEPTION;
- }
- g_pFileLast = NULL;
- // It is possible that the ZIP engine change the file name a bit (like adding
- // a ".zip" if needed). If so, we will pick up the new name.
- if ((result != PK_EXCEPTION) && pG->zipfn && *pG->zipfn) {
- strcpy(g_szZipFile, pG->zipfn);
- }
- // Free our globals.
- FreeGlobals(pG);
- return result;
- }
- //******************************************************************************
- BOOL DoExtractOrTestFiles(LPCSTR szZipFile, EXTRACT_INFO *pei) {
- // WARNING!!! This functions hands the EXTRACT_INFO structure of to a thread
- // to perform the actual extraction/test. When the thread is done, it will
- // send a message to the progress dialog. The calling function must not
- // delete the EXTRAT_INFO structure until it receives the message. Currently,
- // this is not a problem for us since the structure lives on the stack of the
- // calling thread. The calling thread then displays a dialog that blocks the
- // calling thread from clearing the stack until the dialog is dismissed, which
- // occurs when the dialog receives the message.
- // Create our globals so we can store the file name.
- Uz_Globs *pG = InitGlobals(szZipFile);
- if (!pG) {
- pei->result = PK_MEM;
- SendMessage(g_hDlgProgress, WM_PRIVATE, MSG_OPERATION_COMPLETE, (LPARAM)pei);
- return FALSE;
- }
- // Store a global pointer to the Extract structure so it can be reached from
- // our thread and callback functions.
- g_pExtractInfo = pei;
- // Spawn our thread
- DWORD dwThreadId;
- HANDLE hThread;
- #ifdef _WIN32_WCE
- // On CE, we use good old CreateThread() since the WinCE CRT does not
- // allocate per-thread storage.
- hThread = CreateThread(NULL, 0, ExtractOrTestFilesThread, pG, 0, &dwThreadId);
- #else
- // On NT, we need use the CRT's thread function so that we don't leak any
- // CRT allocated memory when the thread exits.
- hThread = (HANDLE)_beginthreadex(NULL, 0, ExtractOrTestFilesThread, pG, 0,
- (unsigned*)&dwThreadId);
- #endif
- // Bail out if our thread failed to create.
- if (!hThread) {
- DebugOut(TEXT("CreateThread() failed [%u]"), GetLastError());
- // Set our error as a memory error.
- g_pExtractInfo->result = PK_MEM;
- // Free our globals.
- FreeGlobals(pG);
- // Tell the progress dialog that we are done.
- SendMessage(g_hDlgProgress, WM_PRIVATE, MSG_OPERATION_COMPLETE, (LPARAM)pei);
- g_pExtractInfo = NULL;
- return FALSE;
- }
- // Close our thread handle since we have no use for it.
- CloseHandle(hThread);
- return TRUE;
- }
- //******************************************************************************
- int DoGetComment(LPCSTR szFile) {
- int result;
- // Create our Globals struct and fill it in whith some default values.
- Uz_Globs *pG = InitGlobals(szFile);
- if (!pG) {
- return PK_MEM;
- }
- pG->UzO.zflag = TRUE; // display the zipfile comment
- // We wrap some exception handling around the entire Info-ZIP engine to be
- // safe. Since we are running on a device with tight memory configurations,
- // all sorts of problems can arise when we run out of memory.
- __try {
- // Call the unzip routine. We will catch the comment string in a callback
- // to win_fprintf().
- result = process_zipfiles(pG);
- } __except(EXCEPTION_EXECUTE_HANDLER) {
- // Catch any exception here.
- DebugOut(TEXT("Exception 0x%08X occurred in DoGetComment()"),
- GetExceptionCode());
- result = PK_EXCEPTION;
- }
- // Free our globals.
- FreeGlobals(pG);
- return result;
- }
- //******************************************************************************
- BOOL SetExtractToDirectory(LPTSTR szDirectory) {
- BOOL fNeedToAddWack = FALSE;
- // Remove any trailing wack from the path.
- int length = _tcslen(szDirectory);
- if ((length > 0) && (szDirectory[length - 1] == TEXT('\'))) {
- szDirectory[--length] = TEXT(' ');
- fNeedToAddWack = TRUE;
- }
- #ifndef _WIN32_WCE
- // Check to see if a root directory was specified.
- if ((length == 2) && isalpha(szDirectory[0]) && (szDirectory[1] == ':')) {
- // If just a root is specified, we need to only verify the drive letter.
- if (!(GetLogicalDrives() & (1 << (tolower(szDirectory[0]) - (int)'a')))) {
- // This drive does not exist. Bail out with a failure.
- return FALSE;
- }
- } else
- #endif
- // We only verify path if length is >0 since we know "" is valid.
- if (length > 0) {
- // Verify the the path exists and that it is a directory.
- if (IsFileOrDirectory(szDirectory) != 2) {
- return FALSE;
- }
- }
- // Store the directory for when we do an extract.
- wcstombs(g_szExtractToDirectory, szDirectory, countof(g_szExtractToDirectory));
- // We always want a wack at the end of our path.
- strcat(g_szExtractToDirectory, "\");
- // Add the wack back to the end of the path.
- if (fNeedToAddWack) {
- _tcscat(szDirectory, TEXT("\"));
- }
- return TRUE;
- }
- //******************************************************************************
- //***** Internal functions
- //******************************************************************************
- Uz_Globs* InitGlobals(LPCSTR szZipFile) {
- // Create our global structure - pG
- CONSTRUCTGLOBALS();
- // Bail out if we failed to allocate our Globals structure.
- if (!pG) {
- return NULL;
- }
- // Store a global pointer to our USERFUNCTIONS structure so that LIST.C,
- // PROCESS.C, and WINMAIN can access it.
- pG->lpUserFunctions = &g_uf;
- // Clear our USERFUNCTIONS structure and assign our SendAppMsg() function.
- ZeroMemory(&g_uf, sizeof(g_uf));
- g_uf.SendApplicationMessage = SendAppMsg;
- // Fill in all our callback functions.
- pG->message = UzpMessagePrnt2;
- pG->input = UzpInput2;
- pG->mpause = UzpMorePause;
- pG->lpUserFunctions->replace = UzpReplace;
- pG->lpUserFunctions->sound = UzpSound;
- #if CRYPT
- pG->decr_passwd = UzpPassword;
- #endif
- // Match filenames case-sensitively. We can do this since we can guarentee
- // exact case because the user can only select files via our UI.
- pG->UzO.C_flag = FALSE;
- // Allocate and store the ZIP file name in pG->zipfn
- if (!(pG->zipfnPtr = new char[FILNAMSIZ])) {
- FreeGlobals(pG);
- return NULL;
- }
- pG->zipfn = pG->zipfnPtr;
- strcpy(pG->zipfn, szZipFile);
- // Allocate and store the ZIP file name in pG->zipfn. This needs to done
- // so that do_wild() does not wind up clearing out the zip file name when
- // it returns in process.c
- if (!(pG->wildzipfnPtr = new char[FILNAMSIZ])) {
- FreeGlobals(pG);
- return NULL;
- }
- pG->wildzipfn = pG->wildzipfnPtr;
- strcpy(pG->wildzipfn, szZipFile);
- return pG;
- }
- //******************************************************************************
- void FreeGlobals(Uz_Globs *pG) {
- // Free our ZIP file name
- if (pG->zipfnPtr) {
- delete[] pG->zipfnPtr;
- pG->zipfnPtr = pG->zipfn = NULL;
- }
- // Free our wild name buffer
- if (pG->wildzipfnPtr) {
- delete[] pG->wildzipfnPtr;
- pG->wildzipfnPtr = pG->wildzipfn = NULL;
- }
- // Free everything else.
- DESTROYGLOBALS()
- }
- //******************************************************************************
- int IsFileOrDirectory(LPCTSTR szPath) {
- // Geth the attributes of the item.
- DWORD dwAttribs = GetFileAttributes(szPath);
- // Bail out now if we could not find the path at all.
- if (dwAttribs == 0xFFFFFFFF) {
- return 0;
- }
- // Return 1 for file and 2 for directory.
- return ((dwAttribs & FILE_ATTRIBUTE_DIRECTORY) ? 2 : 1);
- }
- //******************************************************************************
- BOOL SmartCreateDirectory(Uz_Globs *pG, LPCSTR szDirectory) {
- // Copy path to a UNICODE buffer.
- TCHAR szBuffer[_MAX_PATH];
- mbstowcs(szBuffer, szDirectory, countof(szBuffer));
- int x = IsFileOrDirectory(szBuffer);
- // Create the directory if it does not exist.
- if (x == 0) {
- if (!CreateDirectory(szBuffer, NULL)) {
- Info(slide, 1, ((char *)slide, "error creating directory: %sn", szDirectory));
- return FALSE;
- }
- // If there is a file with the same name, then display an error.
- } else if (x == 1) {
- Info(slide, 1, ((char *)slide,
- "cannot create %s as a file with same name already exists.n",
- szDirectory));
- return FALSE;
- }
- // If the directory already exists or was created, then return success.
- return TRUE;
- }
- //******************************************************************************
- #ifdef _WIN32_WCE
- // On WinCE, we declare our thread function the way CreateThread() likes it.
- DWORD WINAPI ExtractOrTestFilesThread(LPVOID lpv) {
- #else
- // On WinNT, we declare our thread function the way _beginthreadex likes it.
- unsigned __stdcall ExtractOrTestFilesThread(void *lpv) {
- #endif
- Uz_Globs *pG = (Uz_Globs*)lpv;
- if (g_pExtractInfo->fExtract) {
- pG->extract_flag = TRUE;
- switch (g_pExtractInfo->overwriteMode) {
- case OM_NEWER: // Update (extract only newer/brand-new files)
- pG->UzO.uflag = TRUE;
- break;
- case OM_ALWAYS: // OK to overwrite files without prompting
- pG->UzO.overwrite_all = TRUE;
- break;
- case OM_NEVER: // Never overwrite files (no prompting)
- pG->UzO.overwrite_none = TRUE;
- break;
- default: // Force a prompt
- pG->prompt_always = TRUE;
- break;
- }
- // Throw away paths if requested.
- pG->UzO.jflag = !g_pExtractInfo->fRestorePaths;
- } else {
- pG->UzO.tflag = TRUE;
- }
- if (g_pExtractInfo->szFileList) {
- pG->filespecs = g_pExtractInfo->dwFileCount;
- pG->pfnames = g_pExtractInfo->szFileList;
- } else {
- // Improves performance if all files are being extracted.
- pG->process_all_files = TRUE;
- }
- // Invalidate our file offset to show that we are starting a new operation.
- g_pExtractInfo->dwFileOffset = 0xFFFFFFFF;
- // We wrap some exception handling around the entire Info-ZIP engine to be
- // safe. Since we are running on a device with tight memory configurations,
- // all sorts of problems can arise when we run out of memory.
- __try {
- // Put a jump marker on our stack so the user can abort.
- int error = setjmp(dll_error_return);
- // If setjmp() returns 0, then we just set our jump marker and we can
- // continue with the operation. If setjmp() returned something else,
- // then we reached this point because the operation was aborted and
- // set our instruction pointer back here.
- if (error > 0) {
- // We already called process_zipfiles() and were thrown back here.
- g_pExtractInfo->result = (error == 1) ? PK_BADERR : error;
- } else {
- // Entering Info-ZIP... close your eyes.
- g_pExtractInfo->result = process_zipfiles(pG);
- }
- } __except(EXCEPTION_EXECUTE_HANDLER) {
- // Catch any exception here.
- DebugOut(TEXT("Exception 0x%08X occurred in ExtractOrTestFilesThread()"),
- GetExceptionCode());
- g_pExtractInfo->result = PK_EXCEPTION;
- }
- // Free our globals.
- FreeGlobals(pG);
- // Tell the progress dialog that we are done.
- SendMessage(g_hDlgProgress, WM_PRIVATE, MSG_OPERATION_COMPLETE,
- (LPARAM)g_pExtractInfo);
- // Clear our global pointer as we are done with it.
- g_pExtractInfo = NULL;
- #ifndef _WIN32_WCE
- // On NT, we need to free any CRT allocated memory.
- _endthreadex(0);
- #endif
- return 0;
- }
- //******************************************************************************
- void CheckForAbort(Uz_Globs *pG) {
- if (g_pExtractInfo->fAbort) {
- // Add a newline to our log if we are in the middle of a line of text.
- if (!g_pExtractInfo->fNewLineOfText) {
- SendMessage(g_hWndMain, WM_PRIVATE, MSG_ADD_TEXT_TO_EDIT, (LPARAM)"n");
- }
- // Make sure whatever file we are currently processing gets closed.
- if (((int)pG->outfile != 0) && ((int)pG->outfile != -1)) {
- if (g_pExtractInfo->fExtract && *pG->filename) {
- // Make sure the user is aware that this file is screwed.
- SendMessage(g_hWndMain, WM_PRIVATE, MSG_ADD_TEXT_TO_EDIT,
- (LPARAM)"warning: ");
- SendMessage(g_hWndMain, WM_PRIVATE, MSG_ADD_TEXT_TO_EDIT,
- (LPARAM)pG->filename);
- SendMessage(g_hWndMain, WM_PRIVATE, MSG_ADD_TEXT_TO_EDIT,
- (LPARAM)" is probably truncated.n");
- }
- // Close the file.
- close_outfile(pG);
- }
- // Display an aborted message in the log
- SendMessage(g_hWndMain, WM_PRIVATE, MSG_ADD_TEXT_TO_EDIT,
- (LPARAM)"Operation aborted by user.n");
- // I hate to do this... Take a giant step out of here.
- longjmp(dll_error_return, PK_ABORTED);
- }
- }
- //******************************************************************************
- void SetCurrentFile(Uz_Globs *pG) {
- // Reset all our counters as we about to process a new file.
- g_pExtractInfo->dwFileOffset = (DWORD)pG->pInfo->offset;
- g_pExtractInfo->dwFile++;
- g_pExtractInfo->dwBytesWrittenThisFile = 0;
- g_pExtractInfo->dwBytesWrittenPreviousFiles += g_pExtractInfo->dwBytesTotalThisFile;
- g_pExtractInfo->dwBytesTotalThisFile = pG->ucsize;
- g_pExtractInfo->szFile = pG->filename;
- g_pExtractInfo->fNewLineOfText = TRUE;
- // Pass control to our GUI thread to do a full update our progress dialog.
- SendMessage(g_hWndMain, WM_PRIVATE, MSG_UPDATE_PROGRESS_COMPLETE,
- (LPARAM)g_pExtractInfo);
- // Check our abort flag.
- CheckForAbort(pG);
- }
- //******************************************************************************
- //***** Callbacks from Info-ZIP code.
- //******************************************************************************
- int UzpMessagePrnt2(zvoid *pG, uch *buffer, ulg size, int flag) {
- // Some ZIP files cause us to get called during DoListFiles(). We only handle
- // messages while processing DoExtractFiles().
- if (!g_pExtractInfo) {
- if (g_hWndEdit) {
- SendMessage(g_hWndMain, WM_PRIVATE, MSG_ADD_TEXT_TO_EDIT,
- (LPARAM)buffer);
- } else {
- DebugOut(TEXT("Unhandled call to UzpMessagePrnt2("%S")"), buffer);
- }
- return 0;
- }
- // When extracting, mapname() will get called for every file which in turn
- // will call SetCurrentFile(). For testing though, mapname() never gets
- // called so we need to be on the lookout for a new file.
- if (g_pExtractInfo->dwFileOffset != (DWORD)((Uz_Globs*)pG)->pInfo->offset) {
- SetCurrentFile((Uz_Globs*)pG);
- }
- // Make sure this message was inteded for us to display.
- if (!MSG_NO_WGUI(flag) && !MSG_NO_WDLL(flag)) {
- // Insert a leading newline if requested to do so.
- if (MSG_LNEWLN(flag) && !g_pExtractInfo->fNewLineOfText) {
- SendMessage(g_hWndMain, WM_PRIVATE, MSG_ADD_TEXT_TO_EDIT, (LPARAM)"n");
- g_pExtractInfo->fNewLineOfText = TRUE;
- }
- // Since we use a proportional font, we need to do a little cleanup of the
- // text we are passed since it assumes a fixed font and adds padding to try
- // to line things up. We remove leading whitespace on any new line of text.
- if (g_pExtractInfo->fNewLineOfText) {
- while (*buffer == ' ') {
- buffer++;
- }
- }
- // We always remove trailing whitespace.
- LPSTR psz = (LPSTR)buffer + strlen((LPSTR)buffer) - 1;
- while ((psz >= (LPSTR)buffer) && (*psz == ' ')) {
- *(psz--) = ' ';
- }
- // Determine if the next line of text will be a new line of text.
- g_pExtractInfo->fNewLineOfText = ((*psz == 'r') || (*psz == 'n'));
- // Change all forward slashes to back slashes in the buffer
- ForwardSlashesToBackSlashesA((LPSTR)buffer);
- // Add the cleaned-up text to our extraction log edit control.
- SendMessage(g_hWndMain, WM_PRIVATE, MSG_ADD_TEXT_TO_EDIT, (LPARAM)buffer);
- // Append a trailing newline if requested to do so.
- if (MSG_TNEWLN(flag) || MSG_MNEWLN(flag) && !g_pExtractInfo->fNewLineOfText) {
- SendMessage(g_hWndMain, WM_PRIVATE, MSG_ADD_TEXT_TO_EDIT, (LPARAM)"n");
- g_pExtractInfo->fNewLineOfText = TRUE;
- }
- }
- return 0;
- }
- //******************************************************************************
- int UzpInput2(zvoid *pG, uch *buffer, int *size, int flag) {
- DebugOut(TEXT("WARNING: UzpInput2(...) called"));
- return 0;
- }
- //******************************************************************************
- void UzpMorePause(zvoid *pG, const char *szPrompt, int flag) {
- DebugOut(TEXT("WARNING: UzpMorePause(...) called"));
- }
- //******************************************************************************
- int UzpPassword(zvoid *pG, int *pcRetry, char *szPassword, int nSize,
- const char *szZipFile, const char *szFile)
- {
- // Return Values:
- // IZ_PW_ENTERED got some PWD string, use/try it
- // IZ_PW_CANCEL no password available (for this entry)
- // IZ_PW_CANCELALL no password, skip any further PWD request
- // IZ_PW_ERROR failure (no mem, no tty, ...)
- #if CRYPT
- // Build the data structure for our dialog.
- DECRYPT_INFO di;
- di.retry = *pcRetry;
- di.szPassword = szPassword;
- di.nSize = nSize;
- di.szFile = szFile;
- // Clear the password to be safe.
- *di.szPassword = ' ';
- // On our first call for a file, *pcRetry == 0. If we would like to allow
- // for retries, then we set the value of *pcRetry to the number of retries we
- // are willing to allow. We will be recalled as neccessary, each time with
- // *pcRetry being decremented once. 1 is the last retry we will get.
- *pcRetry = (*pcRetry == 0) ? MAX_PASSWORD_RETRIES : (*pcRetry - 1);
- // Pass control to our GUI thread which will prompt the user for a password.
- return SendMessage(g_hWndMain, WM_PRIVATE, MSG_PROMPT_FOR_PASSWORD, (LPARAM)&di);
- #else
- return -2;
- #endif
- }
- //******************************************************************************
- int WINAPI UzpReplace(char *szFile) {
- // Pass control to our GUI thread which will prompt the user to overwrite.
- return SendMessage(g_hWndMain, WM_PRIVATE, MSG_PROMPT_TO_REPLACE, (LPARAM)szFile);
- }
- //******************************************************************************
- void WINAPI UzpSound(void) {
- // Do nothing.
- }
- //******************************************************************************
- // Called from LIST.C
- void WINAPI SendAppMsg(ulg dwSize, ulg dwCompressedSize, int ratio, int month,
- int day, int year, int hour, int minute, int uppercase,
- char *szPath, char *szMethod, ulg dwCRC)
- {
- // If we are out of memory, then just bail since we will only make things worse.
- if (g_fOutOfMemory) {
- return;
- }
- // We get our Globals structure and then retrieve the real file name.
- GETGLOBALS()
- szPath = pG->filename;
- // Allocate a FILE_NODE large enough to hold this file.
- int length = strlen(szPath) + strlen(szMethod);
- g_pFileLast = (FILE_NODE*)new BYTE[sizeof(FILE_NODE) + (sizeof(TCHAR) * length)];
- // Bail out if we failed to allocate the node.
- if (!g_pFileLast) {
- DebugOut(TEXT("Failed to create a FILE_NODE for "%S"."), szPath);
- g_fOutOfMemory = TRUE;
- return;
- }
- // Fill in our node.
- g_pFileLast->dwSize = dwSize;
- g_pFileLast->dwCompressedSize = dwCompressedSize;
- g_pFileLast->dwCRC = dwCRC;
- g_pFileLast->szComment = NULL;
- g_pFileLast->szType = NULL;
- // Fix the year value to contain the real year.
- year += 1900;
- // Year: 0 - 4095 (12) 1111 1111 1111 0000 0000 0000 0000 0000 (0xFFF00000)
- // Month: 1 - 12 ( 4) 0000 0000 0000 1111 0000 0000 0000 0000 (0x000F0000)
- // Day: 1 - 31 ( 5) 0000 0000 0000 0000 1111 1000 0000 0000 (0x0000F800)
- // Hour: 0 - 23 ( 5) 0000 0000 0000 0000 0000 0111 1100 0000 (0x000007C0)
- // Minute: 0 - 59 ( 6) 0000 0000 0000 0000 0000 0000 0011 1111 (0x0000003F)
- // Do some bit shifting to make the date and time fit in a DWORD.
- g_pFileLast->dwModified = (((DWORD)(year & 0x0FFF) << 20) |
- ((DWORD)(month & 0x000F) << 16) |
- ((DWORD)(day & 0x001F) << 11) |
- ((DWORD)(hour & 0x001F) << 6) |
- ((DWORD)(minute & 0x003F)));
- // We need to get our globals structure to determine our attributes and
- // encryption information.
- g_pFileLast->dwAttributes = (pG->crec.external_file_attributes & 0xFF);
- if (pG->crec.general_purpose_bit_flag & 1) {
- g_pFileLast->dwAttributes |= FILE_ATTRIBUTE_ENCRYPTED;
- }
- // Store the path and method in our string buffer.
- strcpy(g_pFileLast->szPathAndMethod, szPath);
- strcpy(g_pFileLast->szPathAndMethod + strlen(szPath) + 1, szMethod);
- // Pass the file object to our windows code to have it added to our list.
- AddFileToListView(g_pFileLast);
- }
- //******************************************************************************
- int win_fprintf(FILE *file, unsigned int dwCount, char far *buffer) {
- // win_fprintf() is used within Info-ZIP to write to a file as well as log
- // information. If the "file" is a real file handle (not stdout or stderr),
- // then we write the data to the file and return.
- if ((file != stdout) && (file != stderr)) {
- DWORD dwBytesWriten = 0;
- #ifdef _WIN32_WCE
- // On WinCE all FILEs are really HANDLEs. See WINCE.CPP for more info.
- WriteFile((HANDLE)file, buffer, dwCount, &dwBytesWriten, NULL);
- #else
- dwBytesWriten = fwrite(buffer, 1, dwCount, file);
- #endif
- // Update our bytes written count.
- g_pExtractInfo->dwBytesWrittenThisFile += dwBytesWriten;
- // Pass control to our GUI thread to do a partial update our progress dialog.
- SendMessage(g_hWndMain, WM_PRIVATE, MSG_UPDATE_PROGRESS_PARTIAL,
- (LPARAM)g_pExtractInfo);
- // Check our abort flag.
- GETGLOBALS();
- CheckForAbort(pG);
- return dwBytesWriten;
- }
- // Check to see if we are expecting a extraction progress string
- if (g_pExtractInfo) {
- // Most of our progress strings come to our UzpMessagePrnt2() callback,
- // but we occasionally get one here. We will just forward it to
- // UzpMessagePrnt2() as if it never came here. To do this, we need to
- // get a pointer to our Globals struct. Calling GETGLOBALS() sort of
- // breaks us from be REENTRANT, but we don't support that anyway.
- GETGLOBALS();
- UzpMessagePrnt2(pG, (uch*)buffer, dwCount, 0);
- return dwCount;
- }
- // Check to see if we are expecting a zip file comment string.
- if (g_hWndEdit) {
- // Change all forward slashes to back slashes in the buffer
- ForwardSlashesToBackSlashesA((LPSTR)buffer);
- SendMessage(g_hWndMain, WM_PRIVATE, MSG_ADD_TEXT_TO_EDIT, (LPARAM)buffer);
- return dwCount;
- }
- // Check to see if we are expecting a compressed file comment string.
- if (g_pFileLast) {
- // Calcalute the size of the buffer we will need to store this comment.
- // We are going to convert all ASC values 0 - 31 (excpet tab, new line,
- // and CR) to ^char.
- int size = 1;
- for (char *p2, *p1 = buffer; *p1; p1++) {
- size += ((*p1 >= 32) || (*p1 == 't') || (*p1 == 'r') || (*p1 == 'n')) ? 1 : 2;
- }
- // Allocate a comment buffer and assign it to the last file node we saw.
- if (g_pFileLast->szComment = new CHAR[size]) {
- // Copy while formatting.
- for (p1 = buffer, p2 = (char*)g_pFileLast->szComment; *p1; p1++) {
- if ((*p1 >= 32) || (*p1 == 't') || (*p1 == 'r') || (*p1 == 'n')) {
- *(p2++) = *p1;
- } else {
- *(p2++) = '^';
- *(p2++) = 64 + *p1;
- }
- }
- *p2 = ' ';
- }
- // Update the attributes of the file node to incldue the comment attribute.
- g_pFileLast->dwAttributes |= FILE_ATTRIBUTE_COMMENT;
- // Clear the file node so we don't try to add another bogus comment to it.
- g_pFileLast = NULL;
- return dwCount;
- }
- if (dwCount >= _MAX_PATH) {
- buffer[_MAX_PATH] = ' ';
- }
- DebugOut(TEXT("Unhandled call to win_fprintf("%S")"), buffer);
- return dwCount;
- }
- //******************************************************************************
- //***** Functions that Info-ZIP expects the port to write and export.
- //***** Some of this code was stolen from the WIN32 port and highly modified.
- //******************************************************************************
- int mapattr(Uz_Globs *pG) {
- // Check to see if we are extracting this file for viewing. Currently, we do
- // this by checking the szMappedPath member of our extract info stucture
- // since we know OnActionView() is the only one who sets this member.
- if (g_pExtractInfo && g_pExtractInfo->szMappedPath) {
- // If we are extracting for view only, then we ignore the file's real
- // attributes and force the file to create as read-only. We make the file
- // read-only to help prevent the user from making changes to the temporary
- // file and then trying to save the changes back to a file that we will
- // eventually delete.
- pG->pInfo->file_attr = FILE_ATTRIBUTE_READONLY;
- } else {
- // Store the attribute exactly as it appears for normal extraction/test.
- pG->pInfo->file_attr = (unsigned)pG->crec.external_file_attributes & 0xff;
- }
- return PK_OK;
- }
- //******************************************************************************
- void utimeToFileTime(time_t ut, FILETIME *pft, BOOL fOldFileSystem) {
- // time_t is a 32-bit value for the seconds since January 1, 1970
- // FILETIME is a 64-bit value for the number of 100-nanosecond intervals since
- // January 1, 1601
- // DWORDLONG is a 64-bit int that we can use to perform large math operations.
- // time_t has minimum of 1/1/1970. Many file systems, such as FAT, have a
- // minimum date of 1/1/1980. If extracting to one of those file systems and
- // out time_t is less than 1980, then we make it 1/1/1980.
- // (365 days/yr * 10 yrs + 3 leap yr days) * (60 secs * 60 mins * 24 hrs).
- if (fOldFileSystem && (ut < 0x12CFF780)) {
- ut = 0x12CFF780;
- }
- // Compute the FILETIME for the given time_t.
- DWORDLONG dwl = ((DWORDLONG)116444736000000000 +
- ((DWORDLONG)ut * (DWORDLONG)10000000));
- // Store the return value.
- *pft = *(FILETIME*)&dwl;
- // Now for the next fix for old file systems. If we are in Daylight Savings
- // Time (DST) and the file is not in DST, then we need subtract off the DST
- // bias from the filetime. This is due to a bug in Windows (NT, CE, and 95)
- // that causes the DST bias to be added to all file times when the system
- // is in DST, even if the file is not in DST. This only effects old file
- // systems since they store local times instead of UTC times. Newer file
- // systems like NTFS and CEFS store UTC times.
- if (fOldFileSystem) {
- // We use the CRT's localtime() and Win32's FileTimeToLocalTime()
- // functions to compute the DST bias. This works because localtime()
- // correctly adds the DST bias only if the file time is in DST.
- // FileTimeToLocalTime() always adds the DST bias to the time.
- // Therefore, if the functions return different results, we know we
- // are dealing with a non-DST file during a system DST.
- FILETIME ftCRT, ftWin32;
- // Get the CRT result - result is a "tm" struct.
- struct tm *ptmCRT = localtime(&ut);
- // Convert the "tm" struct to a FILETIME.
- SYSTEMTIME stCRT;
- ZeroMemory(&stCRT, sizeof(stCRT));
- stCRT.wYear = ptmCRT->tm_year + 1900;
- stCRT.wMonth = ptmCRT->tm_mon + 1;
- stCRT.wDay = ptmCRT->tm_mday;
- stCRT.wHour = ptmCRT->tm_hour;
- stCRT.wMinute = ptmCRT->tm_min;
- stCRT.wSecond = ptmCRT->tm_sec;
- SystemTimeToFileTime(&stCRT, &ftCRT);
- // Get the Win32 result - result is a FILETIME.
- if (FileTimeToLocalFileTime(pft, &ftWin32)) {
- // Subtract the difference from our current filetime.
- *(DWORDLONG*)pft -= *(DWORDLONG*)&ftWin32 - *(DWORDLONG*)&ftCRT;
- }
- }
- }
- //******************************************************************************
- int GetFileTimes(Uz_Globs *pG, FILETIME *pftCreated, FILETIME *pftAccessed,
- FILETIME *pftModified)
- {
- // We need to check to see if this file system is limited. This includes
- // FAT, VFAT, and HPFS. It does not include NTFS and CEFS. The limited
- // file systems can not support dates < 1980 and they store file local times
- // for files as opposed to UTC times.
- BOOL fOldFileSystem = IsOldFileSystem(pG->filename);
- #ifdef USE_EF_UT_TIME // Always true for WinCE build
- #ifdef IZ_CHECK_TZ
- if (pG->extra_field && pG->tz_is_valid) {
- #else
- if (pG->extra_field) {
- #endif
- // Structure for Unix style actime, modtime, creatime
- iztimes z_utime;
- // Get any date/time we can. This can return 0 to 3 unix time fields.
- unsigned eb_izux_flg = ef_scan_for_izux(pG->extra_field,
- pG->lrec.extra_field_length, 0,
- pG->lrec.last_mod_file_date,
- &z_utime, NULL);
- // We require at least a modified time.
- if (eb_izux_flg & EB_UT_FL_MTIME) {
- // We know we have a modified time, so get it first.
- utimeToFileTime(z_utime.mtime, pftModified, fOldFileSystem);
- // Get the accessed time if we have one.
- if (eb_izux_flg & EB_UT_FL_ATIME) {
- utimeToFileTime(z_utime.atime, pftAccessed, fOldFileSystem);
- }
- // Get the created time if we have one.
- if (eb_izux_flg & EB_UT_FL_CTIME) {
- utimeToFileTime(z_utime.ctime, pftCreated, fOldFileSystem);
- }
- // Return our flags.
- return (int)eb_izux_flg;
- }
- }
- #endif // USE_EF_UT_TIME
- // If all else fails, we can resort to using the DOS date and time data.
- time_t ux_modtime = dos_to_unix_time(G.lrec.last_mod_file_date,
- G.lrec.last_mod_file_time);
- utimeToFileTime(ux_modtime, pftModified, fOldFileSystem);
- *pftAccessed = *pftModified;
- return (EB_UT_FL_MTIME | EB_UT_FL_ATIME);
- }
- //******************************************************************************
- void close_outfile(Uz_Globs *pG) {
- // Get the 3 time stamps for the file.
- FILETIME ftCreated, ftAccessed, ftModified;
- int timeFlags = GetFileTimes(pG, &ftCreated, &ftAccessed, &ftModified);
- TCHAR szFile[_MAX_PATH];
- mbstowcs(szFile, pG->filename, countof(szFile));
- #ifdef _WIN32_WCE
- // Cast the outfile to a HANDLE (since that is really what it is), and
- // flush the file. We need to flush, because any unsaved data that is
- // written to the file during CloseHandle() will step on the work done
- // by SetFileTime().
- HANDLE hFile = (HANDLE)pG->outfile;
- FlushFileBuffers(hFile);
- #else
- // Close the file and then re-open it using the Win32 CreateFile() call.
- // SetFileTime() requires a Win32 file HANDLE created with GENERIC_WRITE
- // access.
- fclose(pG->outfile);
- HANDLE hFile = CreateFile(szFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
- OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- #endif
- // Set the file's date and time.
- if (hFile != INVALID_HANDLE_VALUE) {
- // Make sure we retrieved some valid time stamp(s)
- if (timeFlags) {
- // Set the various date and time fields.
- if (!SetFileTime(hFile,
- (timeFlags & EB_UT_FL_CTIME) ? &ftCreated : NULL,
- (timeFlags & EB_UT_FL_ATIME) ? &ftAccessed : NULL,
- (timeFlags & EB_UT_FL_MTIME) ? &ftModified : NULL))
- {
- DebugOut(TEXT("SetFileTime() failed [%u]"), GetLastError());
- }
- } else {
- DebugOut(TEXT("GetFileTimes() failed"));
- }
- // Close out file.
- CloseHandle(hFile);
- } else {
- DebugOut(TEXT("CreateFile() failed [%u]"), GetLastError());
- }
- // If the file was successfully written, then set the attributes.
- if (!pG->disk_full && !g_pExtractInfo->fAbort) {
- if (!SetFileAttributes(szFile, G.pInfo->file_attr & 0x7F)) {
- DebugOut(TEXT("SetFileAttributes() failed [%u]"), GetLastError());
- }
- }
- // Clear outfile so we know it is closed.
- pG->outfile = 0;
- return;
- }
- //******************************************************************************
- // Called by PROCESS.C
- char* do_wild(Uz_Globs *pG, char *wildspec) {
- // This is a very slimmed down version of do_wild() taken from WIN32.C.
- // Since we don't support wildcards, we basically just return the wildspec
- // passed in as the filename.
- // First call - must initialize everything.
- if (!pG->notfirstcall) {
- pG->notfirstcall = TRUE;
- return strcpy(pG->matchname, wildspec);
- }
- // Last time through - reset for new wildspec.
- pG->notfirstcall = FALSE;
- return (char*)NULL;
- }
- //******************************************************************************
- // Called from EXTRACT.C
- //
- // returns: 1 - (on APPEND_NAME) truncated filename
- // 2 - path doesn't exist, not allowed to create
- // 3 - path doesn't exist, tried to create and failed; or
- // path exists and is not a directory, but is supposed to be
- // 4 - path is too long
- // 10 - can't allocate memory for filename buffers
- //
- // IZ_VOL_LABEL - Path was a volume label, skip it.
- // IZ_CREATED_DIR - Created a directory.
- //
- int mapname(Uz_Globs *pG, int renamed) {
- // mapname() is a great place to reset all our status counters for the next
- // file to be processed since it is called for every zip file member before
- // any work is done with that member.
- SetCurrentFile(pG);
- // If Volume Label, skip the "extraction" quietly
- if (pG->pInfo->vollabel) {
- return IZ_VOL_LABEL;
- }
- CHAR szBuffer[countof(pG->filename)] = "", *pIn, *pOut, *pLastSemi = NULL;
- // Initialize file path buffer with our "extract to" path.
- strcpy(szBuffer, g_szExtractToDirectory);
- pOut = szBuffer + strlen(szBuffer);
- // Point pIn to beginning of our internal pathname.
- // If we are junking paths, then locate the file portion of the path.
- pIn = (pG->UzO.jflag) ? (CHAR*)GetFileFromPath(pG->filename) : pG->filename;
- // Begin main loop through characters in filename.
- for ( ; *pIn; pIn++) {
- // Make sure we don't overflow our output buffer.
- if (pOut >= (szBuffer + countof(szBuffer) - 2)) {
- Info(slide, 1, ((char*)slide, "path too long: %sn", pG->filename));
- return 4;
- }
- // Examine the next character in our input buffer.
- switch (*pIn) {
- // Check for a directory wack.
- case '/':
- case '\':
- *pOut = ' ';
- if (!SmartCreateDirectory(pG, szBuffer)) {
- Info(slide, 1, ((char*)slide, "failure extracting: %sn",
- pG->filename));
- return 3;
- }
- *(pOut++) = '\';
- pLastSemi = NULL; // Leave any directory semi-colons alone
- break;
- // Check for illegal characters and replace with underscore.
- case ':':
- case '*':
- case '?':
- case '"':
- case '<':
- case '>':
- case '|':
- *(pOut++) = '_';
- break;
- // Check for start of VMS version.
- case ';':
- pLastSemi = pOut; // Make note as to where we are.
- *(pOut++) = *pIn; // Leave the semi-colon alone for now.
- break;
- default:
- // Allow European characters and spaces in filenames.
- *(pOut++) = ((*pIn >= 0x20) ? *pIn : '_');
- }
- }
- // Done with output buffer, terminate it.
- *pOut = ' ';
- // Remove any VMS version numbers if found (appended ";###").
- if (pLastSemi) {
- // Walk over all digits following the semi-colon.
- for (pOut = pLastSemi + 1; (*pOut >= '0') && (*pOut <= '9'); pOut++) {
- }
- // If we reached the end, then nuke the semi-colon and digits.
- if (!*pOut) {
- *pLastSemi = ' ';
- }
- }
- // Copy the mapped name back to the internal path buffer
- strcpy(pG->filename, szBuffer);
- // Fill in the mapped name buffer if the original caller requested us to.
- if (g_pExtractInfo->szMappedPath) {
- strcpy(g_pExtractInfo->szMappedPath, szBuffer);
- }
- // If it is a directory, then display the "creating" status text.
- if ((pOut > szBuffer) && (pOut[-1] == TEXT('\'))) {
- Info(slide, 0, ((char *)slide, "creating: %sn", pG->filename));
- return IZ_CREATED_DIR;
- }
- return PK_OK;
- }
- //******************************************************************************
- // Called from EXTRACT.C
- int test_NT(Uz_Globs *pG, uch *eb, unsigned eb_size) {
- // This function is called when an NT security descriptor is found in the
- // extra field. We have nothing to do, so we just return success.
- return PK_OK;
- }
- //******************************************************************************
- // Called from PROCESS.C
- int checkdir(Uz_Globs *pG, char *pathcomp, int flag) {
- // This function is only called by free_G_buffers() from PROCESS.C with the
- // flag set to END. We have nothing to do, so we just return success.
- return PK_OK;
- }
- //******************************************************************************
- // Called from EXTRACT.C and LIST.C
- int match(char *string, char *pattern, int ignore_case) {
- // match() for the other ports compares a file in the Zip file with some
- // command line file pattern. In our case, we always pass in exact matches,
- // so we can simply do a string compare to see if we have a match.
- return (strcmp(string, pattern) == 0);
- }
- //******************************************************************************
- // Called from PROCESS.C
- int iswild(char *pattern) {
- // Our file patterns never contain wild characters. They are always exact
- // matches of file names in our Zip file.
- return FALSE;
- }
- //******************************************************************************
- //***** Functions to correct time stamp bugs on old file systems.
- //******************************************************************************
- //******************************************************************************
- // Borrowed/Modified from win32.c
- BOOL IsOldFileSystem(char *szPath) {
- #ifdef _WIN32_WCE
- char szRoot[10];
- // Get the first nine characters of the path.
- strncpy(szRoot, szPath, 9);
- szRoot[9] = ' ';
- // Convert to uppercase to help with compare.
- _strupr(szRoot);
- // PC Cards are mounted off the root in a directory called "PC Cards".
- // PC Cards are FAT, no CEOS. We need to check if the file is being
- // extracted to the PC card.
- return !strcmp(szRoot, "\PC CARD\");
- #else
- char szRoot[_MAX_PATH] = "