⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zippie.cpp

📁 C编写的ZIP解压源吗!!! !!1告诉
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/////////////////////////////////////////////////////////////////////////////////
// zippie.cpp : Defines the entry point for the console application.
// STL program that uses the ZipArchive Library
//  
// Copyright (C) 2000 - 2007 Artpol Software - Tadeusz Dracz
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
// 
// For the licensing details see the file License.txt
////////////////////////////////////////////////////////////////////////////////

#if _MSC_VER > 1000
	// STL warnings
	#pragma warning (disable : 4786) // 'identifier' : identifier was truncated to 'number' characters in the debug information
#endif

#if defined __GNUC__ && !defined __MINGW32__
	#include "ZipArchive.h"
	#include "ZipPlatform.h"
	#include <sys/types.h>
	#include <sys/stat.h>
	#include <dirent.h>
	#include <fnmatch.h>
	#include <unistd.h>
#else
	#include "../ZipArchive/ZipArchive.h"
	#include "../ZipArchive/ZipPlatform.h"
#endif
#include "CmdLine.h"
#include <stdlib.h>
#include <list>
#include <time.h>
#include <stdio.h>

#ifndef __MINGW32__
	#include <locale>
#endif	


ZIPSTRINGCOMPARE pZipComp;


struct CZipAddFileInfo
{
	CZipAddFileInfo(const CZipString& szFilePath, const CZipString& szFileNameInZip)
		:m_szFilePath(szFilePath),	m_szFileNameInZip(szFileNameInZip)
	{
		int is = szFileNameInZip.GetLength();
		m_iSeparators = 0;
		for (int i = 0; i < is; i++)
			if (CZipPathComponent::IsSeparator(szFileNameInZip[i]))
				m_iSeparators++;
	}
	CZipString m_szFilePath, m_szFileNameInZip;
	
	bool CheckOrder(const CZipString& sz1, const CZipString& sz2, 
		int iSep1, int iSep2, bool bCheckTheBeginning = false) const
	{
		if (iSep1)
		{
			if (iSep2)
			{
				if (iSep1 == iSep2)
					return (sz1.*pZipComp)(sz2) < 0;

				if (bCheckTheBeginning)
				{

					int is = sz1.GetLength() > sz2.GetLength() ? sz2.GetLength() : sz1.GetLength();
					int iSeparators = 0;
					// find the common path beginning
					int iLastSepPos = -1;
					for (int i = 0; i < is; i++)
					{
						CZipString sz = sz2.Mid(i, 1);
						if ((sz1.Mid(i, 1).*pZipComp)(sz) != 0) // must be Mid 'cos of case sens. here
							break;
						else if (CZipPathComponent::IsSeparator(sz[0]))
						{
							iLastSepPos = i;
							iSeparators++;
						}
					}
					
					// if necessary remove the common path beginning and check again
					if (iLastSepPos != -1)
						return CheckOrder(sz1.Mid(iLastSepPos), sz2.Mid(iLastSepPos), iSep1 - iSeparators, iSep2 - iSeparators);
							
				}
				return (sz1.*pZipComp)(sz2) < 0;		
			} 
			else
				return false;
		}
		else
			if (iSep2)
				return true;
			else
				return (sz1.*pZipComp)(sz2) < 0;
	}
	bool operator>(const CZipAddFileInfo& wz) const
	{
		bool b = CheckOrder(m_szFileNameInZip, wz.m_szFileNameInZip,
			m_iSeparators, wz.m_iSeparators, true);
		return b;
	}
protected:
	int m_iSeparators; // for a sorting puroposes
};


typedef list<CZipString> FILELIST;
typedef list<CZipString>::iterator FILELISTIT;
typedef list<struct CZipAddFileInfo> FILELISTADD;
typedef list<struct CZipAddFileInfo>::iterator FILELISTADDIT;

struct AddDirectoryInfo
{
	AddDirectoryInfo(FILELIST& l):m_l(l){}
	FILELIST& m_l;
	CZipString m_lpszFile;
	bool m_bRecursive;
	bool m_bAddEmpty;
};

void DisplayUsage()
{
		printf("\
\n\
Zippie v3.2\n\
Copyright (C) 2000 - 2007 Artpol Software - Tadeusz Dracz\n\
E-Mail: tdracz@artpol-software.com\n\
Web   : http://www.artpol-software.com\n\
\n\
This program is free software; you can redistribute it and/or\n\
modify it under the terms of the GNU General Public License\n\
as published by the Free Software Foundation; either version 2\n\
of the License, or (at your option) any later version.\n\
\n\
This is a zipping and unzipping program.\n\
It was created using ZipArchive library in the STL version.\n\
\n\
\n\
USAGE: zippie <commands and (or) switches>\n\
\n\
Notes:\n\
	- the order of commands and switches doesn't matter\n\
	- if some files have spaces inside, put them inside quotation marks\n\
\n\
************  Default switches  ************\n\
\n\
-f <archive>[.zip]\n\
	<archive> file to create or open (can be with or without extension)\n\
	the extension .zip is added automatically if not present\n\
-st\n\
	use this switch if you're opening an existing split archive\n\
	on a removable device (or under Linux)\n\
	(doesn't matter for commands that modify the archive \n\
	e.g. add or delete commands)\n\
\n\
************  Add files to archive commands  ************\n\
\n\
-a <files>\n\
	add <files> to the <archive>; separate them with spaces;\n\
	you can use wildcards (*?)\n\
-af <file>\n\
	add files listed in <file> (one file per line);\n\
	no wildcards allowed in the files\n\
-ax <files>\n\
	prevent <files> from being added to the <archive>;\n\
	separate them with spaces; you can use wildcards (*?)\n\
-afx <file>\n\
	prevent files listed in <file> (one file per line) to be added \n\
	to the <archive>; no wildcards allowed in the files\n\
\n\
	you can use switches -a, -af, -ax, -afx simultaneously\n");
	printf("\
\n\
-r\n\
	recurse subdirectories; don't include in the <archive> directories\n\
	from which no file is added; under linux put file masks into \n\
	quotation marks otherwise they will be automatically expaned by \n\
	the shell and the recursion will be one level only\n\
-re\n\
	recurse subdirectories and add all subdirectories even empty to the\n\
	<archive>; see a note above about using file masks under Linux\n\
-u\n\
	this switch tells the program to not delete the <archive> if it\n\
	already	exists (and if it is not a segmented archive), but add\n\
	the <files> to it;\n\
	if this switch is not specified, there is a new archive created\n\
	even if one with the same name already exists (it is overwritten)\n\
-as [<path>]\n\
	(add smartly) if this switch is specified, for a segmented archive\n\
	the file is first compressed to a temporary directory to see whether \n\
	it is smaller after compression; if it is not it stored then without \n\
	a compression; (you can specify a <path> where the temporary files \n\
	will be created, if you do not specify it, they will be created in \n\
	the directory specified by the TMP system variable or if this variable\n\
	is not defined the file will be created in the current directory;\n\
	in normal archive if there is a such a situation the file is removed\n\
	from the archive and then stored again but with no compression \n\
	(the <path> argument is ignored)\n");
#ifdef _BZIP2
	printf("\
-bz\n\
	use bzip2 compression algorithm instead of deflate which is used by default\n");
#endif
	printf("\
-c <number>\n\
	set the compression level (from 0 to 9);\n\
	if not specified, 5 is assumed\n\
	0 means no compression - only storing\n\
-v <size>\n\
	create a segmented archive\n\
	if <size> is 0 create a spanning archive,\n\
	if <size> is greater than 0 create a split archive\n\
\n");
		printf("\
************  Extract commands  ************\n\
\n\
-xp <path>\n\
	it specifies the path the files	will be extracted to; if not present,\n\
	the current path is assumed\n\
-x  <files>\n\
	extract <files> to the destination <path>;\n\
	separate them with spaces; wildcards are allowed\n\
-xr <numbers>\n\
	extract files with the given <numbers> to the destination <path>\n\
	separate number with spaces; to specify a range of numbers \n\
	put between them a hyphen without spaces e.g. 3-6; \n\
	put before an exclamation mark to exclude the numbers from the set\n\
	(e.g. 2-20 !6-8 !10);\n\
	(use -lr command to list the files with numbers)\n\
-xf <file>\n\
	extract files listed in <file> (one file per line)\n\
	to the destination <path>; wildcards are allowed\n\
-xa \n\
	extract all files from the archive to the <path>\n\
\n\
	you can use switches -x , -xr and -xf (and even -xa) simultaneously\n\
\n\
************  Delete commands  ************\n\
\n\
-d  <files>\n\
	delete <files> separate them with spaces; wildcards are allowed\n");
		printf("\
-dr <numbers>\n\
	delete files with the given <numbers>\n\
	separate number with spaces; to specify a range of numbers \n\
	put between them a hyphen without spaces e.g. 3-6 \n\
	put before an exclamation mark to exclude the numbers from the set\n\
	(e.g. 2-20 !6-8 !10);\n\
	(use -lr command to list the files with numbers)\n\
-df <file>\n\
	delete files listed in <file> (one file per line)\n\
	wildcards are allowed\n\
-da \n\
	delete all the files from the archive\n\
\n\
	you can use switches -d , -dr and -df (and even -da) simultaneously\n\
\n\
************  Other commands  ************\n\
\n\
-t\n\
	test the <archive>\n\
-p <password>\n\
	set the <password> when adding files to <archive>\n\
	or extracting them; the <password> is set for all the files\n\
	- you cannot set it separately for each file in one session\n\
-en <0|1|2|3>\n\
	set the encryption method when encrypting; the password\n\
	be set for the file(s) to be encrypted; the meaning of the\n\
	values is following:\n\
	0: standard PKZIP (default)\n\
	1: AES 128-bit WinZip\n\
	2: AES 192-bit WinZip\n\
	3: AES 256-bit WinZip\n\
-l\n\
	list the files inside <archive>\n\
-lr\n\
	list the files inside <archive> with the numbers\n\
-ll\n\
	list the files inside <archive> (only filenames)\n\
	when redirected to a file, it can be used then with command -xf\n\
\n");
		printf("\
************  Special switches  ************\n\
\n\
-cs \n\
	enable case sensitivity when:\n\
	- searching for files inside <archive> while using the command\n\
		-x or -xf (if not specified a search is non-case-sensitive)\n\
	- adding files to <archive> and trying to avoid the same\n\
		filenames in the archive\n\
-g <comment>\n\
	Set the global <comment> of the <archive>\n\
	(cannot be used on an existing segmented archive)\n\
	if the <comment> contains spaces, put the whole <comment>\n\
	inside quotation marks\n\
-rp <path>\n\
	set root <path> (see CZipArchive::SetRootPath() function description)\n\
-nd\n\
	skip removing duplicates when adding files; may be usefull if adding many files\n\
-nfp\n\
	the same as bFullPath set to false in functions\n\
	CZipArchive::AddNewFile() and CZipArchive::ExtractFile()\n\
	(if not present, bFullPath is assumed to be true; if -rp specified\n\
	bFullPath is always false)\n\
");
#ifdef _UNICODE // this will not work for now - there is no unicode version
printf("-utf\n\
	store filenames encoded as UTF8\n\
-utfe\n\
	store filenames encoded as UTF8 in an extra field (in central and local directory\n\
	filenames are stored as usually (only the Unicode compilation)\n\
");
#endif
printf("\
-w\n\
	Wait for a key after finishing the work to let the user read the output\n\
	in some environments\n\
-dse\n\
	Display only errors when adding or extracting files\n\
\n\
************  Sample commands  ************\n\
\n\
zippie -f a:\\archive -a * -v 0 -as -c 9 \n\
	(create a disk spanning archive adding all the files from the current \n\
	directory, smart add is used, compression level set to maximum)\n\
\n\
zippie -f a:\\archive -xp d:\\a -x zippie.cpp -xr 2-12 !5-7 !9\n\
	(extract file zippie.cpp from the archive and the files with numbers \n\
	from 2 to 12 and the file number 15 apart from 5 to 7 and 9)\n\
\n\
zippie -f example -xa\n\
	extract all files from example.zip file to the current directory\n\
\n\
");
}

char ReadKey()
{
	fflush (stdin);
	char c = (char) tolower(getchar());
	return c;
}

struct SpanCallback : public CZipSegmCallback
{
	bool Callback(ZIP_SIZE_TYPE uProgress)
	{
		printf ("Insert disk number %d and hit ENTER to continue \n or press 'n' key followed by ENTER to abort (code = %d)\n", m_uVolumeNeeded, m_iCode);	
		return ReadKey() != 'n';
	}
};

void FillFromFile(FILELIST& l, LPCTSTR lpszFile, bool bCheck)
{
	FILE* f;
#if _MSC_VER >= 1400
	if (fopen_s(&f, lpszFile, "rt") != 0)
		f = NULL;
#else
	f = fopen(lpszFile, "rt");
#endif
	
	if (!f)
	{
		printf ("File %s could not be opened\n", lpszFile);
		return;
	}
	fseek(f, 0, SEEK_END);
	size_t iSize = ftell(f);
	fseek(f, 0, SEEK_SET);
	CZipAutoBuffer buf((DWORD)(iSize + 1));
	iSize = fread(buf, 1, iSize, f);
	fclose(f);
	char* sEnd = (char*)buf + iSize;
	char* sBeg = buf;
	for (char* pos = buf; ; pos++)
	{
		bool bEnd = pos == sEnd; // there may be no newline at the end
		if (strncmp(pos, "\n", 1) == 0 || bEnd)
		{
			*pos = '\0';
			CZipString s = sBeg;
			s.TrimLeft(" ");
			s.TrimRight(" ");
			if (!s.IsEmpty() && (!bCheck || ZipPlatform::FileExists(s) != 0))
				l.push_back(s);
			if (bEnd)
				break;
			sBeg = pos + 1;			
		}
	}
}




bool IsDots(LPCTSTR lpsz)
{
	return strcmp(lpsz, ".") == 0 || strcmp(lpsz, "..") == 0;
}

void AddDirectory(CZipString szPath, struct AddDirectoryInfo& info, bool bDoNotAdd)
{
	if (!szPath.IsEmpty())
		CZipPathComponent::AppendSeparator(szPath);

	bool bPathAdded = info.m_bAddEmpty || bDoNotAdd;
	if (info.m_bAddEmpty && !szPath.IsEmpty() && !bDoNotAdd)
		info.m_l.push_back(szPath);

#if defined __GNUC__ && !defined __MINGW32__
	DIR* dp = opendir(szPath.IsEmpty() ? "." : szPath);
	if (!dp)
		return;
	struct dirent* entry;
	while (entry = readdir(dp))
	{
		struct stat sStats;
		CZipString szFullFileName = szPath + entry->d_name;
		if (stat(szFullFileName, &sStats) == -1)
			continue;
		if (S_ISDIR(sStats.st_mode))
		{
			if (info.m_bRecursive)
			{
				if (IsDots(entry->d_name))
					continue;
				
				AddDirectory(szFullFileName, info, false);
			}
		}
		else if (fnmatch(info.m_lpszFile, entry->d_name, FNM_NOESCAPE |FNM_PATHNAME) == 0)
		{
			if (!bPathAdded)
			{
				if (!szPath.IsEmpty())
					info.m_l.push_back(szPath);
				bPathAdded = true;
			}
			info.m_l.push_back(szPath + entry->d_name);
		}
	}
	closedir(dp);

#else
    CZipString szFullFileName = szPath + info.m_lpszFile;
	struct _finddata_t c_file;
	intptr_t hFile;
#ifdef __BORLANDC__
	if( (hFile = _findfirst( (LPTSTR)(LPCTSTR)szFullFileName, &c_file )) != -1L )
#else
	if( (hFile = _findfirst( szFullFileName, &c_file )) != -1L )
#endif		
	{
		do
		{
			if (!(c_file.attrib & FILE_ATTRIBUTE_DIRECTORY))
			{
				// add it when the first file comes
				if (!bPathAdded)
				{
					if (!szPath.IsEmpty())
						info.m_l.push_back(szPath);
					bPathAdded = true;
				}
				info.m_l.push_back(szPath + c_file.name);
			}
		}
		while (_findnext(hFile, &c_file) == 0L);
	}
	_findclose(hFile);

	if (info.m_bRecursive)
	{
		szFullFileName = szPath + "*";
#ifdef __BORLANDC__		
		if( (hFile = _findfirst( (LPTSTR)(LPCTSTR)szFullFileName, &c_file )) != -1L )
#else
		if( (hFile = _findfirst( szFullFileName, &c_file )) != -1L )
#endif
		{
			do
			{
				if (c_file.attrib & FILE_ATTRIBUTE_DIRECTORY)
				{
					if (IsDots(c_file.name))
						continue;
					szFullFileName = szPath + c_file.name;
					AddDirectory(szFullFileName, info, false);
				}
			}
			while (_findnext(hFile, &c_file) == 0L);
		}
		_findclose(hFile);		
	}
#endif
}
 
void ExpandFile(FILELIST& l, LPCTSTR lpszPath, 
			 	bool bRecursive, bool bAddEmpty, bool bFullPath)
{
// check if we need to expand it
//         size_t pos = strcspn(lpszFile, "*?");
//         if (pos == strlen(lpszFile))
//         {
//                 l.push_back(lpszFile);
//                 return;
//         }

	CZipPathComponent zpc(lpszPath);
	CZipString szDir = zpc.GetFilePath();
// 	if (szDir.IsEmpty())
// 		if (!ZipPlatform::GetCurrentDirectory(szDir))
// 			return;
	struct AddDirectoryInfo adi(l);
	adi.m_bAddEmpty = bAddEmpty;
	adi.m_bRecursive = bRecursive;
	adi.m_lpszFile = zpc.GetFileName();
	AddDirectory(szDir, adi, !bFullPath); // when not full path is specified for a single file with a path, do not add a directory then
}


void FindInZip(CZipArchive& zip, FILELIST& l, CZipIndexesArray& n)
{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -