1、第一次感觉MS也有这么难用的MFC类;
2、CFtpFileFind类只能实例化一个,多个实例同时查找会出错(因此下载时不能递归),采用队列存储目录再依次下载;
3、本程序支持文件夹嵌套上传下载;
4、boost::filesystem::create_directory不能递归创建文件夹,需手动实现
5、同时支持文件夹先打包压缩再上传功能(m_bZibFlag控制是否压缩)
代码如下:
CFtpClient.h
1 #ifndef __ftp_client_h__ 2 #define __ftp_client_h__ 3 4 #include <afxinet.h> 5 #include <iostream> 6 #include <sstream> 7 #include <queue> 8 #include <boost/filesystem/operations.hpp> 9 #include <boost/filesystem/path.hpp> 10 #include "zip.h" 11 12 class CFtpClient 13 { 14 public: 15 CFtpClient(); 16 ~CFtpClient(); 17 18 bool Connect(); 19 bool Close(); 20 int Download(std::string strServerDir = "\\", std::string strFilename = "*"); 21 int Upload(const std::string strLocalPath); 22 private: 23 //下载文件夹 24 int DownloadFolder(); 25 //下载文件 26 int DownloadFile(std::string strServerDir, std::string strFilename); 27 //创建多级目录 28 void CreateDirectory(boost::filesystem::path path); 29 //获取打包压缩文件名称 30 std::string GetZipFolder(const std::string strFolderPath); 31 //压缩文件夹打包 32 void MakeZipFolder(HZIP hz, const std::string strRoot, const std::string strFolderPath); 33 private: 34 CInternetSession* m_pInternetSession; 35 CFtpConnection* m_pFtpConnection; 36 37 //参数配置 38 std::string m_strServerAddress; //FTP:服务器地址 39 int m_nServerPort; //FTP:服务器端口号 40 std::string m_strUsername; //FTP:登录用户名 41 std::string m_strPassword; //FTP:登录密码 42 bool m_bZibFlag; //文件夹打包上传标志[true:先压缩文件夹打包再上传,false:直接上传文件夹] 43 44 std::string m_strUploadServerDir; //上传服务器存储目录 45 std::string m_strDownloadLocalDir; //下载本地存储目录 46 std::queue<std::string> queServerDir; //等待下载目录队列 47 }; 48 49 50 #endif
CFtpClient.cpp
1 //------------------------------------------------------------------------------ 2 // 版权声明:转载请注明出处 5 // 模块名称: 6 // 模块描述:FTP上传下载类 7 // 开发作者:可笑痴狂 http://www.cnblogs.com/dongsheng/ 8 // 创建日期:2015-12-10 9 // 模块版本:1.0.0.0 10 // 备注:压缩算法引入zip.h和zip.cpp文件,无需lib或dll, 11 // 详情参考:http://www.codeproject.com/Articles/7530/Zip-Utils-clean-elegant-simple-C-Win 12 //------------------------------------------------------------------------------ 13 14 #include <string> 15 #include <iostream> 16 #include <sstream> 17 #include "CFtpClient.h" 18 #include <boost/assert.hpp> 19 #include <boost/lexical_cast.hpp> 20 #include <boost/foreach.hpp> 21 22 23 CFtpClient::CFtpClient() 24 { 25 m_pInternetSession = NULL; 26 m_pFtpConnection = NULL; 27 m_strServerAddress = "127.0.0.1"; 28 m_strUsername = "123"; 29 m_strPassword = "123"; 30 m_nServerPort = 21; 31 m_strDownloadLocalDir = "D:\\DownloadLocal"; 32 m_strUploadServerDir = "\\"; 33 m_bZibFlag = true; 34 } 35 36 CFtpClient::~CFtpClient() 37 { 38 this->Close(); 39 } 40 41 bool CFtpClient::Connect() 42 { 43 if (m_pInternetSession != NULL) 44 { 45 return true; 46 } 47 48 m_pInternetSession = new CInternetSession("OTC_FTP_Client"); 49 int nCnt = 1; 50 while(nCnt++) 51 { 52 try 53 { 54 m_pFtpConnection = m_pInternetSession->GetFtpConnection(m_strServerAddress.c_str(), m_strUsername.c_str(), m_strPassword.c_str(),
m_nServerPort); 55 } 56 catch(CInternetException *pEx) 57 { 58 char szErrMsg[1024+1] = {0}; 59 if (pEx->GetErrorMessage(szErrMsg, 1024)) 60 { 61 std::cout << "连接FTP服务器失败, ErrMsg:" << szErrMsg << std::endl; 62 if (nCnt > 5) 63 { 64 return false; 65 } 66 std::cout << "正在尝试重新连接[" << nCnt-1 << "]......" << std::endl; 67 } 68 continue; 69 } 70 return true; 71 } 72 73 return true; 74 } 75 76 bool CFtpClient::Close() 77 { 78 if (NULL != m_pInternetSession) 79 { 80 m_pInternetSession->Close(); 81 delete m_pInternetSession; 82 m_pInternetSession = NULL; 83 } 84 if (NULL != m_pFtpConnection) 85 { 86 m_pFtpConnection->Close(); 87 delete m_pFtpConnection; 88 m_pFtpConnection = NULL; 89 } 90 91 return true; 92 } 93 int CFtpClient::Download(std::string strServerDir /*="\\"*/, std::string strFilename /*= "*"*/) 94 { 95 if ("*" == strFilename) 96 { 97 queServerDir.push(strServerDir); 98 return this->DownloadFolder(); 99 } 100 else 101 { 102 return this->DownloadFile(strServerDir, strFilename); 103 } 104 105 } 106 int CFtpClient::DownloadFile(std::string strServerDir, std::string strFilename) 107 { 108 int nRet = 0; 109 CFtpFileFind* pFtpFileFind = NULL; 110 if(!this->Connect()) 111 { 112 nRet = -1; 113 goto __end; 114 } 115 else 116 { 117 boost::filesystem::path LocalPath(m_strDownloadLocalDir); 118 if (!boost::filesystem::exists(LocalPath)) 119 { 120 this->CreateDirectory(LocalPath); 121 } 122 if (0 == m_pFtpConnection->SetCurrentDirectory(strServerDir.c_str())) 123 { 124 nRet = -1; 125 std::cout << "设置服务器下载目录[" << strServerDir << "]失败!ErrCode=" << GetLastError() << std::endl; 126 DWORD dw = 0; 127 char szBuf[512]={0}; 128 DWORD dwLen = sizeof(szBuf)-1; 129 InternetGetLastResponseInfo(&dw, szBuf, &dwLen); 130 std::cout << "错误信息:" << szBuf << std::endl; 131 goto __end; 132 } 133 if (pFtpFileFind == NULL) 134 { 135 pFtpFileFind = new CFtpFileFind(m_pFtpConnection); 136 } 137 int nRet = pFtpFileFind->FindFile(strFilename.c_str()); 138 if(nRet) 139 { 140 nRet = pFtpFileFind->FindNextFile(); 141 142 std::string strLocalFilename = m_strDownloadLocalDir + "\\" + strFilename; 143 std::string strServerFilename = strFilename; 144 if(m_pFtpConnection->GetFile(strServerFilename.c_str(), strLocalFilename.c_str(), FALSE)) 145 std::cout << "下载文件[" << strServerFilename << "]到[" << strLocalFilename << "]成功!" << std::endl; 146 else 147 { 148 std::cout << "下载文件[" << strServerFilename << "]到[" << strLocalFilename << "]失败!" << std::endl; 149 char szBuf[512]={0}; 150 DWORD dw = 0; 151 DWORD dwLen = sizeof(szBuf)-1; 152 InternetGetLastResponseInfo(&dw, szBuf, &dwLen); 153 dw = GetLastError(); 154 std::cout << "错误信息:" << szBuf << std::endl; 155 nRet = -1; 156 } 157 } 158 } 159 __end: 160 this->Close(); 161 if (pFtpFileFind) 162 { 163 pFtpFileFind->Close(); 164 delete pFtpFileFind; 165 } 166 167 return nRet; 168 } 169 int CFtpClient::DownloadFolder() 170 { 171 std::string strServerDir; 172 std::string strFilename; 173 CFtpFileFind* pFtpFileFind = NULL; 174 int nRet = 0; 175 176 if(!this->Connect()) 177 { 178 nRet = -1; 179 goto __end; 180 } 181 else 182 { 183 while(!queServerDir.empty()) 184 { 185 strServerDir = queServerDir.front(); 186 queServerDir.pop(); 187 188 boost::filesystem::path LocalPath(m_strDownloadLocalDir); 189 if (!boost::filesystem::exists(LocalPath / strServerDir)) 190 { 191 this->CreateDirectory(LocalPath / strServerDir); 192 } 193 194 if (0 == m_pFtpConnection->SetCurrentDirectory(strServerDir.c_str())) 195 { 196 nRet = -1; 197 std::cout << "设置服务器下载目录[" << strServerDir << "]失败!ErrCode=" << GetLastError() << std::endl; 198 DWORD dw = 0; 199 char szBuf[512]={0}; 200 DWORD dwLen = sizeof(szBuf)-1; 201 InternetGetLastResponseInfo(&dw, szBuf, &dwLen); 202 std::cout << "错误信息:" << szBuf << std::endl; 203 goto __end; 204 } 205 if (pFtpFileFind == NULL) 206 { 207 pFtpFileFind = new CFtpFileFind(m_pFtpConnection); 208 } 209 210 int nRet = pFtpFileFind->FindFile(); 211 while(nRet) 212 { 213 nRet = pFtpFileFind->FindNextFile(); 214 strFilename = pFtpFileFind->GetFilePath(); 215 if (pFtpFileFind->IsDirectory()) 216 { 217 queServerDir.push(std::string(pFtpFileFind->GetFilePath())); 218 continue; 219 } 220 221 std::string strLocalFilename = m_strDownloadLocalDir + strFilename; 222 std::string strServerFilename = strFilename; 223 224 if(m_pFtpConnection->GetFile(strServerFilename.c_str(), strLocalFilename.c_str(), FALSE)) 225 std::cout << "下载文件[" << strServerFilename << "]到[" << strLocalFilename << "]成功!" << std::endl; 226 else 227 { 228 std::cout << "下载文件[" << strServerFilename << "]到[" << strLocalFilename << "]失败!" << std::endl; 229 char szBuf[512]={0}; 230 DWORD dw = 0; 231 DWORD dwLen = sizeof(szBuf)-1; 232 InternetGetLastResponseInfo(&dw, szBuf, &dwLen); 233 dw = GetLastError(); 234 std::cout << "错误信息:" << szBuf << std::endl; 235 nRet = -1; 236 } 237 } 238 } 239 } 240 __end: 241 this->Close(); 242 if (pFtpFileFind != NULL) 243 { 244 pFtpFileFind->Close(); 245 delete pFtpFileFind; 246 } 247 return nRet; 248 } 249 250 int CFtpClient::Upload(const std::string strLocalPath) 251 { 252 int nRet = 0; 253 CFtpFileFind* pFtpFileFind = NULL; 254 boost::filesystem::path localPath(strLocalPath); 255 256 if (m_bZibFlag) 257 {//文件夹先压缩再上传 258 if (boost::filesystem::exists(localPath)) 259 { 260 if (boost::filesystem::is_directory(localPath)) 261 { 262 std::string strUploadName = this->GetZipFolder(localPath.string()); 263 localPath = strUploadName;//改为上传压缩文件 264 } 265 } 266 else 267 { 268 std::cout << "指定上传文件不存在!" << std::endl; 269 nRet = -1; 270 goto __end; 271 } 272 } 273 274 275 //由于压缩大文件很耗时,为防止长时间占用FTP连接产生的异常,因此先压缩文件后连接上传。 276 if(!this->Connect()) 277 { 278 nRet = -1; 279 goto __end; 280 } 281 else 282 { 283 if (0 == m_pFtpConnection->SetCurrentDirectory(m_strUploadServerDir.c_str())) 284 { 285 nRet = -1; 286 std::cout << "设置服务器上传目录[" << m_strUploadServerDir << "]失败!ErrCode=" << GetLastError() << std::endl; 287 DWORD dw = 0; 288 char szBuf[512]={0}; 289 DWORD dwLen = sizeof(szBuf)-1; 290 InternetGetLastResponseInfo(&dw, szBuf, &dwLen); 291 std::cout << "错误信息:" << szBuf << std::endl; 292 goto __end; 293 } 294 295 if (boost::filesystem::exists(localPath)) 296 { 297 if (boost::filesystem::is_directory(localPath)) 298 { 299 m_pFtpConnection->CreateDirectory(localPath.leaf().string().c_str()); 300 301 //directory_iterator:只支持本层目录遍历 302 boost::filesystem::directory_iterator itor_begin(localPath); 303 boost::filesystem::directory_iterator itor_end; 304 305 std::string strServerDir = m_strUploadServerDir; 306 for (; itor_begin != itor_end; itor_begin++) 307 {//回溯算法 308 m_strUploadServerDir += std::string("\\") + localPath.leaf().string(); 309 this->Upload(itor_begin->path().string()); 310 m_strUploadServerDir = strServerDir; 311 } 312 313 } 314 else 315 { 316 if(m_pFtpConnection->PutFile(localPath.string().c_str(), localPath.leaf().string().c_str(), 317 FTP_TRANSFER_TYPE_BINARY,0)) 318 std::cout << "上传文件[" << localPath.leaf().string() << "]成功!" << std::endl; 319 else 320 { 321 DWORD dw0 = GetLastError(); 322 if (dw0) 323 { 324 char szBuf[512]={0}; 325 DWORD dw = 0; 326 DWORD dwLen = sizeof(szBuf)-1; 327 InternetGetLastResponseInfo(&dw, szBuf, &dwLen); 328 std::cout << "上传文件[" << localPath.leaf().string() << "]失败!ErrCode:" << dw0 << "ErrMsg:" << szBuf << std::endl; 329 goto __end; 330 } 331 } 332 } 333 } 334 else 335 { 336 std::cout << "指定上传文件不存在!" << std::endl; 337 nRet = -1; 338 goto __end; 339 } 340 } 341 342 __end: 343 if (pFtpFileFind != NULL) 344 { 345 pFtpFileFind->Close(); 346 delete pFtpFileFind; 347 } 348 this->Close(); 349 return nRet; 350 } 351 352 void CFtpClient::CreateDirectory(boost::filesystem::path path) 353 { 354 boost::filesystem::path::iterator itor = path.begin(); 355 boost::filesystem::path pathTmp; 356 while(itor != path.end()) 357 { 358 pathTmp /= (*itor).string(); 359 if (!pathTmp.empty() && !boost::filesystem::exists(pathTmp)) 360 { 361 boost::filesystem::create_directory(pathTmp); 362 } 363 ++itor; 364 } 365 } 366 367 std::string CFtpClient::GetZipFolder(const std::string strFolderPath) 368 { 369 boost::filesystem::path pathFolder(strFolderPath); 370 std::string strZipName = strFolderPath + ".zip"; 371 std::string strRootPath = pathFolder.branch_path().string(); 372 373 HZIP hz = CreateZip(strZipName.c_str(), 0); 374 this->MakeZipFolder(hz, strRootPath, strFolderPath); 375 CloseZip(hz); 376 377 return strZipName; 378 } 379 380 void CFtpClient::MakeZipFolder(HZIP hz, const std::string strRoot, const std::string strFolderPath) 381 { 382 boost::filesystem::path FolderPath(strFolderPath); 383 ZipAddFolder(hz, FolderPath.leaf().string().c_str()); 384 385 //recursive_directory_iterator:支持深层目录遍历 386 boost::filesystem::recursive_directory_iterator itor_begin(FolderPath); 387 boost::filesystem::recursive_directory_iterator itor_end; 388 389 for (; itor_begin != itor_end; itor_begin++) 390 { 391 std::cout << "正在压缩文件:" << itor_begin->path().string() << "......" << std::endl; 392 std::string strFilePath = itor_begin->path().string(); 393 int nPos = strFilePath.find(strRoot); 394 if (nPos != std::string::npos) 395 {//取得相对于压缩文件本身的路径 396 strFilePath = strFilePath.substr(nPos+strRoot.length()); 397 } 398 399 if (boost::filesystem::is_directory(*itor_begin)) 400 { 401 ZipAddFolder(hz, strFilePath.c_str()); 402 } 403 else 404 { 405 ZipAdd(hz, strFilePath.c_str(), itor_begin->path().string().c_str()); 406 } 407 } 408 }
zip.h
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #ifndef _zip_H 2 #define _zip_H 3 // 4 #ifdef ZIP_STD 5 #include <time.h> 6 #define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name 7 #ifndef MAX_PATH 8 #define MAX_PATH 1024 9 #endif 10 typedef unsigned long DWORD; 11 typedef char TCHAR; 12 typedef FILE* HANDLE; 13 typedef time_t FILETIME; 14 #endif 15 16 // ZIP functions -- for creating zip files 17 // This file is a repackaged form of the Info-Zip source code available 18 // at www.info-zip.org. The original copyright notice may be found in 19 // zip.cpp. The repackaging was done by Lucian Wischik to simplify and 20 // extend its use in Windows/C++. Also to add encryption and unicode. 21 22 23 #ifndef _unzip_H 24 DECLARE_HANDLE(HZIP); 25 #endif 26 // An HZIP identifies a zip file that is being created 27 28 typedef DWORD ZRESULT; 29 // return codes from any of the zip functions. Listed later. 30 31 32 33 HZIP CreateZip(const TCHAR *fn, const char *password); 34 HZIP CreateZip(void *buf,unsigned int len, const char *password); 35 HZIP CreateZipHandle(HANDLE h, const char *password); 36 // CreateZip - call this to start the creation of a zip file. 37 // As the zip is being created, it will be stored somewhere: 38 // to a pipe: CreateZipHandle(hpipe_write); 39 // in a file (by handle): CreateZipHandle(hfile); 40 // in a file (by name): CreateZip("c:\\test.zip"); 41 // in memory: CreateZip(buf, len); 42 // or in pagefile memory: CreateZip(0, len); 43 // The final case stores it in memory backed by the system paging file, 44 // where the zip may not exceed len bytes. This is a bit friendlier than 45 // allocating memory with new[]: it won't lead to fragmentation, and the 46 // memory won't be touched unless needed. That means you can give very 47 // large estimates of the maximum-size without too much worry. 48 // As for the password, it lets you encrypt every file in the archive. 49 // (This api doesn't support per-file encryption.) 50 // Note: because pipes don't allow random access, the structure of a zipfile 51 // created into a pipe is slightly different from that created into a file 52 // or memory. In particular, the compressed-size of the item cannot be 53 // stored in the zipfile until after the item itself. (Also, for an item added 54 // itself via a pipe, the uncompressed-size might not either be known until 55 // after.) This is not normally a problem. But if you try to unzip via a pipe 56 // as well, then the unzipper will not know these things about the item until 57 // after it has been unzipped. Therefore: for unzippers which don't just write 58 // each item to disk or to a pipe, but instead pre-allocate memory space into 59 // which to unzip them, then either you have to create the zip not to a pipe, 60 // or you have to add items not from a pipe, or at least when adding items 61 // from a pipe you have to specify the length. 62 // Note: for windows-ce, you cannot close the handle until after CloseZip. 63 // but for real windows, the zip makes its own copy of your handle, so you 64 // can close yours anytime. 65 66 67 ZRESULT ZipAdd(HZIP hz,const TCHAR *dstzn, const TCHAR *fn); 68 ZRESULT ZipAdd(HZIP hz,const TCHAR *dstzn, void *src,unsigned int len); 69 ZRESULT ZipAddHandle(HZIP hz,const TCHAR *dstzn, HANDLE h); 70 ZRESULT ZipAddHandle(HZIP hz,const TCHAR *dstzn, HANDLE h, unsigned int len); 71 ZRESULT ZipAddFolder(HZIP hz,const TCHAR *dstzn); 72 // ZipAdd - call this for each file to be added to the zip. 73 // dstzn is the name that the file will be stored as in the zip file. 74 // The file to be added to the zip can come 75 // from a pipe: ZipAddHandle(hz,"file.dat", hpipe_read); 76 // from a file: ZipAddHandle(hz,"file.dat", hfile); 77 // from a filen: ZipAdd(hz,"file.dat", "c:\\docs\\origfile.dat"); 78 // from memory: ZipAdd(hz,"subdir\\file.dat", buf,len); 79 // (folder): ZipAddFolder(hz,"subdir"); 80 // Note: if adding an item from a pipe, and if also creating the zip file itself 81 // to a pipe, then you might wish to pass a non-zero length to the ZipAddHandle 82 // function. This will let the zipfile store the item's size ahead of the 83 // compressed item itself, which in turn makes it easier when unzipping the 84 // zipfile from a pipe. 85 86 ZRESULT ZipGetMemory(HZIP hz, void **buf, unsigned long *len); 87 // ZipGetMemory - If the zip was created in memory, via ZipCreate(0,len), 88 // then this function will return information about that memory block. 89 // buf will receive a pointer to its start, and len its length. 90 // Note: you can't add any more after calling this. 91 92 ZRESULT CloseZip(HZIP hz); 93 // CloseZip - the zip handle must be closed with this function. 94 95 unsigned int FormatZipMessage(ZRESULT code, TCHAR *buf,unsigned int len); 96 // FormatZipMessage - given an error code, formats it as a string. 97 // It returns the length of the error message. If buf/len points 98 // to a real buffer, then it also writes as much as possible into there. 99 100 101 102 // These are the result codes: 103 #define ZR_OK 0x00000000 // nb. the pseudo-code zr-recent is never returned, 104 #define ZR_RECENT 0x00000001 // but can be passed to FormatZipMessage. 105 // The following come from general system stuff (e.g. files not openable) 106 #define ZR_GENMASK 0x0000FF00 107 #define ZR_NODUPH 0x00000100 // couldn't duplicate the handle 108 #define ZR_NOFILE 0x00000200 // couldn't create/open the file 109 #define ZR_NOALLOC 0x00000300 // failed to allocate some resource 110 #define ZR_WRITE 0x00000400 // a general error writing to the file 111 #define ZR_NOTFOUND 0x00000500 // couldn't find that file in the zip 112 #define ZR_MORE 0x00000600 // there's still more data to be unzipped 113 #define ZR_CORRUPT 0x00000700 // the zipfile is corrupt or not a zipfile 114 #define ZR_READ 0x00000800 // a general error reading the file 115 // The following come from mistakes on the part of the caller 116 #define ZR_CALLERMASK 0x00FF0000 117 #define ZR_ARGS 0x00010000 // general mistake with the arguments 118 #define ZR_NOTMMAP 0x00020000 // tried to ZipGetMemory, but that only works on mmap zipfiles, which yours wasn't 119 #define ZR_MEMSIZE 0x00030000 // the memory size is too small 120 #define ZR_FAILED 0x00040000 // the thing was already failed when you called this function 121 #define ZR_ENDED 0x00050000 // the zip creation has already been closed 122 #define ZR_MISSIZE 0x00060000 // the indicated input file size turned out mistaken 123 #define ZR_PARTIALUNZ 0x00070000 // the file had already been partially unzipped 124 #define ZR_ZMODE 0x00080000 // tried to mix creating/opening a zip 125 // The following come from bugs within the zip library itself 126 #define ZR_BUGMASK 0xFF000000 127 #define ZR_NOTINITED 0x01000000 // initialisation didn't work 128 #define ZR_SEEK 0x02000000 // trying to seek in an unseekable file 129 #define ZR_NOCHANGE 0x04000000 // changed its mind on storage, but not allowed 130 #define ZR_FLATE 0x05000000 // an internal error in the de/inflation code 131 132 133 134 135 136 137 // e.g. 138 // 139 // (1) Traditional use, creating a zipfile from existing files 140 // HZIP hz = CreateZip("c:\\simple1.zip",0); 141 // ZipAdd(hz,"znsimple.bmp", "c:\\simple.bmp"); 142 // ZipAdd(hz,"znsimple.txt", "c:\\simple.txt"); 143 // CloseZip(hz); 144 // 145 // (2) Memory use, creating an auto-allocated mem-based zip file from various sources 146 // HZIP hz = CreateZip(0,100000, 0); 147 // // adding a conventional file... 148 // ZipAdd(hz,"src1.txt", "c:\\src1.txt"); 149 // // adding something from memory... 150 // char buf[1000]; for (int i=0; i<1000; i++) buf[i]=(char)(i&0x7F); 151 // ZipAdd(hz,"file.dat", buf,1000); 152 // // adding something from a pipe... 153 // HANDLE hread,hwrite; CreatePipe(&hread,&hwrite,NULL,0); 154 // HANDLE hthread = CreateThread(0,0,ThreadFunc,(void*)hwrite,0,0); 155 // ZipAdd(hz,"unz3.dat", hread,1000); // the '1000' is optional. 156 // WaitForSingleObject(hthread,INFINITE); 157 // CloseHandle(hthread); CloseHandle(hread); 158 // ... meanwhile DWORD WINAPI ThreadFunc(void *dat) 159 // { HANDLE hwrite = (HANDLE)dat; 160 // char buf[1000]={17}; 161 // DWORD writ; WriteFile(hwrite,buf,1000,&writ,NULL); 162 // CloseHandle(hwrite); 163 // return 0; 164 // } 165 // // and now that the zip is created, let's do something with it: 166 // void *zbuf; unsigned long zlen; ZipGetMemory(hz,&zbuf,&zlen); 167 // HANDLE hfz = CreateFile("test2.zip",GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0); 168 // DWORD writ; WriteFile(hfz,zbuf,zlen,&writ,NULL); 169 // CloseHandle(hfz); 170 // CloseZip(hz); 171 // 172 // (3) Handle use, for file handles and pipes 173 // HANDLE hzread,hzwrite; CreatePipe(&hzread,&hzwrite,0,0); 174 // HANDLE hthread = CreateThread(0,0,ZipReceiverThread,(void*)hzread,0,0); 175 // HZIP hz = CreateZipHandle(hzwrite,0); 176 // // ... add to it 177 // CloseZip(hz); 178 // CloseHandle(hzwrite); 179 // WaitForSingleObject(hthread,INFINITE); 180 // CloseHandle(hthread); 181 // ... meanwhile DWORD WINAPI ZipReceiverThread(void *dat) 182 // { HANDLE hread = (HANDLE)dat; 183 // char buf[1000]; 184 // while (true) 185 // { DWORD red; ReadFile(hread,buf,1000,&red,NULL); 186 // // ... and do something with this zip data we're receiving 187 // if (red==0) break; 188 // } 189 // CloseHandle(hread); 190 // return 0; 191 // } 192 193 194 195 // Now we indulge in a little skullduggery so that the code works whether 196 // the user has included just zip or both zip and unzip. 197 // Idea: if header files for both zip and unzip are present, then presumably 198 // the cpp files for zip and unzip are both present, so we will call 199 // one or the other of them based on a dynamic choice. If the header file 200 // for only one is present, then we will bind to that particular one. 201 ZRESULT CloseZipZ(HZIP hz); 202 unsigned int FormatZipMessageZ(ZRESULT code, char *buf,unsigned int len); 203 bool IsZipHandleZ(HZIP hz); 204 #ifdef _unzip_H 205 #undef CloseZip 206 #define CloseZip(hz) (IsZipHandleZ(hz)?CloseZipZ(hz):CloseZipU(hz)) 207 #else 208 #define CloseZip CloseZipZ 209 #define FormatZipMessage FormatZipMessageZ 210 #endif 211 212 213 214 #endif
zip.cpp
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #ifdef ZIP_STD 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <stdarg.h> 5 #include <time.h> 6 #include <sys/types.h> 7 #include <sys/stat.h> 8 #include <memory.h> 9 #include <string.h> 10 #include <ctype.h> 11 12 #include "zip.h" 13 // 14 typedef unsigned short WORD; 15 #define _tcslen strlen 16 #define _tcsicmp stricmp 17 #define _tcsncpy strncpy 18 #define _tcsstr strstr 19 #define INVALID_HANDLE_VALUE 0 20 #ifndef _T 21 #define _T(s) s 22 #endif 23 #ifndef S_IWUSR 24 #define S_IWUSR 0000200 25 #define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR) 26 #define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG) 27 #endif 28 29 // 30 #else 31 #include <windows.h> 32 #include <tchar.h> 33 #include <ctype.h> 34 #include <stdio.h> 35 #include "zip.h" 36 #endif 37 38 39 // THIS FILE is almost entirely based upon code by info-zip. 40 // It has been modified by Lucian Wischik. The modifications 41 // were a complete rewrite of the bit of code that generates the 42 // layout of the zipfile, and support for zipping to/from memory 43 // or handles or pipes or pagefile or diskfiles, encryption, unicode. 44 // The original code may be found at http://www.info-zip.org 45 // The original copyright text follows. 46 // 47 // 48 // 49 // This is version 1999-Oct-05 of the Info-ZIP copyright and license. 50 // The definitive version of this document should be available at 51 // ftp://ftp.cdrom.com/pub/infozip/license.html indefinitely. 52 // 53 // Copyright (c) 1990-1999 Info-ZIP. All rights reserved. 54 // 55 // For the purposes of this copyright and license, "Info-ZIP" is defined as 56 // the following set of individuals: 57 // 58 // Mark Adler, John Bush, Karl Davis, Harald Denker, Jean-Michel Dubois, 59 // Jean-loup Gailly, Hunter Goatley, Ian Gorman, Chris Herborth, Dirk Haase, 60 // Greg Hartwig, Robert Heath, Jonathan Hudson, Paul Kienitz, David Kirschbaum, 61 // Johnny Lee, Onno van der Linden, Igor Mandrichenko, Steve P. Miller, 62 // Sergio Monesi, Keith Owens, George Petrov, Greg Roelofs, Kai Uwe Rommel, 63 // Steve Salisbury, Dave Smith, Christian Spieler, Antoine Verheijen, 64 // Paul von Behren, Rich Wales, Mike White 65 // 66 // This software is provided "as is," without warranty of any kind, express 67 // or implied. In no event shall Info-ZIP or its contributors be held liable 68 // for any direct, indirect, incidental, special or consequential damages 69 // arising out of the use of or inability to use this software. 70 // 71 // Permission is granted to anyone to use this software for any purpose, 72 // including commercial applications, and to alter it and redistribute it 73 // freely, subject to the following restrictions: 74 // 75 // 1. Redistributions of source code must retain the above copyright notice, 76 // definition, disclaimer, and this list of conditions. 77 // 78 // 2. Redistributions in binary form must reproduce the above copyright 79 // notice, definition, disclaimer, and this list of conditions in 80 // documentation and/or other materials provided with the distribution. 81 // 82 // 3. Altered versions--including, but not limited to, ports to new operating 83 // systems, existing ports with new graphical interfaces, and dynamic, 84 // shared, or static library versions--must be plainly marked as such 85 // and must not be misrepresented as being the original source. Such 86 // altered versions also must not be misrepresented as being Info-ZIP 87 // releases--including, but not limited to, labeling of the altered 88 // versions with the names "Info-ZIP" (or any variation thereof, including, 89 // but not limited to, different capitalizations), "Pocket UnZip," "WiZ" 90 // or "MacZip" without the explicit permission of Info-ZIP. Such altered 91 // versions are further prohibited from misrepresentative use of the 92 // Zip-Bugs or Info-ZIP e-mail addresses or of the Info-ZIP URL(s). 93 // 94 // 4. Info-ZIP retains the right to use the names "Info-ZIP," "Zip," "UnZip," 95 // "WiZ," "Pocket UnZip," "Pocket Zip," and "MacZip" for its own source and 96 // binary releases. 97 // 98 99 100 typedef unsigned char uch; // unsigned 8-bit value 101 typedef unsigned short ush; // unsigned 16-bit value 102 typedef unsigned long ulg; // unsigned 32-bit value 103 typedef size_t extent; // file size 104 typedef unsigned Pos; // must be at least 32 bits 105 typedef unsigned IPos; // A Pos is an index in the character window. Pos is used only for parameter passing 106 107 #ifndef EOF 108 #define EOF (-1) 109 #endif 110 111 112 113 114 115 116 // Error return values. The values 0..4 and 12..18 follow the conventions 117 // of PKZIP. The values 4..10 are all assigned to "insufficient memory" 118 // by PKZIP, so the codes 5..10 are used here for other purposes. 119 #define ZE_MISS -1 // used by procname(), zipbare() 120 #define ZE_OK 0 // success 121 #define ZE_EOF 2 // unexpected end of zip file 122 #define ZE_FORM 3 // zip file structure error 123 #define ZE_MEM 4 // out of memory 124 #define ZE_LOGIC 5 // internal logic error 125 #define ZE_BIG 6 // entry too large to split 126 #define ZE_NOTE 7 // invalid comment format 127 #define ZE_TEST 8 // zip test (-T) failed or out of memory 128 #define ZE_ABORT 9 // user interrupt or termination 129 #define ZE_TEMP 10 // error using a temp file 130 #define ZE_READ 11 // read or seek error 131 #define ZE_NONE 12 // nothing to do 132 #define ZE_NAME 13 // missing or empty zip file 133 #define ZE_WRITE 14 // error writing to a file 134 #define ZE_CREAT 15 // couldn't open to write 135 #define ZE_PARMS 16 // bad command line 136 #define ZE_OPEN 18 // could not open a specified file to read 137 #define ZE_MAXERR 18 // the highest error number 138 139 140 // internal file attribute 141 #define UNKNOWN (-1) 142 #define BINARY 0 143 #define ASCII 1 144 145 #define BEST -1 // Use best method (deflation or store) 146 #define STORE 0 // Store method 147 #define DEFLATE 8 // Deflation method 148 149 #define CRCVAL_INITIAL 0L 150 151 // MSDOS file or directory attributes 152 #define MSDOS_HIDDEN_ATTR 0x02 153 #define MSDOS_DIR_ATTR 0x10 154 155 // Lengths of headers after signatures in bytes 156 #define LOCHEAD 26 157 #define CENHEAD 42 158 #define ENDHEAD 18 159 160 // Definitions for extra field handling: 161 #define EB_HEADSIZE 4 /* length of a extra field block header */ 162 #define EB_LEN 2 /* offset of data length field in header */ 163 #define EB_UT_MINLEN 1 /* minimal UT field contains Flags byte */ 164 #define EB_UT_FLAGS 0 /* byte offset of Flags field */ 165 #define EB_UT_TIME1 1 /* byte offset of 1st time value */ 166 #define EB_UT_FL_MTIME (1 << 0) /* mtime present */ 167 #define EB_UT_FL_ATIME (1 << 1) /* atime present */ 168 #define EB_UT_FL_CTIME (1 << 2) /* ctime present */ 169 #define EB_UT_LEN(n) (EB_UT_MINLEN + 4 * (n)) 170 #define EB_L_UT_SIZE (EB_HEADSIZE + EB_UT_LEN(3)) 171 #define EB_C_UT_SIZE (EB_HEADSIZE + EB_UT_LEN(1)) 172 173 174 // Macros for writing machine integers to little-endian format 175 #define PUTSH(a,f) {char _putsh_c=(char)((a)&0xff); wfunc(param,&_putsh_c,1); _putsh_c=(char)((a)>>8); wfunc(param,&_putsh_c,1);} 176 #define PUTLG(a,f) {PUTSH((a) & 0xffff,(f)) PUTSH((a) >> 16,(f))} 177 178 179 // -- Structure of a ZIP file -- 180 // Signatures for zip file information headers 181 #define LOCSIG 0x04034b50L 182 #define CENSIG 0x02014b50L 183 #define ENDSIG 0x06054b50L 184 #define EXTLOCSIG 0x08074b50L 185 186 187 #define MIN_MATCH 3 188 #define MAX_MATCH 258 189 // The minimum and maximum match lengths 190 191 192 #define WSIZE (0x8000) 193 // Maximum window size = 32K. If you are really short of memory, compile 194 // with a smaller WSIZE but this reduces the compression ratio for files 195 // of size > WSIZE. WSIZE must be a power of two in the current implementation. 196 // 197 198 #define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) 199 // Minimum amount of lookahead, except at the end of the input file. 200 // See deflate.c for comments about the MIN_MATCH+1. 201 // 202 203 #define MAX_DIST (WSIZE-MIN_LOOKAHEAD) 204 // In order to simplify the code, particularly on 16 bit machines, match 205 // distances are limited to MAX_DIST instead of WSIZE. 206 // 207 208 209 #define ZIP_HANDLE 1 210 #define ZIP_FILENAME 2 211 #define ZIP_MEMORY 3 212 #define ZIP_FOLDER 4 213 214 215 216 // =========================================================================== 217 // Constants 218 // 219 220 #define MAX_BITS 15 221 // All codes must not exceed MAX_BITS bits 222 223 #define MAX_BL_BITS 7 224 // Bit length codes must not exceed MAX_BL_BITS bits 225 226 #define LENGTH_CODES 29 227 // number of length codes, not counting the special END_BLOCK code 228 229 #define LITERALS 256 230 // number of literal bytes 0..255 231 232 #define END_BLOCK 256 233 // end of block literal code 234 235 #define L_CODES (LITERALS+1+LENGTH_CODES) 236 // number of Literal or Length codes, including the END_BLOCK code 237 238 #define D_CODES 30 239 // number of distance codes 240 241 #define BL_CODES 19 242 // number of codes used to transfer the bit lengths 243 244 245 #define STORED_BLOCK 0 246 #define STATIC_TREES 1 247 #define DYN_TREES 2 248 // The three kinds of block type 249 250 #define LIT_BUFSIZE 0x8000 251 #define DIST_BUFSIZE LIT_BUFSIZE 252 // Sizes of match buffers for literals/lengths and distances. There are 253 // 4 reasons for limiting LIT_BUFSIZE to 64K: 254 // - frequencies can be kept in 16 bit counters 255 // - if compression is not successful for the first block, all input data is 256 // still in the window so we can still emit a stored block even when input 257 // comes from standard input. (This can also be done for all blocks if 258 // LIT_BUFSIZE is not greater than 32K.) 259 // - if compression is not successful for a file smaller than 64K, we can 260 // even emit a stored file instead of a stored block (saving 5 bytes). 261 // - creating new Huffman trees less frequently may not provide fast 262 // adaptation to changes in the input data statistics. (Take for 263 // example a binary file with poorly compressible code followed by 264 // a highly compressible string table.) Smaller buffer sizes give 265 // fast adaptation but have of course the overhead of transmitting trees 266 // more frequently. 267 // - I can't count above 4 268 // The current code is general and allows DIST_BUFSIZE < LIT_BUFSIZE (to save 269 // memory at the expense of compression). Some optimizations would be possible 270 // if we rely on DIST_BUFSIZE == LIT_BUFSIZE. 271 // 272 273 #define REP_3_6 16 274 // repeat previous bit length 3-6 times (2 bits of repeat count) 275 276 #define REPZ_3_10 17 277 // repeat a zero length 3-10 times (3 bits of repeat count) 278 279 #define REPZ_11_138 18 280 // repeat a zero length 11-138 times (7 bits of repeat count) 281 282 #define HEAP_SIZE (2*L_CODES+1) 283 // maximum heap size 284 285 286 // =========================================================================== 287 // Local data used by the "bit string" routines. 288 // 289 290 #define Buf_size (8 * 2*sizeof(char)) 291 // Number of bits used within bi_buf. (bi_buf may be implemented on 292 // more than 16 bits on some systems.) 293 294 // Output a 16 bit value to the bit stream, lower (oldest) byte first 295 #define PUTSHORT(state,w) \ 296 { if (state.bs.out_offset >= state.bs.out_size-1) \ 297 state.flush_outbuf(state.param,state.bs.out_buf, &state.bs.out_offset); \ 298 state.bs.out_buf[state.bs.out_offset++] = (char) ((w) & 0xff); \ 299 state.bs.out_buf[state.bs.out_offset++] = (char) ((ush)(w) >> 8); \ 300 } 301 302 #define PUTBYTE(state,b) \ 303 { if (state.bs.out_offset >= state.bs.out_size) \ 304 state.flush_outbuf(state.param,state.bs.out_buf, &state.bs.out_offset); \ 305 state.bs.out_buf[state.bs.out_offset++] = (char) (b); \ 306 } 307 308 // DEFLATE.CPP HEADER 309 310 #define HASH_BITS 15 311 // For portability to 16 bit machines, do not use values above 15. 312 313 #define HASH_SIZE (unsigned)(1<<HASH_BITS) 314 #define HASH_MASK (HASH_SIZE-1) 315 #define WMASK (WSIZE-1) 316 // HASH_SIZE and WSIZE must be powers of two 317 318 #define NIL 0 319 // Tail of hash chains 320 321 #define FAST 4 322 #define SLOW 2 323 // speed options for the general purpose bit flag 324 325 #define TOO_FAR 4096 326 // Matches of length 3 are discarded if their distance exceeds TOO_FAR 327 328 329 330 #define EQUAL 0 331 // result of memcmp for equal strings 332 333 334 // =========================================================================== 335 // Local data used by the "longest match" routines. 336 337 #define H_SHIFT ((HASH_BITS+MIN_MATCH-1)/MIN_MATCH) 338 // Number of bits by which ins_h and del_h must be shifted at each 339 // input step. It must be such that after MIN_MATCH steps, the oldest 340 // byte no longer takes part in the hash key, that is: 341 // H_SHIFT * MIN_MATCH >= HASH_BITS 342 343 #define max_insert_length max_lazy_match 344 // Insert new strings in the hash table only if the match length 345 // is not greater than this length. This saves time but degrades compression. 346 // max_insert_length is used only for compression levels <= 3. 347 348 349 350 const int extra_lbits[LENGTH_CODES] // extra bits for each length code 351 = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; 352 353 const int extra_dbits[D_CODES] // extra bits for each distance code 354 = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; 355 356 const int extra_blbits[BL_CODES]// extra bits for each bit length code 357 = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; 358 359 const uch bl_order[BL_CODES] = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; 360 // The lengths of the bit length codes are sent in order of decreasing 361 // probability, to avoid transmitting the lengths for unused bit length codes. 362 363 364 typedef struct config { 365 ush good_length; // reduce lazy search above this match length 366 ush max_lazy; // do not perform lazy search above this match length 367 ush nice_length; // quit search above this match length 368 ush max_chain; 369 } config; 370 371 // Values for max_lazy_match, good_match, nice_match and max_chain_length, 372 // depending on the desired pack level (0..9). The values given below have 373 // been tuned to exclude worst case performance for pathological files. 374 // Better values may be found for specific files. 375 // 376 377 const config configuration_table[10] = { 378 // good lazy nice chain 379 {0, 0, 0, 0}, // 0 store only 380 {4, 4, 8, 4}, // 1 maximum speed, no lazy matches 381 {4, 5, 16, 8}, // 2 382 {4, 6, 32, 32}, // 3 383 {4, 4, 16, 16}, // 4 lazy matches */ 384 {8, 16, 32, 32}, // 5 385 {8, 16, 128, 128}, // 6 386 {8, 32, 128, 256}, // 7 387 {32, 128, 258, 1024}, // 8 388 {32, 258, 258, 4096}};// 9 maximum compression */ 389 390 // Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 391 // For deflate_fast() (levels <= 3) good is ignored and lazy has a different meaning. 392 393 394 395 396 397 398 399 // Data structure describing a single value and its code string. 400 typedef struct ct_data { 401 union { 402 ush freq; // frequency count 403 ush code; // bit string 404 } fc; 405 union { 406 ush dad; // father node in Huffman tree 407 ush len; // length of bit string 408 } dl; 409 } ct_data; 410 411 typedef struct tree_desc { 412 ct_data *dyn_tree; // the dynamic tree 413 ct_data *static_tree; // corresponding static tree or NULL 414 const int *extra_bits; // extra bits for each code or NULL 415 int extra_base; // base index for extra_bits 416 int elems; // max number of elements in the tree 417 int max_length; // max bit length for the codes 418 int max_code; // largest code with non zero frequency 419 } tree_desc; 420 421 422 423 424 class TTreeState 425 { public: 426 TTreeState(); 427 428 ct_data dyn_ltree[HEAP_SIZE]; // literal and length tree 429 ct_data dyn_dtree[2*D_CODES+1]; // distance tree 430 ct_data static_ltree[L_CODES+2]; // the static literal tree... 431 // ... Since the bit lengths are imposed, there is no need for the L_CODES 432 // extra codes used during heap construction. However the codes 286 and 287 433 // are needed to build a canonical tree (see ct_init below). 434 ct_data static_dtree[D_CODES]; // the static distance tree... 435 // ... (Actually a trivial tree since all codes use 5 bits.) 436 ct_data bl_tree[2*BL_CODES+1]; // Huffman tree for the bit lengths 437 438 tree_desc l_desc; 439 tree_desc d_desc; 440 tree_desc bl_desc; 441 442 ush bl_count[MAX_BITS+1]; // number of codes at each bit length for an optimal tree 443 444 int heap[2*L_CODES+1]; // heap used to build the Huffman trees 445 int heap_len; // number of elements in the heap 446 int heap_max; // element of largest frequency 447 // The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. 448 // The same heap array is used to build all trees. 449 450 uch depth[2*L_CODES+1]; 451 // Depth of each subtree used as tie breaker for trees of equal frequency 452 453 uch length_code[MAX_MATCH-MIN_MATCH+1]; 454 // length code for each normalized match length (0 == MIN_MATCH) 455 456 uch dist_code[512]; 457 // distance codes. The first 256 values correspond to the distances 458 // 3 .. 258, the last 256 values correspond to the top 8 bits of 459 // the 15 bit distances. 460 461 int base_length[LENGTH_CODES]; 462 // First normalized length for each code (0 = MIN_MATCH) 463 464 int base_dist[D_CODES]; 465 // First normalized distance for each code (0 = distance of 1) 466 467 uch l_buf[LIT_BUFSIZE]; // buffer for literals/lengths 468 ush d_buf[DIST_BUFSIZE]; // buffer for distances 469 470 uch flag_buf[(LIT_BUFSIZE/8)]; 471 // flag_buf is a bit array distinguishing literals from lengths in 472 // l_buf, and thus indicating the presence or absence of a distance. 473 474 unsigned last_lit; // running index in l_buf 475 unsigned last_dist; // running index in d_buf 476 unsigned last_flags; // running index in flag_buf 477 uch flags; // current flags not yet saved in flag_buf 478 uch flag_bit; // current bit used in flags 479 // bits are filled in flags starting at bit 0 (least significant). 480 // Note: these flags are overkill in the current code since we don't 481 // take advantage of DIST_BUFSIZE == LIT_BUFSIZE. 482 483 ulg opt_len; // bit length of current block with optimal trees 484 ulg static_len; // bit length of current block with static trees 485 486 ulg cmpr_bytelen; // total byte length of compressed file 487 ulg cmpr_len_bits; // number of bits past 'cmpr_bytelen' 488 489 ulg input_len; // total byte length of input file 490 // input_len is for debugging only since we can get it by other means. 491 492 ush *file_type; // pointer to UNKNOWN, BINARY or ASCII 493 // int *file_method; // pointer to DEFLATE or STORE 494 }; 495 496 TTreeState::TTreeState() 497 { tree_desc a = {dyn_ltree, static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS, 0}; l_desc = a; 498 tree_desc b = {dyn_dtree, static_dtree, extra_dbits, 0, D_CODES, MAX_BITS, 0}; d_desc = b; 499 tree_desc c = {bl_tree, NULL, extra_blbits, 0, BL_CODES, MAX_BL_BITS, 0}; bl_desc = c; 500 last_lit=0; 501 last_dist=0; 502 last_flags=0; 503 } 504 505 506 507 class TBitState 508 { public: 509 510 int flush_flg; 511 // 512 unsigned bi_buf; 513 // Output buffer. bits are inserted starting at the bottom (least significant 514 // bits). The width of bi_buf must be at least 16 bits. 515 int bi_valid; 516 // Number of valid bits in bi_buf. All bits above the last valid bit 517 // are always zero. 518 char *out_buf; 519 // Current output buffer. 520 unsigned out_offset; 521 // Current offset in output buffer. 522 // On 16 bit machines, the buffer is limited to 64K. 523 unsigned out_size; 524 // Size of current output buffer 525 ulg bits_sent; // bit length of the compressed data only needed for debugging??? 526 }; 527 528 529 530 531 532 533 534 class TDeflateState 535 { public: 536 TDeflateState() {window_size=0;} 537 538 uch window[2L*WSIZE]; 539 // Sliding window. Input bytes are read into the second half of the window, 540 // and move to the first half later to keep a dictionary of at least WSIZE 541 // bytes. With this organization, matches are limited to a distance of 542 // WSIZE-MAX_MATCH bytes, but this ensures that IO is always 543 // performed with a length multiple of the block size. Also, it limits 544 // the window size to 64K, which is quite useful on MSDOS. 545 // To do: limit the window size to WSIZE+CBSZ if SMALL_MEM (the code would 546 // be less efficient since the data would have to be copied WSIZE/CBSZ times) 547 Pos prev[WSIZE]; 548 // Link to older string with same hash index. To limit the size of this 549 // array to 64K, this link is maintained only for the last 32K strings. 550 // An index in this array is thus a window index modulo 32K. 551 Pos head[HASH_SIZE]; 552 // Heads of the hash chains or NIL. If your compiler thinks that 553 // HASH_SIZE is a dynamic value, recompile with -DDYN_ALLOC. 554 555 ulg window_size; 556 // window size, 2*WSIZE except for MMAP or BIG_MEM, where it is the 557 // input file length plus MIN_LOOKAHEAD. 558 559 long block_start; 560 // window position at the beginning of the current output block. Gets 561 // negative when the window is moved backwards. 562 563 int sliding; 564 // Set to false when the input file is already in memory 565 566 unsigned ins_h; // hash index of string to be inserted 567 568 unsigned int prev_length; 569 // Length of the best match at previous step. Matches not greater than this 570 // are discarded. This is used in the lazy match evaluation. 571 572 unsigned strstart; // start of string to insert 573 unsigned match_start; // start of matching string 574 int eofile; // flag set at end of input file 575 unsigned lookahead; // number of valid bytes ahead in window 576 577 unsigned max_chain_length; 578 // To speed up deflation, hash chains are never searched beyond this length. 579 // A higher limit improves compression ratio but degrades the speed. 580 581 unsigned int max_lazy_match; 582 // Attempt to find a better match only when the current match is strictly 583 // smaller than this value. This mechanism is used only for compression 584 // levels >= 4. 585 586 unsigned good_match; 587 // Use a faster search when the previous match is longer than this 588 589 int nice_match; // Stop searching when current match exceeds this 590 }; 591 592 typedef long lutime_t; // define it ourselves since we don't include time.h 593 594 typedef struct iztimes { 595 lutime_t atime,mtime,ctime; 596 } iztimes; // access, modify, create times 597 598 typedef struct zlist { 599 ush vem, ver, flg, how; // See central header in zipfile.c for what vem..off are 600 ulg tim, crc, siz, len; 601 extent nam, ext, cext, com; // offset of ext must be >= LOCHEAD 602 ush dsk, att, lflg; // offset of lflg must be >= LOCHEAD 603 ulg atx, off; 604 char name[MAX_PATH]; // File name in zip file 605 char *extra; // Extra field (set only if ext != 0) 606 char *cextra; // Extra in central (set only if cext != 0) 607 char *comment; // Comment (set only if com != 0) 608 char iname[MAX_PATH]; // Internal file name after cleanup 609 char zname[MAX_PATH]; // External version of internal name 610 int mark; // Marker for files to operate on 611 int trash; // Marker for files to delete 612 int dosflag; // Set to force MSDOS file attributes 613 struct zlist *nxt; // Pointer to next header in list 614 } TZipFileInfo; 615 616 617 struct TState; 618 typedef unsigned (*READFUNC)(TState &state, char *buf,unsigned size); 619 typedef unsigned (*FLUSHFUNC)(void *param, const char *buf, unsigned *size); 620 typedef unsigned (*WRITEFUNC)(void *param, const char *buf, unsigned size); 621 struct TState 622 { void *param; 623 int level; bool seekable; 624 READFUNC readfunc; FLUSHFUNC flush_outbuf; 625 TTreeState ts; TBitState bs; TDeflateState ds; 626 const char *err; 627 }; 628 629 630 631 632 // ---------------------------------------------------------------------- 633 // some windows<->linux portability things 634 #ifdef ZIP_STD 635 void filetime2dosdatetime(const FILETIME ft, WORD *dosdate, WORD *dostime) 636 { struct tm *st=gmtime(&ft); 637 *dosdate = (ush)(((st->tm_year+1900 -1980)&0x7f) << 9); 638 *dosdate |= (ush)((st->tm_mon&0xf) << 5); 639 *dosdate |= (ush)((st->tm_mday&0x1f)); 640 *dostime = (ush)((st->tm_hour&0x1f) << 11); 641 *dostime |= (ush)((st->tm_min&0x3f) << 5); 642 *dostime |= (ush)((st->tm_sec*2)&0x1f); 643 } 644 645 void GetNow(lutime_t *ft, WORD *dosdate, WORD *dostime) 646 { time_t tm = time(0); 647 filetime2dosdatetime(tm,dosdate,dostime); 648 *ft = (lutime_t)tm; 649 } 650 651 DWORD GetFilePosZ(HANDLE hfout) 652 { struct stat st; fstat(fileno(hfout),&st); 653 if ((st.st_mode&S_IFREG)==0) return 0xFFFFFFFF; 654 return ftell(hfout); 655 } 656 657 ZRESULT GetFileInfo(FILE *hf, ulg *attr, long *size, iztimes *times, ulg *timestamp) 658 { // The handle must be a handle to a file 659 // The date and time is returned in a long with the date most significant to allow 660 // unsigned integer comparison of absolute times. The attributes have two 661 // high bytes unix attr, and two low bytes a mapping of that to DOS attr. 662 struct stat bhi; int res=fstat(fileno(hf),&bhi); if (res==-1) return ZR_NOFILE; 663 ulg fa=bhi.st_mode; ulg a=0; 664 // Zip uses the lower word for its interpretation of windows stuff 665 if ((fa&S_IWUSR)==0) a|=0x01; 666 if (S_ISDIR(fa)) a|=0x10; 667 // It uses the upper word for standard unix attr 668 a |= ((fa&0xFFFF)<<16); 669 // 670 if (attr!=NULL) *attr = a; 671 if (size!=NULL) *size = bhi.st_size; 672 if (times!=NULL) 673 { times->atime = (lutime_t)bhi.st_atime; 674 times->mtime = (lutime_t)bhi.st_mtime; 675 times->ctime = (lutime_t)bhi.st_ctime; 676 } 677 if (timestamp!=NULL) 678 { ush dosdate,dostime; 679 filetime2dosdatetime(bhi.st_mtime,&dosdate,&dostime); 680 *timestamp = (ush)dostime | (((ulg)dosdate)<<16); 681 } 682 return ZR_OK; 683 } 684 685 686 // ---------------------------------------------------------------------- 687 #else 688 void filetime2dosdatetime(const FILETIME ft, WORD *dosdate,WORD *dostime) 689 { // date: bits 0-4 are day of month 1-31. Bits 5-8 are month 1..12. Bits 9-15 are year-1980 690 // time: bits 0-4 are seconds/2, bits 5-10 are minute 0..59. Bits 11-15 are hour 0..23 691 SYSTEMTIME st; FileTimeToSystemTime(&ft,&st); 692 *dosdate = (WORD)(((st.wYear-1980)&0x7f) << 9); 693 *dosdate |= (WORD)((st.wMonth&0xf) << 5); 694 *dosdate |= (WORD)((st.wDay&0x1f)); 695 *dostime = (WORD)((st.wHour&0x1f) << 11); 696 *dostime |= (WORD)((st.wMinute&0x3f) << 5); 697 *dostime |= (WORD)((st.wSecond*2)&0x1f); 698 } 699 700 lutime_t filetime2timet(const FILETIME ft) 701 { LONGLONG i = *(LONGLONG*)&ft; 702 return (lutime_t)((i-116444736000000000LL)/10000000LL); 703 } 704 705 void GetNow(lutime_t *pft, WORD *dosdate, WORD *dostime) 706 { SYSTEMTIME st; GetLocalTime(&st); 707 FILETIME ft; SystemTimeToFileTime(&st,&ft); 708 filetime2dosdatetime(ft,dosdate,dostime); 709 *pft = filetime2timet(ft); 710 } 711 712 DWORD GetFilePosZ(HANDLE hfout) 713 { return SetFilePointer(hfout,0,0,FILE_CURRENT); 714 } 715 716 717 ZRESULT GetFileInfo(HANDLE hf, ulg *attr, long *size, iztimes *times, ulg *timestamp) 718 { // The handle must be a handle to a file 719 // The date and time is returned in a long with the date most significant to allow 720 // unsigned integer comparison of absolute times. The attributes have two 721 // high bytes unix attr, and two low bytes a mapping of that to DOS attr. 722 //struct stat s; int res=stat(fn,&s); if (res!=0) return false; 723 // translate windows file attributes into zip ones. 724 BY_HANDLE_FILE_INFORMATION bhi; BOOL res=GetFileInformationByHandle(hf,&bhi); 725 if (!res) return ZR_NOFILE; 726 DWORD fa=bhi.dwFileAttributes; ulg a=0; 727 // Zip uses the lower word for its interpretation of windows stuff 728 if (fa&FILE_ATTRIBUTE_READONLY) a|=0x01; 729 if (fa&FILE_ATTRIBUTE_HIDDEN) a|=0x02; 730 if (fa&FILE_ATTRIBUTE_SYSTEM) a|=0x04; 731 if (fa&FILE_ATTRIBUTE_DIRECTORY)a|=0x10; 732 if (fa&FILE_ATTRIBUTE_ARCHIVE) a|=0x20; 733 // It uses the upper word for standard unix attr, which we manually construct 734 if (fa&FILE_ATTRIBUTE_DIRECTORY)a|=0x40000000; // directory 735 else a|=0x80000000; // normal file 736 a|=0x01000000; // readable 737 if (fa&FILE_ATTRIBUTE_READONLY) {} else a|=0x00800000; // writeable 738 // now just a small heuristic to check if it's an executable: 739 DWORD red, hsize=GetFileSize(hf,NULL); if (hsize>40) 740 { SetFilePointer(hf,0,NULL,FILE_BEGIN); unsigned short magic; ReadFile(hf,&magic,sizeof(magic),&red,NULL); 741 SetFilePointer(hf,36,NULL,FILE_BEGIN); unsigned long hpos; ReadFile(hf,&hpos,sizeof(hpos),&red,NULL); 742 if (magic==0x54AD && hsize>hpos+4+20+28) 743 { SetFilePointer(hf,hpos,NULL,FILE_BEGIN); unsigned long signature; ReadFile(hf,&signature,sizeof(signature),&red,NULL); 744 if (signature==IMAGE_DOS_SIGNATURE || signature==IMAGE_OS2_SIGNATURE 745 || signature==IMAGE_OS2_SIGNATURE_LE || signature==IMAGE_NT_SIGNATURE) 746 { a |= 0x00400000; // executable 747 } 748 } 749 } 750 // 751 if (attr!=NULL) *attr = a; 752 if (size!=NULL) *size = hsize; 753 if (times!=NULL) 754 { // lutime_t is 32bit number of seconds elapsed since 0:0:0GMT, Jan1, 1970. 755 // but FILETIME is 64bit number of 100-nanosecs since Jan1, 1601 756 times->atime = filetime2timet(bhi.ftLastAccessTime); 757 times->mtime = filetime2timet(bhi.ftLastWriteTime); 758 times->ctime = filetime2timet(bhi.ftCreationTime); 759 } 760 if (timestamp!=NULL) 761 { WORD dosdate,dostime; 762 filetime2dosdatetime(bhi.ftLastWriteTime,&dosdate,&dostime); 763 *timestamp = (WORD)dostime | (((DWORD)dosdate)<<16); 764 } 765 return ZR_OK; 766 } 767 #endif 768 // ---------------------------------------------------------------------- 769 770 771 772 773 774 void Assert(TState &state,bool cond, const char *msg) 775 { if (cond) return; 776 state.err=msg; 777 } 778 void Trace(const char *x, ...) {va_list paramList; va_start(paramList, x); paramList; va_end(paramList);} 779 void Tracec(bool ,const char *x, ...) {va_list paramList; va_start(paramList, x); paramList; va_end(paramList);} 780 781 782 783 // =========================================================================== 784 // Local (static) routines in this file. 785 // 786 787 void init_block (TState &); 788 void pqdownheap (TState &,ct_data *tree, int k); 789 void gen_bitlen (TState &,tree_desc *desc); 790 void gen_codes (TState &state,ct_data *tree, int max_code); 791 void build_tree (TState &,tree_desc *desc); 792 void scan_tree (TState &,ct_data *tree, int max_code); 793 void send_tree (TState &state,ct_data *tree, int max_code); 794 int build_bl_tree (TState &); 795 void send_all_trees (TState &state,int lcodes, int dcodes, int blcodes); 796 void compress_block (TState &state,ct_data *ltree, ct_data *dtree); 797 void set_file_type (TState &); 798 void send_bits (TState &state, int value, int length); 799 unsigned bi_reverse (unsigned code, int len); 800 void bi_windup (TState &state); 801 void copy_block (TState &state,char *buf, unsigned len, int header); 802 803 804 #define send_code(state, c, tree) send_bits(state, tree[c].fc.code, tree[c].dl.len) 805 // Send a code of the given tree. c and tree must not have side effects 806 807 // alternatively... 808 //#define send_code(state, c, tree) 809 // { if (state.verbose>1) fprintf(stderr,"\ncd %3d ",(c)); 810 // send_bits(state, tree[c].fc.code, tree[c].dl.len); } 811 812 #define d_code(dist) ((dist) < 256 ? state.ts.dist_code[dist] : state.ts.dist_code[256+((dist)>>7)]) 813 // Mapping from a distance to a distance code. dist is the distance - 1 and 814 // must not have side effects. dist_code[256] and dist_code[257] are never used. 815 816 #define Max(a,b) (a >= b ? a : b) 817 /* the arguments must not have side effects */ 818 819 /* =========================================================================== 820 * Allocate the match buffer, initialize the various tables and save the 821 * location of the internal file attribute (ascii/binary) and method 822 * (DEFLATE/STORE). 823 */ 824 void ct_init(TState &state, ush *attr) 825 { 826 int n; /* iterates over tree elements */ 827 int bits; /* bit counter */ 828 int length; /* length value */ 829 int code; /* code value */ 830 int dist; /* distance index */ 831 832 state.ts.file_type = attr; 833 //state.ts.file_method = method; 834 state.ts.cmpr_bytelen = state.ts.cmpr_len_bits = 0L; 835 state.ts.input_len = 0L; 836 837 if (state.ts.static_dtree[0].dl.len != 0) return; /* ct_init already called */ 838 839 /* Initialize the mapping length (0..255) -> length code (0..28) */ 840 length = 0; 841 for (code = 0; code < LENGTH_CODES-1; code++) { 842 state.ts.base_length[code] = length; 843 for (n = 0; n < (1<<extra_lbits[code]); n++) { 844 state.ts.length_code[length++] = (uch)code; 845 } 846 } 847 Assert(state,length == 256, "ct_init: length != 256"); 848 /* Note that the length 255 (match length 258) can be represented 849 * in two different ways: code 284 + 5 bits or code 285, so we 850 * overwrite length_code[255] to use the best encoding: 851 */ 852 state.ts.length_code[length-1] = (uch)code; 853 854 /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ 855 dist = 0; 856 for (code = 0 ; code < 16; code++) { 857 state.ts.base_dist[code] = dist; 858 for (n = 0; n < (1<<extra_dbits[code]); n++) { 859 state.ts.dist_code[dist++] = (uch)code; 860 } 861 } 862 Assert(state,dist == 256, "ct_init: dist != 256"); 863 dist >>= 7; /* from now on, all distances are divided by 128 */ 864 for ( ; code < D_CODES; code++) { 865 state.ts.base_dist[code] = dist << 7; 866 for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { 867 state.ts.dist_code[256 + dist++] = (uch)code; 868 } 869 } 870 Assert(state,dist == 256, "ct_init: 256+dist != 512"); 871 872 /* Construct the codes of the static literal tree */ 873 for (bits = 0; bits <= MAX_BITS; bits++) state.ts.bl_count[bits] = 0; 874 n = 0; 875 while (n <= 143) state.ts.static_ltree[n++].dl.len = 8, state.ts.bl_count[8]++; 876 while (n <= 255) state.ts.static_ltree[n++].dl.len = 9, state.ts.bl_count[9]++; 877 while (n <= 279) state.ts.static_ltree[n++].dl.len = 7, state.ts.bl_count[7]++; 878 while (n <= 287) state.ts.static_ltree[n++].dl.len = 8, state.ts.bl_count[8]++; 879 /* fc.codes 286 and 287 do not exist, but we must include them in the 880 * tree construction to get a canonical Huffman tree (longest code 881 * all ones) 882 */ 883 gen_codes(state,(ct_data *)state.ts.static_ltree, L_CODES+1); 884 885 /* The static distance tree is trivial: */ 886 for (n = 0; n < D_CODES; n++) { 887 state.ts.static_dtree[n].dl.len = 5; 888 state.ts.static_dtree[n].fc.code = (ush)bi_reverse(n, 5); 889 } 890 891 /* Initialize the first block of the first file: */ 892 init_block(state); 893 } 894 895 /* =========================================================================== 896 * Initialize a new block. 897 */ 898 void init_block(TState &state) 899 { 900 int n; /* iterates over tree elements */ 901 902 /* Initialize the trees. */ 903 for (n = 0; n < L_CODES; n++) state.ts.dyn_ltree[n].fc.freq = 0; 904 for (n = 0; n < D_CODES; n++) state.ts.dyn_dtree[n].fc.freq = 0; 905 for (n = 0; n < BL_CODES; n++) state.ts.bl_tree[n].fc.freq = 0; 906 907 state.ts.dyn_ltree[END_BLOCK].fc.freq = 1; 908 state.ts.opt_len = state.ts.static_len = 0L; 909 state.ts.last_lit = state.ts.last_dist = state.ts.last_flags = 0; 910 state.ts.flags = 0; state.ts.flag_bit = 1; 911 } 912 913 #define SMALLEST 1 914 /* Index within the heap array of least frequent node in the Huffman tree */ 915 916 917 /* =========================================================================== 918 * Remove the smallest element from the heap and recreate the heap with 919 * one less element. Updates heap and heap_len. 920 */ 921 #define pqremove(tree, top) \ 922 {\ 923 top = state.ts.heap[SMALLEST]; \ 924 state.ts.heap[SMALLEST] = state.ts.heap[state.ts.heap_len--]; \ 925 pqdownheap(state,tree, SMALLEST); \ 926 } 927 928 /* =========================================================================== 929 * Compares to subtrees, using the tree depth as tie breaker when 930 * the subtrees have equal frequency. This minimizes the worst case length. 931 */ 932 #define smaller(tree, n, m) \ 933 (tree[n].fc.freq < tree[m].fc.freq || \ 934 (tree[n].fc.freq == tree[m].fc.freq && state.ts.depth[n] <= state.ts.depth[m])) 935 936 /* =========================================================================== 937 * Restore the heap property by moving down the tree starting at node k, 938 * exchanging a node with the smallest of its two sons if necessary, stopping 939 * when the heap property is re-established (each father smaller than its 940 * two sons). 941 */ 942 void pqdownheap(TState &state,ct_data *tree, int k) 943 { 944 int v = state.ts.heap[k]; 945 int j = k << 1; /* left son of k */ 946 int htemp; /* required because of bug in SASC compiler */ 947 948 while (j <= state.ts.heap_len) { 949 /* Set j to the smallest of the two sons: */ 950 if (j < state.ts.heap_len && smaller(tree, state.ts.heap[j+1], state.ts.heap[j])) j++; 951 952 /* Exit if v is smaller than both sons */ 953 htemp = state.ts.heap[j]; 954 if (smaller(tree, v, htemp)) break; 955 956 /* Exchange v with the smallest son */ 957 state.ts.heap[k] = htemp; 958 k = j; 959 960 /* And continue down the tree, setting j to the left son of k */ 961 j <<= 1; 962 } 963 state.ts.heap[k] = v; 964 } 965 966 /* =========================================================================== 967 * Compute the optimal bit lengths for a tree and update the total bit length 968 * for the current block. 969 * IN assertion: the fields freq and dad are set, heap[heap_max] and 970 * above are the tree nodes sorted by increasing frequency. 971 * OUT assertions: the field len is set to the optimal bit length, the 972 * array bl_count contains the frequencies for each bit length. 973 * The length opt_len is updated; static_len is also updated if stree is 974 * not null. 975 */ 976 void gen_bitlen(TState &state,tree_desc *desc) 977 { 978 ct_data *tree = desc->dyn_tree; 979 const int *extra = desc->extra_bits; 980 int base = desc->extra_base; 981 int max_code = desc->max_code; 982 int max_length = desc->max_length; 983 ct_data *stree = desc->static_tree; 984 int h; /* heap index */ 985 int n, m; /* iterate over the tree elements */ 986 int bits; /* bit length */ 987 int xbits; /* extra bits */ 988 ush f; /* frequency */ 989 int overflow = 0; /* number of elements with bit length too large */ 990 991 for (bits = 0; bits <= MAX_BITS; bits++) state.ts.bl_count[bits] = 0; 992 993 /* In a first pass, compute the optimal bit lengths (which may 994 * overflow in the case of the bit length tree). 995 */ 996 tree[state.ts.heap[state.ts.heap_max]].dl.len = 0; /* root of the heap */ 997 998 for (h = state.ts.heap_max+1; h < HEAP_SIZE; h++) { 999 n = state.ts.heap[h]; 1000 bits = tree[tree[n].dl.dad].dl.len + 1; 1001 if (bits > max_length) bits = max_length, overflow++; 1002 tree[n].dl.len = (ush)bits; 1003 /* We overwrite tree[n].dl.dad which is no longer needed */ 1004 1005 if (n > max_code) continue; /* not a leaf node */ 1006 1007 state.ts.bl_count[bits]++; 1008 xbits = 0; 1009 if (n >= base) xbits = extra[n-base]; 1010 f = tree[n].fc.freq; 1011 state.ts.opt_len += (ulg)f * (bits + xbits); 1012 if (stree) state.ts.static_len += (ulg)f * (stree[n].dl.len + xbits); 1013 } 1014 if (overflow == 0) return; 1015 1016 Trace("\nbit length overflow\n"); 1017 /* This happens for example on obj2 and pic of the Calgary corpus */ 1018 1019 /* Find the first bit length which could increase: */ 1020 do { 1021 bits = max_length-1; 1022 while (state.ts.bl_count[bits] == 0) bits--; 1023 state.ts.bl_count[bits]--; /* move one leaf down the tree */ 1024 state.ts.bl_count[bits+1] += (ush)2; /* move one overflow item as its brother */ 1025 state.ts.bl_count[max_length]--; 1026 /* The brother of the overflow item also moves one step up, 1027 * but this does not affect bl_count[max_length] 1028 */ 1029 overflow -= 2; 1030 } while (overflow > 0); 1031 1032 /* Now recompute all bit lengths, scanning in increasing frequency. 1033 * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all 1034 * lengths instead of fixing only the wrong ones. This idea is taken 1035 * from 'ar' written by Haruhiko Okumura.) 1036 */ 1037 for (bits = max_length; bits != 0; bits--) { 1038 n = state.ts.bl_count[bits]; 1039 while (n != 0) { 1040 m = state.ts.heap[--h]; 1041 if (m > max_code) continue; 1042 if (tree[m].dl.len != (ush)bits) { 1043 Trace("code %d bits %d->%d\n", m, tree[m].dl.len, bits); 1044 state.ts.opt_len += ((long)bits-(long)tree[m].dl.len)*(long)tree[m].fc.freq; 1045 tree[m].dl.len = (ush)bits; 1046 } 1047 n--; 1048 } 1049 } 1050 } 1051 1052 /* =========================================================================== 1053 * Generate the codes for a given tree and bit counts (which need not be 1054 * optimal). 1055 * IN assertion: the array bl_count contains the bit length statistics for 1056 * the given tree and the field len is set for all tree elements. 1057 * OUT assertion: the field code is set for all tree elements of non 1058 * zero code length. 1059 */ 1060 void gen_codes (TState &state, ct_data *tree, int max_code) 1061 { 1062 ush next_code[MAX_BITS+1]; /* next code value for each bit length */ 1063 ush code = 0; /* running code value */ 1064 int bits; /* bit index */ 1065 int n; /* code index */ 1066 1067 /* The distribution counts are first used to generate the code values 1068 * without bit reversal. 1069 */ 1070 for (bits = 1; bits <= MAX_BITS; bits++) { 1071 next_code[bits] = code = (ush)((code + state.ts.bl_count[bits-1]) << 1); 1072 } 1073 /* Check that the bit counts in bl_count are consistent. The last code 1074 * must be all ones. 1075 */ 1076 Assert(state,code + state.ts.bl_count[MAX_BITS]-1 == (1<< ((ush) MAX_BITS)) - 1, 1077 "inconsistent bit counts"); 1078 Trace("\ngen_codes: max_code %d ", max_code); 1079 1080 for (n = 0; n <= max_code; n++) { 1081 int len = tree[n].dl.len; 1082 if (len == 0) continue; 1083 /* Now reverse the bits */ 1084 tree[n].fc.code = (ush)bi_reverse(next_code[len]++, len); 1085 1086 //Tracec(tree != state.ts.static_ltree, "\nn %3d %c l %2d c %4x (%x) ", n, (isgraph(n) ? n : ' '), len, tree[n].fc.code, next_code[len]-1); 1087 } 1088 } 1089 1090 /* =========================================================================== 1091 * Construct one Huffman tree and assigns the code bit strings and lengths. 1092 * Update the total bit length for the current block. 1093 * IN assertion: the field freq is set for all tree elements. 1094 * OUT assertions: the fields len and code are set to the optimal bit length 1095 * and corresponding code. The length opt_len is updated; static_len is 1096 * also updated if stree is not null. The field max_code is set. 1097 */ 1098 void build_tree(TState &state,tree_desc *desc) 1099 { 1100 ct_data *tree = desc->dyn_tree; 1101 ct_data *stree = desc->static_tree; 1102 int elems = desc->elems; 1103 int n, m; /* iterate over heap elements */ 1104 int max_code = -1; /* largest code with non zero frequency */ 1105 int node = elems; /* next internal node of the tree */ 1106 1107 /* Construct the initial heap, with least frequent element in 1108 * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. 1109 * heap[0] is not used. 1110 */ 1111 state.ts.heap_len = 0, state.ts.heap_max = HEAP_SIZE; 1112 1113 for (n = 0; n < elems; n++) { 1114 if (tree[n].fc.freq != 0) { 1115 state.ts.heap[++state.ts.heap_len] = max_code = n; 1116 state.ts.depth[n] = 0; 1117 } else { 1118 tree[n].dl.len = 0; 1119 } 1120 } 1121 1122 /* The pkzip format requires that at least one distance code exists, 1123 * and that at least one bit should be sent even if there is only one 1124 * possible code. So to avoid special checks later on we force at least 1125 * two codes of non zero frequency. 1126 */ 1127 while (state.ts.heap_len < 2) { 1128 int newcp = state.ts.heap[++state.ts.heap_len] = (max_code < 2 ? ++max_code : 0); 1129 tree[newcp].fc.freq = 1; 1130 state.ts.depth[newcp] = 0; 1131 state.ts.opt_len--; if (stree) state.ts.static_len -= stree[newcp].dl.len; 1132 /* new is 0 or 1 so it does not have extra bits */ 1133 } 1134 desc->max_code = max_code; 1135 1136 /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, 1137 * establish sub-heaps of increasing lengths: 1138 */ 1139 for (n = state.ts.heap_len/2; n >= 1; n--) pqdownheap(state,tree, n); 1140 1141 /* Construct the Huffman tree by repeatedly combining the least two 1142 * frequent nodes. 1143 */ 1144 do { 1145 pqremove(tree, n); /* n = node of least frequency */ 1146 m = state.ts.heap[SMALLEST]; /* m = node of next least frequency */ 1147 1148 state.ts.heap[--state.ts.heap_max] = n; /* keep the nodes sorted by frequency */ 1149 state.ts.heap[--state.ts.heap_max] = m; 1150 1151 /* Create a new node father of n and m */ 1152 tree[node].fc.freq = (ush)(tree[n].fc.freq + tree[m].fc.freq); 1153 state.ts.depth[node] = (uch) (Max(state.ts.depth[n], state.ts.depth[m]) + 1); 1154 tree[n].dl.dad = tree[m].dl.dad = (ush)node; 1155 /* and insert the new node in the heap */ 1156 state.ts.heap[SMALLEST] = node++; 1157 pqdownheap(state,tree, SMALLEST); 1158 1159 } while (state.ts.heap_len >= 2); 1160 1161 state.ts.heap[--state.ts.heap_max] = state.ts.heap[SMALLEST]; 1162 1163 /* At this point, the fields freq and dad are set. We can now 1164 * generate the bit lengths. 1165 */ 1166 gen_bitlen(state,(tree_desc *)desc); 1167 1168 /* The field len is now set, we can generate the bit codes */ 1169 gen_codes (state,(ct_data *)tree, max_code); 1170 } 1171 1172 /* =========================================================================== 1173 * Scan a literal or distance tree to determine the frequencies of the codes 1174 * in the bit length tree. Updates opt_len to take into account the repeat 1175 * counts. (The contribution of the bit length codes will be added later 1176 * during the construction of bl_tree.) 1177 */ 1178 void scan_tree (TState &state,ct_data *tree, int max_code) 1179 { 1180 int n; /* iterates over all tree elements */ 1181 int prevlen = -1; /* last emitted length */ 1182 int curlen; /* length of current code */ 1183 int nextlen = tree[0].dl.len; /* length of next code */ 1184 int count = 0; /* repeat count of the current code */ 1185 int max_count = 7; /* max repeat count */ 1186 int min_count = 4; /* min repeat count */ 1187 1188 if (nextlen == 0) max_count = 138, min_count = 3; 1189 tree[max_code+1].dl.len = (ush)-1; /* guard */ 1190 1191 for (n = 0; n <= max_code; n++) { 1192 curlen = nextlen; nextlen = tree[n+1].dl.len; 1193 if (++count < max_count && curlen == nextlen) { 1194 continue; 1195 } else if (count < min_count) { 1196 state.ts.bl_tree[curlen].fc.freq = (ush)(state.ts.bl_tree[curlen].fc.freq + count); 1197 } else if (curlen != 0) { 1198 if (curlen != prevlen) state.ts.bl_tree[curlen].fc.freq++; 1199 state.ts.bl_tree[REP_3_6].fc.freq++; 1200 } else if (count <= 10) { 1201 state.ts.bl_tree[REPZ_3_10].fc.freq++; 1202 } else { 1203 state.ts.bl_tree[REPZ_11_138].fc.freq++; 1204 } 1205 count = 0; prevlen = curlen; 1206 if (nextlen == 0) { 1207 max_count = 138, min_count = 3; 1208 } else if (curlen == nextlen) { 1209 max_count = 6, min_count = 3; 1210 } else { 1211 max_count = 7, min_count = 4; 1212 } 1213 } 1214 } 1215 1216 /* =========================================================================== 1217 * Send a literal or distance tree in compressed form, using the codes in 1218 * bl_tree. 1219 */ 1220 void send_tree (TState &state, ct_data *tree, int max_code) 1221 { 1222 int n; /* iterates over all tree elements */ 1223 int prevlen = -1; /* last emitted length */ 1224 int curlen; /* length of current code */ 1225 int nextlen = tree[0].dl.len; /* length of next code */ 1226 int count = 0; /* repeat count of the current code */ 1227 int max_count = 7; /* max repeat count */ 1228 int min_count = 4; /* min repeat count */ 1229 1230 /* tree[max_code+1].dl.len = -1; */ /* guard already set */ 1231 if (nextlen == 0) max_count = 138, min_count = 3; 1232 1233 for (n = 0; n <= max_code; n++) { 1234 curlen = nextlen; nextlen = tree[n+1].dl.len; 1235 if (++count < max_count && curlen == nextlen) { 1236 continue; 1237 } else if (count < min_count) { 1238 do { send_code(state, curlen, state.ts.bl_tree); } while (--count != 0); 1239 1240 } else if (curlen != 0) { 1241 if (curlen != prevlen) { 1242 send_code(state, curlen, state.ts.bl_tree); count--; 1243 } 1244 Assert(state,count >= 3 && count <= 6, " 3_6?"); 1245 send_code(state,REP_3_6, state.ts.bl_tree); send_bits(state,count-3, 2); 1246 1247 } else if (count <= 10) { 1248 send_code(state,REPZ_3_10, state.ts.bl_tree); send_bits(state,count-3, 3); 1249 1250 } else { 1251 send_code(state,REPZ_11_138, state.ts.bl_tree); send_bits(state,count-11, 7); 1252 } 1253 count = 0; prevlen = curlen; 1254 if (nextlen == 0) { 1255 max_count = 138, min_count = 3; 1256 } else if (curlen == nextlen) { 1257 max_count = 6, min_count = 3; 1258 } else { 1259 max_count = 7, min_count = 4; 1260 } 1261 } 1262 } 1263 1264 /* =========================================================================== 1265 * Construct the Huffman tree for the bit lengths and return the index in 1266 * bl_order of the last bit length code to send. 1267 */ 1268 int build_bl_tree(TState &state) 1269 { 1270 int max_blindex; /* index of last bit length code of non zero freq */ 1271 1272 /* Determine the bit length frequencies for literal and distance trees */ 1273 scan_tree(state,(ct_data *)state.ts.dyn_ltree, state.ts.l_desc.max_code); 1274 scan_tree(state,(ct_data *)state.ts.dyn_dtree, state.ts.d_desc.max_code); 1275 1276 /* Build the bit length tree: */ 1277 build_tree(state,(tree_desc *)(&state.ts.bl_desc)); 1278 /* opt_len now includes the length of the tree representations, except 1279 * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. 1280 */ 1281 1282 /* Determine the number of bit length codes to send. The pkzip format 1283 * requires that at least 4 bit length codes be sent. (appnote.txt says 1284 * 3 but the actual value used is 4.) 1285 */ 1286 for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { 1287 if (state.ts.bl_tree[bl_order[max_blindex]].dl.len != 0) break; 1288 } 1289 /* Update opt_len to include the bit length tree and counts */ 1290 state.ts.opt_len += 3*(max_blindex+1) + 5+5+4; 1291 Trace("\ndyn trees: dyn %ld, stat %ld", state.ts.opt_len, state.ts.static_len); 1292 1293 return max_blindex; 1294 } 1295 1296 /* =========================================================================== 1297 * Send the header for a block using dynamic Huffman trees: the counts, the 1298 * lengths of the bit length codes, the literal tree and the distance tree. 1299 * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. 1300 */ 1301 void send_all_trees(TState &state,int lcodes, int dcodes, int blcodes) 1302 { 1303 int rank; /* index in bl_order */ 1304 1305 Assert(state,lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); 1306 Assert(state,lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, 1307 "too many codes"); 1308 Trace("\nbl counts: "); 1309 send_bits(state,lcodes-257, 5); 1310 /* not +255 as stated in appnote.txt 1.93a or -256 in 2.04c */ 1311 send_bits(state,dcodes-1, 5); 1312 send_bits(state,blcodes-4, 4); /* not -3 as stated in appnote.txt */ 1313 for (rank = 0; rank < blcodes; rank++) { 1314 Trace("\nbl code %2d ", bl_order[rank]); 1315 send_bits(state,state.ts.bl_tree[bl_order[rank]].dl.len, 3); 1316 } 1317 Trace("\nbl tree: sent %ld", state.bs.bits_sent); 1318 1319 send_tree(state,(ct_data *)state.ts.dyn_ltree, lcodes-1); /* send the literal tree */ 1320 Trace("\nlit tree: sent %ld", state.bs.bits_sent); 1321 1322 send_tree(state,(ct_data *)state.ts.dyn_dtree, dcodes-1); /* send the distance tree */ 1323 Trace("\ndist tree: sent %ld", state.bs.bits_sent); 1324 } 1325 1326 /* =========================================================================== 1327 * Determine the best encoding for the current block: dynamic trees, static 1328 * trees or store, and output the encoded block to the zip file. This function 1329 * returns the total compressed length (in bytes) for the file so far. 1330 */ 1331 ulg flush_block(TState &state,char *buf, ulg stored_len, int eof) 1332 { 1333 ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ 1334 int max_blindex; /* index of last bit length code of non zero freq */ 1335 1336 state.ts.flag_buf[state.ts.last_flags] = state.ts.flags; /* Save the flags for the last 8 items */ 1337 1338 /* Check if the file is ascii or binary */ 1339 if (*state.ts.file_type == (ush)UNKNOWN) set_file_type(state); 1340 1341 /* Construct the literal and distance trees */ 1342 build_tree(state,(tree_desc *)(&state.ts.l_desc)); 1343 Trace("\nlit data: dyn %ld, stat %ld", state.ts.opt_len, state.ts.static_len); 1344 1345 build_tree(state,(tree_desc *)(&state.ts.d_desc)); 1346 Trace("\ndist data: dyn %ld, stat %ld", state.ts.opt_len, state.ts.static_len); 1347 /* At this point, opt_len and static_len are the total bit lengths of 1348 * the compressed block data, excluding the tree representations. 1349 */ 1350 1351 /* Build the bit length tree for the above two trees, and get the index 1352 * in bl_order of the last bit length code to send. 1353 */ 1354 max_blindex = build_bl_tree(state); 1355 1356 /* Determine the best encoding. Compute first the block length in bytes */ 1357 opt_lenb = (state.ts.opt_len+3+7)>>3; 1358 static_lenb = (state.ts.static_len+3+7)>>3; 1359 state.ts.input_len += stored_len; /* for debugging only */ 1360 1361 Trace("\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u dist %u ", 1362 opt_lenb, state.ts.opt_len, static_lenb, state.ts.static_len, stored_len, 1363 state.ts.last_lit, state.ts.last_dist); 1364 1365 if (static_lenb <= opt_lenb) opt_lenb = static_lenb; 1366 1367 // Originally, zip allowed the file to be transformed from a compressed 1368 // into a stored file in the case where compression failed, there 1369 // was only one block, and it was allowed to change. I've removed this 1370 // possibility since the code's cleaner if no changes are allowed. 1371 //if (stored_len <= opt_lenb && eof && state.ts.cmpr_bytelen == 0L 1372 // && state.ts.cmpr_len_bits == 0L && state.seekable) 1373 //{ // && state.ts.file_method != NULL 1374 // // Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: 1375 // Assert(state,buf!=NULL,"block vanished"); 1376 // copy_block(state,buf, (unsigned)stored_len, 0); // without header 1377 // state.ts.cmpr_bytelen = stored_len; 1378 // Assert(state,false,"unimplemented *state.ts.file_method = STORE;"); 1379 // //*state.ts.file_method = STORE; 1380 //} 1381 //else 1382 if (stored_len+4 <= opt_lenb && buf != (char*)NULL) { 1383 /* 4: two words for the lengths */ 1384 /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. 1385 * Otherwise we can't have processed more than WSIZE input bytes since 1386 * the last block flush, because compression would have been 1387 * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to 1388 * transform a block into a stored block. 1389 */ 1390 send_bits(state,(STORED_BLOCK<<1)+eof, 3); /* send block type */ 1391 state.ts.cmpr_bytelen += ((state.ts.cmpr_len_bits + 3 + 7) >> 3) + stored_len + 4; 1392 state.ts.cmpr_len_bits = 0L; 1393 1394 copy_block(state,buf, (unsigned)stored_len, 1); /* with header */ 1395 } 1396 else if (static_lenb == opt_lenb) { 1397 send_bits(state,(STATIC_TREES<<1)+eof, 3); 1398 compress_block(state,(ct_data *)state.ts.static_ltree, (ct_data *)state.ts.static_dtree); 1399 state.ts.cmpr_len_bits += 3 + state.ts.static_len; 1400 state.ts.cmpr_bytelen += state.ts.cmpr_len_bits >> 3; 1401 state.ts.cmpr_len_bits &= 7L; 1402 } 1403 else { 1404 send_bits(state,(DYN_TREES<<1)+eof, 3); 1405 send_all_trees(state,state.ts.l_desc.max_code+1, state.ts.d_desc.max_code+1, max_blindex+1); 1406 compress_block(state,(ct_data *)state.ts.dyn_ltree, (ct_data *)state.ts.dyn_dtree); 1407 state.ts.cmpr_len_bits += 3 + state.ts.opt_len; 1408 state.ts.cmpr_bytelen += state.ts.cmpr_len_bits >> 3; 1409 state.ts.cmpr_len_bits &= 7L; 1410 } 1411 Assert(state,((state.ts.cmpr_bytelen << 3) + state.ts.cmpr_len_bits) == state.bs.bits_sent, "bad compressed size"); 1412 init_block(state); 1413 1414 if (eof) { 1415 // Assert(state,input_len == isize, "bad input size"); 1416 bi_windup(state); 1417 state.ts.cmpr_len_bits += 7; /* align on byte boundary */ 1418 } 1419 Trace("\n"); 1420 1421 return state.ts.cmpr_bytelen + (state.ts.cmpr_len_bits >> 3); 1422 } 1423 1424 /* =========================================================================== 1425 * Save the match info and tally the frequency counts. Return true if 1426 * the current block must be flushed. 1427 */ 1428 int ct_tally (TState &state,int dist, int lc) 1429 { 1430 state.ts.l_buf[state.ts.last_lit++] = (uch)lc; 1431 if (dist == 0) { 1432 /* lc is the unmatched char */ 1433 state.ts.dyn_ltree[lc].fc.freq++; 1434 } else { 1435 /* Here, lc is the match length - MIN_MATCH */ 1436 dist--; /* dist = match distance - 1 */ 1437 Assert(state,(ush)dist < (ush)MAX_DIST && 1438 (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && 1439 (ush)d_code(dist) < (ush)D_CODES, "ct_tally: bad match"); 1440 1441 state.ts.dyn_ltree[state.ts.length_code[lc]+LITERALS+1].fc.freq++; 1442 state.ts.dyn_dtree[d_code(dist)].fc.freq++; 1443 1444 state.ts.d_buf[state.ts.last_dist++] = (ush)dist; 1445 state.ts.flags |= state.ts.flag_bit; 1446 } 1447 state.ts.flag_bit <<= 1; 1448 1449 /* Output the flags if they fill a byte: */ 1450 if ((state.ts.last_lit & 7) == 0) { 1451 state.ts.flag_buf[state.ts.last_flags++] = state.ts.flags; 1452 state.ts.flags = 0, state.ts.flag_bit = 1; 1453 } 1454 /* Try to guess if it is profitable to stop the current block here */ 1455 if (state.level > 2 && (state.ts.last_lit & 0xfff) == 0) { 1456 /* Compute an upper bound for the compressed length */ 1457 ulg out_length = (ulg)state.ts.last_lit*8L; 1458 ulg in_length = (ulg)state.ds.strstart-state.ds.block_start; 1459 int dcode; 1460 for (dcode = 0; dcode < D_CODES; dcode++) { 1461 out_length += (ulg)state.ts.dyn_dtree[dcode].fc.freq*(5L+extra_dbits[dcode]); 1462 } 1463 out_length >>= 3; 1464 Trace("\nlast_lit %u, last_dist %u, in %ld, out ~%ld(%ld%%) ", 1465 state.ts.last_lit, state.ts.last_dist, in_length, out_length, 1466 100L - out_length*100L/in_length); 1467 if (state.ts.last_dist < state.ts.last_lit/2 && out_length < in_length/2) return 1; 1468 } 1469 return (state.ts.last_lit == LIT_BUFSIZE-1 || state.ts.last_dist == DIST_BUFSIZE); 1470 /* We avoid equality with LIT_BUFSIZE because of wraparound at 64K 1471 * on 16 bit machines and because stored blocks are restricted to 1472 * 64K-1 bytes. 1473 */ 1474 } 1475 1476 /* =========================================================================== 1477 * Send the block data compressed using the given Huffman trees 1478 */ 1479 void compress_block(TState &state,ct_data *ltree, ct_data *dtree) 1480 { 1481 unsigned dist; /* distance of matched string */ 1482 int lc; /* match length or unmatched char (if dist == 0) */ 1483 unsigned lx = 0; /* running index in l_buf */ 1484 unsigned dx = 0; /* running index in d_buf */ 1485 unsigned fx = 0; /* running index in flag_buf */ 1486 uch flag = 0; /* current flags */ 1487 unsigned code; /* the code to send */ 1488 int extra; /* number of extra bits to send */ 1489 1490 if (state.ts.last_lit != 0) do { 1491 if ((lx & 7) == 0) flag = state.ts.flag_buf[fx++]; 1492 lc = state.ts.l_buf[lx++]; 1493 if ((flag & 1) == 0) { 1494 send_code(state,lc, ltree); /* send a literal byte */ 1495 } else { 1496 /* Here, lc is the match length - MIN_MATCH */ 1497 code = state.ts.length_code[lc]; 1498 send_code(state,code+LITERALS+1, ltree); /* send the length code */ 1499 extra = extra_lbits[code]; 1500 if (extra != 0) { 1501 lc -= state.ts.base_length[code]; 1502 send_bits(state,lc, extra); /* send the extra length bits */ 1503 } 1504 dist = state.ts.d_buf[dx++]; 1505 /* Here, dist is the match distance - 1 */ 1506 code = d_code(dist); 1507 Assert(state,code < D_CODES, "bad d_code"); 1508 1509 send_code(state,code, dtree); /* send the distance code */ 1510 extra = extra_dbits[code]; 1511 if (extra != 0) { 1512 dist -= state.ts.base_dist[code]; 1513 send_bits(state,dist, extra); /* send the extra distance bits */ 1514 } 1515 } /* literal or match pair ? */ 1516 flag >>= 1; 1517 } while (lx < state.ts.last_lit); 1518 1519 send_code(state,END_BLOCK, ltree); 1520 } 1521 1522 /* =========================================================================== 1523 * Set the file type to ASCII or BINARY, using a crude approximation: 1524 * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. 1525 * IN assertion: the fields freq of dyn_ltree are set and the total of all 1526 * frequencies does not exceed 64K (to fit in an int on 16 bit machines). 1527 */ 1528 void set_file_type(TState &state) 1529 { 1530 int n = 0; 1531 unsigned ascii_freq = 0; 1532 unsigned bin_freq = 0; 1533 while (n < 7) bin_freq += state.ts.dyn_ltree[n++].fc.freq; 1534 while (n < 128) ascii_freq += state.ts.dyn_ltree[n++].fc.freq; 1535 while (n < LITERALS) bin_freq += state.ts.dyn_ltree[n++].fc.freq; 1536 *state.ts.file_type = (ush)(bin_freq > (ascii_freq >> 2) ? BINARY : ASCII); 1537 } 1538 1539 1540 /* =========================================================================== 1541 * Initialize the bit string routines. 1542 */ 1543 void bi_init (TState &state,char *tgt_buf, unsigned tgt_size, int flsh_allowed) 1544 { 1545 state.bs.out_buf = tgt_buf; 1546 state.bs.out_size = tgt_size; 1547 state.bs.out_offset = 0; 1548 state.bs.flush_flg = flsh_allowed; 1549 1550 state.bs.bi_buf = 0; 1551 state.bs.bi_valid = 0; 1552 state.bs.bits_sent = 0L; 1553 } 1554 1555 /* =========================================================================== 1556 * Send a value on a given number of bits. 1557 * IN assertion: length <= 16 and value fits in length bits. 1558 */ 1559 void send_bits(TState &state,int value, int length) 1560 { 1561 Assert(state,length > 0 && length <= 15, "invalid length"); 1562 state.bs.bits_sent += (ulg)length; 1563 /* If not enough room in bi_buf, use (bi_valid) bits from bi_buf and 1564 * (Buf_size - bi_valid) bits from value to flush the filled bi_buf, 1565 * then fill in the rest of (value), leaving (length - (Buf_size-bi_valid)) 1566 * unused bits in bi_buf. 1567 */ 1568 state.bs.bi_buf |= (value << state.bs.bi_valid); 1569 state.bs.bi_valid += length; 1570 if (state.bs.bi_valid > (int)Buf_size) { 1571 PUTSHORT(state,state.bs.bi_buf); 1572 state.bs.bi_valid -= Buf_size; 1573 state.bs.bi_buf = (unsigned)value >> (length - state.bs.bi_valid); 1574 } 1575 } 1576 1577 /* =========================================================================== 1578 * Reverse the first len bits of a code, using straightforward code (a faster 1579 * method would use a table) 1580 * IN assertion: 1 <= len <= 15 1581 */ 1582 unsigned bi_reverse(unsigned code, int len) 1583 { 1584 register unsigned res = 0; 1585 do { 1586 res |= code & 1; 1587 code >>= 1, res <<= 1; 1588 } while (--len > 0); 1589 return res >> 1; 1590 } 1591 1592 /* =========================================================================== 1593 * Write out any remaining bits in an incomplete byte. 1594 */ 1595 void bi_windup(TState &state) 1596 { 1597 if (state.bs.bi_valid > 8) { 1598 PUTSHORT(state,state.bs.bi_buf); 1599 } else if (state.bs.bi_valid > 0) { 1600 PUTBYTE(state,state.bs.bi_buf); 1601 } 1602 if (state.bs.flush_flg) { 1603 state.flush_outbuf(state.param,state.bs.out_buf, &state.bs.out_offset); 1604 } 1605 state.bs.bi_buf = 0; 1606 state.bs.bi_valid = 0; 1607 state.bs.bits_sent = (state.bs.bits_sent+7) & ~7; 1608 } 1609 1610 /* =========================================================================== 1611 * Copy a stored block to the zip file, storing first the length and its 1612 * one's complement if requested. 1613 */ 1614 void copy_block(TState &state, char *block, unsigned len, int header) 1615 { 1616 bi_windup(state); /* align on byte boundary */ 1617 1618 if (header) { 1619 PUTSHORT(state,(ush)len); 1620 PUTSHORT(state,(ush)~len); 1621 state.bs.bits_sent += 2*16; 1622 } 1623 if (state.bs.flush_flg) { 1624 state.flush_outbuf(state.param,state.bs.out_buf, &state.bs.out_offset); 1625 state.bs.out_offset = len; 1626 state.flush_outbuf(state.param,block, &state.bs.out_offset); 1627 } else if (state.bs.out_offset + len > state.bs.out_size) { 1628 Assert(state,false,"output buffer too small for in-memory compression"); 1629 } else { 1630 memcpy(state.bs.out_buf + state.bs.out_offset, block, len); 1631 state.bs.out_offset += len; 1632 } 1633 state.bs.bits_sent += (ulg)len<<3; 1634 } 1635 1636 1637 1638 1639 1640 1641 1642 1643 /* =========================================================================== 1644 * Prototypes for functions. 1645 */ 1646 1647 void fill_window (TState &state); 1648 ulg deflate_fast (TState &state); 1649 1650 int longest_match (TState &state,IPos cur_match); 1651 1652 1653 /* =========================================================================== 1654 * Update a hash value with the given input byte 1655 * IN assertion: all calls to to UPDATE_HASH are made with consecutive 1656 * input characters, so that a running hash key can be computed from the 1657 * previous key instead of complete recalculation each time. 1658 */ 1659 #define UPDATE_HASH(h,c) (h = (((h)<<H_SHIFT) ^ (c)) & HASH_MASK) 1660 1661 /* =========================================================================== 1662 * Insert string s in the dictionary and set match_head to the previous head 1663 * of the hash chain (the most recent string with same hash key). Return 1664 * the previous length of the hash chain. 1665 * IN assertion: all calls to to INSERT_STRING are made with consecutive 1666 * input characters and the first MIN_MATCH bytes of s are valid 1667 * (except for the last MIN_MATCH-1 bytes of the input file). 1668 */ 1669 #define INSERT_STRING(s, match_head) \ 1670 (UPDATE_HASH(state.ds.ins_h, state.ds.window[(s) + (MIN_MATCH-1)]), \ 1671 state.ds.prev[(s) & WMASK] = match_head = state.ds.head[state.ds.ins_h], \ 1672 state.ds.head[state.ds.ins_h] = (s)) 1673 1674 /* =========================================================================== 1675 * Initialize the "longest match" routines for a new file 1676 * 1677 * IN assertion: window_size is > 0 if the input file is already read or 1678 * mmap'ed in the window[] array, 0 otherwise. In the first case, 1679 * window_size is sufficient to contain the whole input file plus 1680 * MIN_LOOKAHEAD bytes (to avoid referencing memory beyond the end 1681 * of window[] when looking for matches towards the end). 1682 */ 1683 void lm_init (TState &state, int pack_level, ush *flags) 1684 { 1685 register unsigned j; 1686 1687 Assert(state,pack_level>=1 && pack_level<=8,"bad pack level"); 1688 1689 /* Do not slide the window if the whole input is already in memory 1690 * (window_size > 0) 1691 */ 1692 state.ds.sliding = 0; 1693 if (state.ds.window_size == 0L) { 1694 state.ds.sliding = 1; 1695 state.ds.window_size = (ulg)2L*WSIZE; 1696 } 1697 1698 /* Initialize the hash table (avoiding 64K overflow for 16 bit systems). 1699 * prev[] will be initialized on the fly. 1700 */ 1701 state.ds.head[HASH_SIZE-1] = NIL; 1702 memset((char*)state.ds.head, NIL, (unsigned)(HASH_SIZE-1)*sizeof(*state.ds.head)); 1703 1704 /* Set the default configuration parameters: 1705 */ 1706 state.ds.max_lazy_match = configuration_table[pack_level].max_lazy; 1707 state.ds.good_match = configuration_table[pack_level].good_length; 1708 state.ds.nice_match = configuration_table[pack_level].nice_length; 1709 state.ds.max_chain_length = configuration_table[pack_level].max_chain; 1710 if (pack_level <= 2) { 1711 *flags |= FAST; 1712 } else if (pack_level >= 8) { 1713 *flags |= SLOW; 1714 } 1715 /* ??? reduce max_chain_length for binary files */ 1716 1717 state.ds.strstart = 0; 1718 state.ds.block_start = 0L; 1719 1720 j = WSIZE; 1721 j <<= 1; // Can read 64K in one step 1722 state.ds.lookahead = state.readfunc(state, (char*)state.ds.window, j); 1723 1724 if (state.ds.lookahead == 0 || state.ds.lookahead == (unsigned)EOF) { 1725 state.ds.eofile = 1, state.ds.lookahead = 0; 1726 return; 1727 } 1728 state.ds.eofile = 0; 1729 /* Make sure that we always have enough lookahead. This is important 1730 * if input comes from a device such as a tty. 1731 */ 1732 if (state.ds.lookahead < MIN_LOOKAHEAD) fill_window(state); 1733 1734 state.ds.ins_h = 0; 1735 for (j=0; j<MIN_MATCH-1; j++) UPDATE_HASH(state.ds.ins_h, state.ds.window[j]); 1736 /* If lookahead < MIN_MATCH, ins_h is garbage, but this is 1737 * not important since only literal bytes will be emitted. 1738 */ 1739 } 1740 1741 1742 /* =========================================================================== 1743 * Set match_start to the longest match starting at the given string and 1744 * return its length. Matches shorter or equal to prev_length are discarded, 1745 * in which case the result is equal to prev_length and match_start is 1746 * garbage. 1747 * IN assertions: cur_match is the head of the hash chain for the current 1748 * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 1749 */ 1750 // For 80x86 and 680x0 and ARM, an optimized version is in match.asm or 1751 // match.S. The code is functionally equivalent, so you can use the C version 1752 // if desired. Which I do so desire! 1753 int longest_match(TState &state,IPos cur_match) 1754 { 1755 unsigned chain_length = state.ds.max_chain_length; /* max hash chain length */ 1756 register uch *scan = state.ds.window + state.ds.strstart; /* current string */ 1757 register uch *match; /* matched string */ 1758 register int len; /* length of current match */ 1759 int best_len = state.ds.prev_length; /* best match length so far */ 1760 IPos limit = state.ds.strstart > (IPos)MAX_DIST ? state.ds.strstart - (IPos)MAX_DIST : NIL; 1761 /* Stop when cur_match becomes <= limit. To simplify the code, 1762 * we prevent matches with the string of window index 0. 1763 */ 1764 1765 // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. 1766 // It is easy to get rid of this optimization if necessary. 1767 Assert(state,HASH_BITS>=8 && MAX_MATCH==258,"Code too clever"); 1768 1769 1770 1771 register uch *strend = state.ds.window + state.ds.strstart + MAX_MATCH; 1772 register uch scan_end1 = scan[best_len-1]; 1773 register uch scan_end = scan[best_len]; 1774 1775 /* Do not waste too much time if we already have a good match: */ 1776 if (state.ds.prev_length >= state.ds.good_match) { 1777 chain_length >>= 2; 1778 } 1779 1780 Assert(state,state.ds.strstart <= state.ds.window_size-MIN_LOOKAHEAD, "insufficient lookahead"); 1781 1782 do { 1783 Assert(state,cur_match < state.ds.strstart, "no future"); 1784 match = state.ds.window + cur_match; 1785 1786 /* Skip to next match if the match length cannot increase 1787 * or if the match length is less than 2: 1788 */ 1789 if (match[best_len] != scan_end || 1790 match[best_len-1] != scan_end1 || 1791 *match != *scan || 1792 *++match != scan[1]) continue; 1793 1794 /* The check at best_len-1 can be removed because it will be made 1795 * again later. (This heuristic is not always a win.) 1796 * It is not necessary to compare scan[2] and match[2] since they 1797 * are always equal when the other bytes match, given that 1798 * the hash keys are equal and that HASH_BITS >= 8. 1799 */ 1800 scan += 2, match++; 1801 1802 /* We check for insufficient lookahead only every 8th comparison; 1803 * the 256th check will be made at strstart+258. 1804 */ 1805 do { 1806 } while (*++scan == *++match && *++scan == *++match && 1807 *++scan == *++match && *++scan == *++match && 1808 *++scan == *++match && *++scan == *++match && 1809 *++scan == *++match && *++scan == *++match && 1810 scan < strend); 1811 1812 Assert(state,scan <= state.ds.window+(unsigned)(state.ds.window_size-1), "wild scan"); 1813 1814 len = MAX_MATCH - (int)(strend - scan); 1815 scan = strend - MAX_MATCH; 1816 1817 1818 if (len > best_len) { 1819 state.ds.match_start = cur_match; 1820 best_len = len; 1821 if (len >= state.ds.nice_match) break; 1822 scan_end1 = scan[best_len-1]; 1823 scan_end = scan[best_len]; 1824 } 1825 } while ((cur_match = state.ds.prev[cur_match & WMASK]) > limit 1826 && --chain_length != 0); 1827 1828 return best_len; 1829 } 1830 1831 1832 1833 #define check_match(state,start, match, length) 1834 // or alternatively... 1835 //void check_match(TState &state,IPos start, IPos match, int length) 1836 //{ // check that the match is indeed a match 1837 // if (memcmp((char*)state.ds.window + match, 1838 // (char*)state.ds.window + start, length) != EQUAL) { 1839 // fprintf(stderr, 1840 // " start %d, match %d, length %d\n", 1841 // start, match, length); 1842 // error("invalid match"); 1843 // } 1844 // if (state.verbose > 1) { 1845 // fprintf(stderr,"\\[%d,%d]", start-match, length); 1846 // do { fprintf(stdout,"%c",state.ds.window[start++]); } while (--length != 0); 1847 // } 1848 //} 1849 1850 /* =========================================================================== 1851 * Fill the window when the lookahead becomes insufficient. 1852 * Updates strstart and lookahead, and sets eofile if end of input file. 1853 * 1854 * IN assertion: lookahead < MIN_LOOKAHEAD && strstart + lookahead > 0 1855 * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD 1856 * At least one byte has been read, or eofile is set; file reads are 1857 * performed for at least two bytes (required for the translate_eol option). 1858 */ 1859 void fill_window(TState &state) 1860 { 1861 register unsigned n, m; 1862 unsigned more; /* Amount of free space at the end of the window. */ 1863 1864 do { 1865 more = (unsigned)(state.ds.window_size - (ulg)state.ds.lookahead - (ulg)state.ds.strstart); 1866 1867 /* If the window is almost full and there is insufficient lookahead, 1868 * move the upper half to the lower one to make room in the upper half. 1869 */ 1870 if (more == (unsigned)EOF) { 1871 /* Very unlikely, but possible on 16 bit machine if strstart == 0 1872 * and lookahead == 1 (input done one byte at time) 1873 */ 1874 more--; 1875 1876 /* For MMAP or BIG_MEM, the whole input file is already in memory so 1877 * we must not perform sliding. We must however call (*read_buf)() in 1878 * order to compute the crc, update lookahead and possibly set eofile. 1879 */ 1880 } else if (state.ds.strstart >= WSIZE+MAX_DIST && state.ds.sliding) { 1881 1882 /* By the IN assertion, the window is not empty so we can't confuse 1883 * more == 0 with more == 64K on a 16 bit machine. 1884 */ 1885 memcpy((char*)state.ds.window, (char*)state.ds.window+WSIZE, (unsigned)WSIZE); 1886 state.ds.match_start -= WSIZE; 1887 state.ds.strstart -= WSIZE; /* we now have strstart >= MAX_DIST: */ 1888 1889 state.ds.block_start -= (long) WSIZE; 1890 1891 for (n = 0; n < HASH_SIZE; n++) { 1892 m = state.ds.head[n]; 1893 state.ds.head[n] = (Pos)(m >= WSIZE ? m-WSIZE : NIL); 1894 } 1895 for (n = 0; n < WSIZE; n++) { 1896 m = state.ds.prev[n]; 1897 state.ds.prev[n] = (Pos)(m >= WSIZE ? m-WSIZE : NIL); 1898 /* If n is not on any hash chain, prev[n] is garbage but 1899 * its value will never be used. 1900 */ 1901 } 1902 more += WSIZE; 1903 } 1904 if (state.ds.eofile) return; 1905 1906 /* If there was no sliding: 1907 * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && 1908 * more == window_size - lookahead - strstart 1909 * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) 1910 * => more >= window_size - 2*WSIZE + 2 1911 * In the MMAP or BIG_MEM case (not yet supported in gzip), 1912 * window_size == input_size + MIN_LOOKAHEAD && 1913 * strstart + lookahead <= input_size => more >= MIN_LOOKAHEAD. 1914 * Otherwise, window_size == 2*WSIZE so more >= 2. 1915 * If there was sliding, more >= WSIZE. So in all cases, more >= 2. 1916 */ 1917 Assert(state,more >= 2, "more < 2"); 1918 1919 n = state.readfunc(state, (char*)state.ds.window+state.ds.strstart+state.ds.lookahead, more); 1920 1921 if (n == 0 || n == (unsigned)EOF) { 1922 state.ds.eofile = 1; 1923 } else { 1924 state.ds.lookahead += n; 1925 } 1926 } while (state.ds.lookahead < MIN_LOOKAHEAD && !state.ds.eofile); 1927 } 1928 1929 /* =========================================================================== 1930 * Flush the current block, with given end-of-file flag. 1931 * IN assertion: strstart is set to the end of the current match. 1932 */ 1933 #define FLUSH_BLOCK(state,eof) \ 1934 flush_block(state,state.ds.block_start >= 0L ? (char*)&state.ds.window[(unsigned)state.ds.block_start] : \ 1935 (char*)NULL, (long)state.ds.strstart - state.ds.block_start, (eof)) 1936 1937 /* =========================================================================== 1938 * Processes a new input file and return its compressed length. This 1939 * function does not perform lazy evaluation of matches and inserts 1940 * new strings in the dictionary only for unmatched strings or for short 1941 * matches. It is used only for the fast compression options. 1942 */ 1943 ulg deflate_fast(TState &state) 1944 { 1945 IPos hash_head = NIL; /* head of the hash chain */ 1946 int flush; /* set if current block must be flushed */ 1947 unsigned match_length = 0; /* length of best match */ 1948 1949 state.ds.prev_length = MIN_MATCH-1; 1950 while (state.ds.lookahead != 0) { 1951 /* Insert the string window[strstart .. strstart+2] in the 1952 * dictionary, and set hash_head to the head of the hash chain: 1953 */ 1954 if (state.ds.lookahead >= MIN_MATCH) 1955 INSERT_STRING(state.ds.strstart, hash_head); 1956 1957 /* Find the longest match, discarding those <= prev_length. 1958 * At this point we have always match_length < MIN_MATCH 1959 */ 1960 if (hash_head != NIL && state.ds.strstart - hash_head <= MAX_DIST) { 1961 /* To simplify the code, we prevent matches with the string 1962 * of window index 0 (in particular we have to avoid a match 1963 * of the string with itself at the start of the input file). 1964 */ 1965 /* Do not look for matches beyond the end of the input. 1966 * This is necessary to make deflate deterministic. 1967 */ 1968 if ((unsigned)state.ds.nice_match > state.ds.lookahead) state.ds.nice_match = (int)state.ds.lookahead; 1969 match_length = longest_match (state,hash_head); 1970 /* longest_match() sets match_start */ 1971 if (match_length > state.ds.lookahead) match_length = state.ds.lookahead; 1972 } 1973 if (match_length >= MIN_MATCH) { 1974 check_match(state,state.ds.strstart, state.ds.match_start, match_length); 1975 1976 flush = ct_tally(state,state.ds.strstart-state.ds.match_start, match_length - MIN_MATCH); 1977 1978 state.ds.lookahead -= match_length; 1979 1980 /* Insert new strings in the hash table only if the match length 1981 * is not too large. This saves time but degrades compression. 1982 */ 1983 if (match_length <= state.ds.max_insert_length 1984 && state.ds.lookahead >= MIN_MATCH) { 1985 match_length--; /* string at strstart already in hash table */ 1986 do { 1987 state.ds.strstart++; 1988 INSERT_STRING(state.ds.strstart, hash_head); 1989 /* strstart never exceeds WSIZE-MAX_MATCH, so there are 1990 * always MIN_MATCH bytes ahead. 1991 */ 1992 } while (--match_length != 0); 1993 state.ds.strstart++; 1994 } else { 1995 state.ds.strstart += match_length; 1996 match_length = 0; 1997 state.ds.ins_h = state.ds.window[state.ds.strstart]; 1998 UPDATE_HASH(state.ds.ins_h, state.ds.window[state.ds.strstart+1]); 1999 Assert(state,MIN_MATCH==3,"Call UPDATE_HASH() MIN_MATCH-3 more times"); 2000 } 2001 } else { 2002 /* No match, output a literal byte */ 2003 flush = ct_tally (state,0, state.ds.window[state.ds.strstart]); 2004 state.ds.lookahead--; 2005 state.ds.strstart++; 2006 } 2007 if (flush) FLUSH_BLOCK(state,0), state.ds.block_start = state.ds.strstart; 2008 2009 /* Make sure that we always have enough lookahead, except 2010 * at the end of the input file. We need MAX_MATCH bytes 2011 * for the next match, plus MIN_MATCH bytes to insert the 2012 * string following the next match. 2013 */ 2014 if (state.ds.lookahead < MIN_LOOKAHEAD) fill_window(state); 2015 } 2016 return FLUSH_BLOCK(state,1); /* eof */ 2017 } 2018 2019 /* =========================================================================== 2020 * Same as above, but achieves better compression. We use a lazy 2021 * evaluation for matches: a match is finally adopted only if there is 2022 * no better match at the next window position. 2023 */ 2024 ulg deflate(TState &state) 2025 { 2026 IPos hash_head = NIL; /* head of hash chain */ 2027 IPos prev_match; /* previous match */ 2028 int flush; /* set if current block must be flushed */ 2029 int match_available = 0; /* set if previous match exists */ 2030 register unsigned match_length = MIN_MATCH-1; /* length of best match */ 2031 2032 if (state.level <= 3) return deflate_fast(state); /* optimized for speed */ 2033 2034 /* Process the input block. */ 2035 while (state.ds.lookahead != 0) { 2036 /* Insert the string window[strstart .. strstart+2] in the 2037 * dictionary, and set hash_head to the head of the hash chain: 2038 */ 2039 if (state.ds.lookahead >= MIN_MATCH) 2040 INSERT_STRING(state.ds.strstart, hash_head); 2041 2042 /* Find the longest match, discarding those <= prev_length. 2043 */ 2044 state.ds.prev_length = match_length, prev_match = state.ds.match_start; 2045 match_length = MIN_MATCH-1; 2046 2047 if (hash_head != NIL && state.ds.prev_length < state.ds.max_lazy_match && 2048 state.ds.strstart - hash_head <= MAX_DIST) { 2049 /* To simplify the code, we prevent matches with the string 2050 * of window index 0 (in particular we have to avoid a match 2051 * of the string with itself at the start of the input file). 2052 */ 2053 /* Do not look for matches beyond the end of the input. 2054 * This is necessary to make deflate deterministic. 2055 */ 2056 if ((unsigned)state.ds.nice_match > state.ds.lookahead) state.ds.nice_match = (int)state.ds.lookahead; 2057 match_length = longest_match (state,hash_head); 2058 /* longest_match() sets match_start */ 2059 if (match_length > state.ds.lookahead) match_length = state.ds.lookahead; 2060 2061 /* Ignore a length 3 match if it is too distant: */ 2062 if (match_length == MIN_MATCH && state.ds.strstart-state.ds.match_start > TOO_FAR){ 2063 /* If prev_match is also MIN_MATCH, match_start is garbage 2064 * but we will ignore the current match anyway. 2065 */ 2066 match_length = MIN_MATCH-1; 2067 } 2068 } 2069 /* If there was a match at the previous step and the current 2070 * match is not better, output the previous match: 2071 */ 2072 if (state.ds.prev_length >= MIN_MATCH && match_length <= state.ds.prev_length) { 2073 unsigned max_insert = state.ds.strstart + state.ds.lookahead - MIN_MATCH; 2074 check_match(state,state.ds.strstart-1, prev_match, state.ds.prev_length); 2075 flush = ct_tally(state,state.ds.strstart-1-prev_match, state.ds.prev_length - MIN_MATCH); 2076 2077 /* Insert in hash table all strings up to the end of the match. 2078 * strstart-1 and strstart are already inserted. 2079 */ 2080 state.ds.lookahead -= state.ds.prev_length-1; 2081 state.ds.prev_length -= 2; 2082 do { 2083 if (++state.ds.strstart <= max_insert) { 2084 INSERT_STRING(state.ds.strstart, hash_head); 2085 /* strstart never exceeds WSIZE-MAX_MATCH, so there are 2086 * always MIN_MATCH bytes ahead. 2087 */ 2088 } 2089 } while (--state.ds.prev_length != 0); 2090 state.ds.strstart++; 2091 match_available = 0; 2092 match_length = MIN_MATCH-1; 2093 2094 if (flush) FLUSH_BLOCK(state,0), state.ds.block_start = state.ds.strstart; 2095 2096 } else if (match_available) { 2097 /* If there was no match at the previous position, output a 2098 * single literal. If there was a match but the current match 2099 * is longer, truncate the previous match to a single literal. 2100 */ 2101 if (ct_tally (state,0, state.ds.window[state.ds.strstart-1])) { 2102 FLUSH_BLOCK(state,0), state.ds.block_start = state.ds.strstart; 2103 } 2104 state.ds.strstart++; 2105 state.ds.lookahead--; 2106 } else { 2107 /* There is no previous match to compare with, wait for 2108 * the next step to decide. 2109 */ 2110 match_available = 1; 2111 state.ds.strstart++; 2112 state.ds.lookahead--; 2113 } 2114 // Assert(state,strstart <= isize && lookahead <= isize, "a bit too far"); 2115 2116 /* Make sure that we always have enough lookahead, except 2117 * at the end of the input file. We need MAX_MATCH bytes 2118 * for the next match, plus MIN_MATCH bytes to insert the 2119 * string following the next match. 2120 */ 2121 if (state.ds.lookahead < MIN_LOOKAHEAD) fill_window(state); 2122 } 2123 if (match_available) ct_tally (state,0, state.ds.window[state.ds.strstart-1]); 2124 2125 return FLUSH_BLOCK(state,1); /* eof */ 2126 } 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 int putlocal(struct zlist *z, WRITEFUNC wfunc,void *param) 2140 { // Write a local header described by *z to file *f. Return a ZE_ error code. 2141 PUTLG(LOCSIG, f); 2142 PUTSH(z->ver, f); 2143 PUTSH(z->lflg, f); 2144 PUTSH(z->how, f); 2145 PUTLG(z->tim, f); 2146 PUTLG(z->crc, f); 2147 PUTLG(z->siz, f); 2148 PUTLG(z->len, f); 2149 PUTSH(z->nam, f); 2150 PUTSH(z->ext, f); 2151 size_t res = (size_t)wfunc(param, z->iname, (unsigned int)z->nam); 2152 if (res!=z->nam) return ZE_TEMP; 2153 if (z->ext) 2154 { res = (size_t)wfunc(param, z->extra, (unsigned int)z->ext); 2155 if (res!=z->ext) return ZE_TEMP; 2156 } 2157 return ZE_OK; 2158 } 2159 2160 int putextended(struct zlist *z, WRITEFUNC wfunc, void *param) 2161 { // Write an extended local header described by *z to file *f. Returns a ZE_ code 2162 PUTLG(EXTLOCSIG, f); 2163 PUTLG(z->crc, f); 2164 PUTLG(z->siz, f); 2165 PUTLG(z->len, f); 2166 return ZE_OK; 2167 } 2168 2169 int putcentral(struct zlist *z, WRITEFUNC wfunc, void *param) 2170 { // Write a central header entry of *z to file *f. Returns a ZE_ code. 2171 PUTLG(CENSIG, f); 2172 PUTSH(z->vem, f); 2173 PUTSH(z->ver, f); 2174 PUTSH(z->flg, f); 2175 PUTSH(z->how, f); 2176 PUTLG(z->tim, f); 2177 PUTLG(z->crc, f); 2178 PUTLG(z->siz, f); 2179 PUTLG(z->len, f); 2180 PUTSH(z->nam, f); 2181 PUTSH(z->cext, f); 2182 PUTSH(z->com, f); 2183 PUTSH(z->dsk, f); 2184 PUTSH(z->att, f); 2185 PUTLG(z->atx, f); 2186 PUTLG(z->off, f); 2187 if ((size_t)wfunc(param, z->iname, (unsigned int)z->nam) != z->nam || 2188 (z->cext && (size_t)wfunc(param, z->cextra, (unsigned int)z->cext) != z->cext) || 2189 (z->com && (size_t)wfunc(param, z->comment, (unsigned int)z->com) != z->com)) 2190 return ZE_TEMP; 2191 return ZE_OK; 2192 } 2193 2194 2195 int putend(int n, ulg s, ulg c, extent m, char *z, WRITEFUNC wfunc, void *param) 2196 { // write the end of the central-directory-data to file *f. 2197 PUTLG(ENDSIG, f); 2198 PUTSH(0, f); 2199 PUTSH(0, f); 2200 PUTSH(n, f); 2201 PUTSH(n, f); 2202 PUTLG(s, f); 2203 PUTLG(c, f); 2204 PUTSH(m, f); 2205 // Write the comment, if any 2206 if (m && wfunc(param, z, (unsigned int)m) != m) return ZE_TEMP; 2207 return ZE_OK; 2208 } 2209 2210 2211 2212 2213 2214 2215 const ulg crc_table[256] = { 2216 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 2217 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, 2218 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 2219 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 2220 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, 2221 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 2222 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 2223 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, 2224 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 2225 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, 2226 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 2227 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 2228 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, 2229 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 2230 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 2231 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, 2232 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 2233 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, 2234 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 2235 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 2236 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, 2237 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 2238 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 2239 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, 2240 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 2241 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, 2242 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 2243 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 2244 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, 2245 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 2246 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 2247 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, 2248 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 2249 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, 2250 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 2251 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 2252 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, 2253 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 2254 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 2255 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, 2256 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 2257 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, 2258 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 2259 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 2260 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, 2261 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 2262 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 2263 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, 2264 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 2265 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, 2266 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 2267 0x2d02ef8dL 2268 }; 2269 2270 #define CRC32(c, b) (crc_table[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8)) 2271 #define DO1(buf) crc = CRC32(crc, *buf++) 2272 #define DO2(buf) DO1(buf); DO1(buf) 2273 #define DO4(buf) DO2(buf); DO2(buf) 2274 #define DO8(buf) DO4(buf); DO4(buf) 2275 2276 ulg crc32(ulg crc, const uch *buf, extent len) 2277 { if (buf==NULL) return 0L; 2278 crc = crc ^ 0xffffffffL; 2279 while (len >= 8) {DO8(buf); len -= 8;} 2280 if (len) do {DO1(buf);} while (--len); 2281 return crc ^ 0xffffffffL; // (instead of ~c for 64-bit machines) 2282 } 2283 2284 2285 void update_keys(unsigned long *keys, char c) 2286 { keys[0] = CRC32(keys[0],c); 2287 keys[1] += keys[0] & 0xFF; 2288 keys[1] = keys[1]*134775813L +1; 2289 keys[2] = CRC32(keys[2], keys[1] >> 24); 2290 } 2291 char decrypt_byte(unsigned long *keys) 2292 { unsigned temp = ((unsigned)keys[2] & 0xffff) | 2; 2293 return (char)(((temp * (temp ^ 1)) >> 8) & 0xff); 2294 } 2295 char zencode(unsigned long *keys, char c) 2296 { int t=decrypt_byte(keys); 2297 update_keys(keys,c); 2298 return (char)(t^c); 2299 } 2300 2301 2302 2303 2304 2305 2306 2307 int lustricmp(const TCHAR *sa, const TCHAR *sb) 2308 { for (const TCHAR *ca=sa, *cb=sb; ; ca++, cb++) 2309 { int ia=tolower(*ca), ib=tolower(*cb); 2310 if (ia==ib && ia==0) return 0; 2311 if (ia==ib) continue; 2312 if (ia<ib) return -1; 2313 if (ia>ib) return 1; 2314 } 2315 } 2316 2317 2318 bool HasZipSuffix(const TCHAR *fn) 2319 { const TCHAR *ext = fn+_tcslen(fn); 2320 while (ext>fn && *ext!='.') ext--; 2321 if (ext==fn && *ext!='.') return false; 2322 if (lustricmp(ext,_T(".Z"))==0) return true; 2323 if (lustricmp(ext,_T(".zip"))==0) return true; 2324 if (lustricmp(ext,_T(".zoo"))==0) return true; 2325 if (lustricmp(ext,_T(".arc"))==0) return true; 2326 if (lustricmp(ext,_T(".lzh"))==0) return true; 2327 if (lustricmp(ext,_T(".arj"))==0) return true; 2328 if (lustricmp(ext,_T(".gz"))==0) return true; 2329 if (lustricmp(ext,_T(".tgz"))==0) return true; 2330 return false; 2331 } 2332 2333 2334 2335 2336 2337 2338 2339 2340 class TZip 2341 { public: 2342 TZip(const char *pwd) : hfout(0),mustclosehfout(false),hmapout(0),zfis(0),obuf(0),hfin(0),writ(0),oerr(false),hasputcen(false),ooffset(0),encwriting(false),encbuf(0),password(0), state(0) {if (pwd!=0 && *pwd!=0) {password=new char[strlen(pwd)+1]; strcpy(password,pwd);}} 2343 ~TZip() {if (state!=0) delete state; state=0; if (encbuf!=0) delete[] encbuf; encbuf=0; if (password!=0) delete[] password; password=0;} 2344 2345 // These variables say about the file we're writing into 2346 // We can write to pipe, file-by-handle, file-by-name, memory-to-memmapfile 2347 char *password; // keep a copy of the password 2348 HANDLE hfout; // if valid, we'll write here (for files or pipes) 2349 bool mustclosehfout; // if true, we are responsible for closing hfout 2350 HANDLE hmapout; // otherwise, we'll write here (for memmap) 2351 unsigned ooffset; // for hfout, this is where the pointer was initially 2352 ZRESULT oerr; // did a write operation give rise to an error? 2353 unsigned writ; // how far have we written. This is maintained by Add, not write(), to avoid confusion over seeks 2354 bool ocanseek; // can we seek? 2355 char *obuf; // this is where we've locked mmap to view. 2356 unsigned int opos; // current pos in the mmap 2357 unsigned int mapsize; // the size of the map we created 2358 bool hasputcen; // have we yet placed the central directory? 2359 bool encwriting; // if true, then we'll encrypt stuff using 'keys' before we write it to disk 2360 unsigned long keys[3]; // keys are initialised inside Add() 2361 char *encbuf; // if encrypting, then this is a temporary workspace for encrypting the data 2362 unsigned int encbufsize; // (to be used and resized inside write(), and deleted in the destructor) 2363 // 2364 TZipFileInfo *zfis; // each file gets added onto this list, for writing the table at the end 2365 TState *state; // we use just one state object per zip, because it's big (500k) 2366 2367 ZRESULT Create(void *z,unsigned int len,DWORD flags); 2368 static unsigned sflush(void *param,const char *buf, unsigned *size); 2369 static unsigned swrite(void *param,const char *buf, unsigned size); 2370 unsigned int write(const char *buf,unsigned int size); 2371 bool oseek(unsigned int pos); 2372 ZRESULT GetMemory(void **pbuf, unsigned long *plen); 2373 ZRESULT Close(); 2374 2375 // some variables to do with the file currently being read: 2376 // I haven't done it object-orientedly here, just put them all 2377 // together, since OO didn't seem to make the design any clearer. 2378 ulg attr; iztimes times; ulg timestamp; // all open_* methods set these 2379 bool iseekable; long isize,ired; // size is not set until close() on pips 2380 ulg crc; // crc is not set until close(). iwrit is cumulative 2381 HANDLE hfin; bool selfclosehf; // for input files and pipes 2382 const char *bufin; unsigned int lenin,posin; // for memory 2383 // and a variable for what we've done with the input: (i.e. compressed it!) 2384 ulg csize; // compressed size, set by the compression routines 2385 // and this is used by some of the compression routines 2386 char buf[16384]; 2387 2388 2389 ZRESULT open_file(const TCHAR *fn); 2390 ZRESULT open_handle(HANDLE hf,unsigned int len); 2391 ZRESULT open_mem(void *src,unsigned int len); 2392 ZRESULT open_dir(); 2393 static unsigned sread(TState &s,char *buf,unsigned size); 2394 unsigned read(char *buf, unsigned size); 2395 ZRESULT iclose(); 2396 2397 ZRESULT ideflate(TZipFileInfo *zfi); 2398 ZRESULT istore(); 2399 2400 ZRESULT Add(const TCHAR *odstzn, void *src,unsigned int len, DWORD flags); 2401 ZRESULT AddCentral(); 2402 2403 }; 2404 2405 2406 2407 ZRESULT TZip::Create(void *z,unsigned int len,DWORD flags) 2408 { if (hfout!=0 || hmapout!=0 || obuf!=0 || writ!=0 || oerr!=ZR_OK || hasputcen) return ZR_NOTINITED; 2409 // 2410 if (flags==ZIP_HANDLE) 2411 { HANDLE hf = (HANDLE)z; 2412 hfout=hf; mustclosehfout=false; 2413 #ifdef DuplicateHandle 2414 BOOL res = DuplicateHandle(GetCurrentProcess(),hf,GetCurrentProcess(),&hfout,0,FALSE,DUPLICATE_SAME_ACCESS); 2415 if (res) mustclosehandle=true; 2416 #endif 2417 // now we have hfout. Either we duplicated the handle and we close it ourselves 2418 // (while the caller closes h themselves), or we couldn't duplicate it. 2419 DWORD res=GetFilePosZ(hfout); 2420 ocanseek = (res!=0xFFFFFFFF); 2421 ooffset = ocanseek ? res : 0; 2422 return ZR_OK; 2423 } 2424 else if (flags==ZIP_FILENAME) 2425 { const TCHAR *fn = (const TCHAR*)z; 2426 #ifdef ZIP_STD 2427 hfout = fopen(fn,"wb"); 2428 if (hfout==0) return ZR_NOFILE; 2429 #else 2430 hfout = CreateFile(fn,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); 2431 if (hfout==INVALID_HANDLE_VALUE) {hfout=0; return ZR_NOFILE;} 2432 #endif 2433 ocanseek=true; 2434 ooffset=0; 2435 mustclosehfout=true; 2436 return ZR_OK; 2437 } 2438 else if (flags==ZIP_MEMORY) 2439 { unsigned int size = len; 2440 if (size==0) return ZR_MEMSIZE; 2441 #ifdef ZIP_STD 2442 if (z!=0) obuf=(char*)z; 2443 else return ZR_ARGS; 2444 #else 2445 if (z!=0) obuf=(char*)z; 2446 else 2447 { hmapout = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,size,NULL); 2448 if (hmapout==NULL) return ZR_NOALLOC; 2449 obuf = (char*)MapViewOfFile(hmapout,FILE_MAP_ALL_ACCESS,0,0,size); 2450 if (obuf==0) {CloseHandle(hmapout); hmapout=0; return ZR_NOALLOC;} 2451 } 2452 #endif 2453 ocanseek=true; 2454 opos=0; mapsize=size; 2455 return ZR_OK; 2456 } 2457 else return ZR_ARGS; 2458 } 2459 2460 unsigned TZip::sflush(void *param,const char *buf, unsigned *size) 2461 { // static 2462 if (*size==0) return 0; 2463 TZip *zip = (TZip*)param; 2464 unsigned int writ = zip->write(buf,*size); 2465 if (writ!=0) *size=0; 2466 return writ; 2467 } 2468 unsigned TZip::swrite(void *param,const char *buf, unsigned size) 2469 { // static 2470 if (size==0) return 0; 2471 TZip *zip=(TZip*)param; return zip->write(buf,size); 2472 } 2473 unsigned int TZip::write(const char *buf,unsigned int size) 2474 { const char *srcbuf=buf; 2475 if (encwriting) 2476 { if (encbuf!=0 && encbufsize<size) {delete[] encbuf; encbuf=0;} 2477 if (encbuf==0) {encbuf=new char[size*2]; encbufsize=size;} 2478 memcpy(encbuf,buf,size); 2479 for (unsigned int i=0; i<size; i++) encbuf[i]=zencode(keys,encbuf[i]); 2480 srcbuf=encbuf; 2481 } 2482 if (obuf!=0) 2483 { if (opos+size>=mapsize) {oerr=ZR_MEMSIZE; return 0;} 2484 memcpy(obuf+opos, srcbuf, size); 2485 opos+=size; 2486 return size; 2487 } 2488 else if (hfout!=0) 2489 { 2490 #ifdef ZIP_STD 2491 DWORD writ=(DWORD)fwrite(srcbuf,1,size,hfout); 2492 #else 2493 DWORD writ; WriteFile(hfout,srcbuf,size,&writ,NULL); 2494 #endif 2495 return writ; 2496 } 2497 oerr=ZR_NOTINITED; return 0; 2498 } 2499 2500 bool TZip::oseek(unsigned int pos) 2501 { if (!ocanseek) {oerr=ZR_SEEK; return false;} 2502 if (obuf!=0) 2503 { if (pos>=mapsize) {oerr=ZR_MEMSIZE; return false;} 2504 opos=pos; 2505 return true; 2506 } 2507 else if (hfout!=0) 2508 { 2509 #ifdef ZIP_STD 2510 fseek(hfout,pos+ooffset,SEEK_SET); 2511 #else 2512 SetFilePointer(hfout,pos+ooffset,NULL,FILE_BEGIN); 2513 #endif 2514 return true; 2515 } 2516 oerr=ZR_NOTINITED; return 0; 2517 } 2518 2519 ZRESULT TZip::GetMemory(void **pbuf, unsigned long *plen) 2520 { // When the user calls GetMemory, they're presumably at the end 2521 // of all their adding. In any case, we have to add the central 2522 // directory now, otherwise the memory we tell them won't be complete. 2523 if (!hasputcen) AddCentral(); hasputcen=true; 2524 if (pbuf!=NULL) *pbuf=(void*)obuf; 2525 if (plen!=NULL) *plen=writ; 2526 if (obuf==NULL) return ZR_NOTMMAP; 2527 return ZR_OK; 2528 } 2529 2530 ZRESULT TZip::Close() 2531 { // if the directory hadn't already been added through a call to GetMemory, 2532 // then we do it now 2533 ZRESULT res=ZR_OK; if (!hasputcen) res=AddCentral(); hasputcen=true; 2534 #ifdef ZIP_STD 2535 if (hfout!=0 && mustclosehfout) fclose(hfout); hfout=0; mustclosehfout=false; 2536 #else 2537 if (obuf!=0 && hmapout!=0) UnmapViewOfFile(obuf); obuf=0; 2538 if (hmapout!=0) CloseHandle(hmapout); hmapout=0; 2539 if (hfout!=0 && mustclosehfout) CloseHandle(hfout); hfout=0; mustclosehfout=false; 2540 #endif 2541 return res; 2542 } 2543 2544 2545 2546 2547 ZRESULT TZip::open_file(const TCHAR *fn) 2548 { hfin=0; bufin=0; selfclosehf=false; crc=CRCVAL_INITIAL; isize=0; csize=0; ired=0; 2549 if (fn==0) return ZR_ARGS; 2550 #ifdef ZIP_STD 2551 HANDLE hf = fopen(fn,"rb"); 2552 if (hf==0) return ZR_NOFILE; 2553 ZRESULT res = open_handle(hf,0); 2554 if (res!=ZR_OK) {fclose(hf); return res;} 2555 #else 2556 HANDLE hf = CreateFile(fn,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL); 2557 if (hf==INVALID_HANDLE_VALUE) return ZR_NOFILE; 2558 ZRESULT res = open_handle(hf,0); 2559 if (res!=ZR_OK) {CloseHandle(hf); return res;} 2560 #endif 2561 selfclosehf=true; 2562 return ZR_OK; 2563 } 2564 ZRESULT TZip::open_handle(HANDLE hf,unsigned int len) 2565 { hfin=0; bufin=0; selfclosehf=false; crc=CRCVAL_INITIAL; isize=0; csize=0; ired=0; 2566 if (hf==0 || hf==INVALID_HANDLE_VALUE) return ZR_ARGS; 2567 bool canseek; 2568 #ifdef ZIP_STD 2569 struct stat st; fstat(fileno(hf),&st); canseek = S_ISREG(st.st_mode); 2570 #else 2571 DWORD res = SetFilePointer(hfout,0,0,FILE_CURRENT); 2572 canseek = (res!=0xFFFFFFFF); 2573 #endif 2574 if (canseek) 2575 { ZRESULT res = GetFileInfo(hf,&attr,&isize,×,×tamp); 2576 if (res!=ZR_OK) return res; 2577 #ifdef ZIP_STD 2578 fseek(hf,0,SEEK_SET); 2579 #else 2580 SetFilePointer(hf,0,NULL,FILE_BEGIN); // because GetFileInfo will have screwed it up 2581 #endif 2582 iseekable=true; hfin=hf; 2583 return ZR_OK; 2584 } 2585 else 2586 { attr= 0x80000000; // just a normal file 2587 isize = -1; // can't know size until at the end 2588 if (len!=0) isize=len; // unless we were told explicitly! 2589 iseekable=false; 2590 WORD dosdate, dostime; GetNow(×.atime, &dosdate, &dostime); 2591 times.mtime=times.atime; 2592 times.ctime=times.atime; 2593 timestamp = (WORD)dostime | (((DWORD)dosdate)<<16); 2594 hfin=hf; 2595 return ZR_OK; 2596 } 2597 } 2598 ZRESULT TZip::open_mem(void *src,unsigned int len) 2599 { hfin=0; bufin=(const char*)src; selfclosehf=false; crc=CRCVAL_INITIAL; ired=0; csize=0; ired=0; 2600 lenin=len; posin=0; 2601 if (src==0 || len==0) return ZR_ARGS; 2602 attr= 0x80000000; // just a normal file 2603 isize = len; 2604 iseekable=true; 2605 WORD dosdate, dostime; GetNow(×.atime, &dosdate, &dostime); 2606 times.mtime=times.atime; 2607 times.ctime=times.atime; 2608 timestamp = (WORD)dostime | (((DWORD)dosdate)<<16); 2609 return ZR_OK; 2610 } 2611 ZRESULT TZip::open_dir() 2612 { hfin=0; bufin=0; selfclosehf=false; crc=CRCVAL_INITIAL; isize=0; csize=0; ired=0; 2613 attr= 0x41C00010; // a readable writable directory, and again directory 2614 isize = 0; 2615 iseekable=false; 2616 WORD dosdate, dostime; GetNow(×.atime, &dosdate, &dostime); 2617 times.mtime=times.atime; 2618 times.ctime=times.atime; 2619 timestamp = (WORD)dostime | (((DWORD)dosdate)<<16); 2620 return ZR_OK; 2621 } 2622 2623 unsigned TZip::sread(TState &s,char *buf,unsigned size) 2624 { // static 2625 TZip *zip = (TZip*)s.param; 2626 return zip->read(buf,size); 2627 } 2628 2629 unsigned TZip::read(char *buf, unsigned size) 2630 { if (bufin!=0) 2631 { if (posin>=lenin) return 0; // end of input 2632 ulg red = lenin-posin; 2633 if (red>size) red=size; 2634 memcpy(buf, bufin+posin, red); 2635 posin += red; 2636 ired += red; 2637 crc = crc32(crc, (uch*)buf, red); 2638 return red; 2639 } 2640 else if (hfin!=0) 2641 { DWORD red; 2642 #ifdef ZIP_STD 2643 red = (DWORD)fread(buf,1,size,hfin); 2644 if (red==0) return 0; 2645 #else 2646 BOOL ok = ReadFile(hfin,buf,size,&red,NULL); 2647 if (!ok) return 0; 2648 #endif 2649 ired += red; 2650 crc = crc32(crc, (uch*)buf, red); 2651 return red; 2652 } 2653 else {oerr=ZR_NOTINITED; return 0;} 2654 } 2655 2656 ZRESULT TZip::iclose() 2657 { 2658 #ifdef ZIP_STD 2659 if (selfclosehf && hfin!=0) fclose(hfin); hfin=0; 2660 #else 2661 if (selfclosehf && hfin!=0) CloseHandle(hfin); hfin=0; 2662 #endif 2663 bool mismatch = (isize!=-1 && isize!=ired); 2664 isize=ired; // and crc has been being updated anyway 2665 if (mismatch) return ZR_MISSIZE; 2666 else return ZR_OK; 2667 } 2668 2669 2670 2671 ZRESULT TZip::ideflate(TZipFileInfo *zfi) 2672 { if (state==0) state=new TState(); 2673 // It's a very big object! 500k! We allocate it on the heap, because PocketPC's 2674 // stack breaks if we try to put it all on the stack. It will be deleted lazily 2675 state->err=0; 2676 state->readfunc=sread; state->flush_outbuf=sflush; 2677 state->param=this; state->level=8; state->seekable=iseekable; state->err=NULL; 2678 // the following line will make ct_init realise it has to perform the init 2679 state->ts.static_dtree[0].dl.len = 0; 2680 // Thanks to Alvin77 for this crucial fix: 2681 state->ds.window_size=0; 2682 // I think that covers everything that needs to be initted. 2683 // 2684 bi_init(*state,buf, sizeof(buf), 1); // it used to be just 1024-size, not 16384 as here 2685 ct_init(*state,&zfi->att); 2686 lm_init(*state,state->level, &zfi->flg); 2687 ulg sz = deflate(*state); 2688 csize=sz; 2689 ZRESULT r=ZR_OK; if (state->err!=NULL) r=ZR_FLATE; 2690 return r; 2691 } 2692 2693 ZRESULT TZip::istore() 2694 { ulg size=0; 2695 for (;;) 2696 { unsigned int cin=read(buf,16384); if (cin<=0 || cin==(unsigned int)EOF) break; 2697 unsigned int cout = write(buf,cin); if (cout!=cin) return ZR_MISSIZE; 2698 size += cin; 2699 } 2700 csize=size; 2701 return ZR_OK; 2702 } 2703 2704 2705 2706 2707 2708 bool has_seeded=false; 2709 ZRESULT TZip::Add(const TCHAR *odstzn, void *src,unsigned int len, DWORD flags) 2710 { if (oerr) return ZR_FAILED; 2711 if (hasputcen) return ZR_ENDED; 2712 2713 // if we use password encryption, then every isize and csize is 12 bytes bigger 2714 int passex=0; if (password!=0 && flags!=ZIP_FOLDER) passex=12; 2715 2716 // zip has its own notion of what its names should look like: i.e. dir/file.stuff 2717 TCHAR dstzn[MAX_PATH]; _tcsncpy(dstzn,odstzn,MAX_PATH); dstzn[MAX_PATH-1]=0; 2718 if (*dstzn==0) return ZR_ARGS; 2719 TCHAR *d=dstzn; while (*d!=0) {if (*d=='\\') *d='/'; d++;} 2720 bool isdir = (flags==ZIP_FOLDER); 2721 bool needs_trailing_slash = (isdir && dstzn[_tcslen(dstzn)-1]!='/'); 2722 int method=DEFLATE; if (isdir || HasZipSuffix(dstzn)) method=STORE; 2723 2724 // now open whatever was our input source: 2725 ZRESULT openres; 2726 if (flags==ZIP_FILENAME) openres=open_file((const TCHAR*)src); 2727 else if (flags==ZIP_HANDLE) openres=open_handle((HANDLE)src,len); 2728 else if (flags==ZIP_MEMORY) openres=open_mem(src,len); 2729 else if (flags==ZIP_FOLDER) openres=open_dir(); 2730 else return ZR_ARGS; 2731 if (openres!=ZR_OK) return openres; 2732 2733 // A zip "entry" consists of a local header (which includes the file name), 2734 // then the compressed data, and possibly an extended local header. 2735 2736 // Initialize the local header 2737 TZipFileInfo zfi; zfi.nxt=NULL; 2738 strcpy(zfi.name,""); 2739 #ifdef UNICODE 2740 WideCharToMultiByte(CP_UTF8,0,dstzn,-1,zfi.iname,MAX_PATH,0,0); 2741 #else 2742 strncpy(zfi.iname,dstzn,MAX_PATH); zfi.iname[MAX_PATH-1]=0; 2743 #endif 2744 zfi.nam=strlen(zfi.iname); 2745 if (needs_trailing_slash) {strcat(zfi.iname,"/"); zfi.nam++;} 2746 strcpy(zfi.zname,""); 2747 zfi.extra=NULL; zfi.ext=0; // extra header to go after this compressed data, and its length 2748 zfi.cextra=NULL; zfi.cext=0; // extra header to go in the central end-of-zip directory, and its length 2749 zfi.comment=NULL; zfi.com=0; // comment, and its length 2750 zfi.mark = 1; 2751 zfi.dosflag = 0; 2752 zfi.att = (ush)BINARY; 2753 zfi.vem = (ush)0xB17; // 0xB00 is win32 os-code. 0x17 is 23 in decimal: zip 2.3 2754 zfi.ver = (ush)20; // Needs PKUNZIP 2.0 to unzip it 2755 zfi.tim = timestamp; 2756 // Even though we write the header now, it will have to be rewritten, since we don't know compressed size or crc. 2757 zfi.crc = 0; // to be updated later 2758 zfi.flg = 8; // 8 means 'there is an extra header'. Assume for the moment that we need it. 2759 if (password!=0 && !isdir) zfi.flg=9; // and 1 means 'password-encrypted' 2760 zfi.lflg = zfi.flg; // to be updated later 2761 zfi.how = (ush)method; // to be updated later 2762 zfi.siz = (ulg)(method==STORE && isize>=0 ? isize+passex : 0); // to be updated later 2763 zfi.len = (ulg)(isize); // to be updated later 2764 zfi.dsk = 0; 2765 zfi.atx = attr; 2766 zfi.off = writ+ooffset; // offset within file of the start of this local record 2767 // stuff the 'times' structure into zfi.extra 2768 2769 // nb. apparently there's a problem with PocketPC CE(zip)->CE(unzip) fails. And removing the following block fixes it up. 2770 char xloc[EB_L_UT_SIZE]; zfi.extra=xloc; zfi.ext=EB_L_UT_SIZE; 2771 char xcen[EB_C_UT_SIZE]; zfi.cextra=xcen; zfi.cext=EB_C_UT_SIZE; 2772 xloc[0] = 'U'; 2773 xloc[1] = 'T'; 2774 xloc[2] = EB_UT_LEN(3); // length of data part of e.f. 2775 xloc[3] = 0; 2776 xloc[4] = EB_UT_FL_MTIME | EB_UT_FL_ATIME | EB_UT_FL_CTIME; 2777 xloc[5] = (char)(times.mtime); 2778 xloc[6] = (char)(times.mtime >> 8); 2779 xloc[7] = (char)(times.mtime >> 16); 2780 xloc[8] = (char)(times.mtime >> 24); 2781 xloc[9] = (char)(times.atime); 2782 xloc[10] = (char)(times.atime >> 8); 2783 xloc[11] = (char)(times.atime >> 16); 2784 xloc[12] = (char)(times.atime >> 24); 2785 xloc[13] = (char)(times.ctime); 2786 xloc[14] = (char)(times.ctime >> 8); 2787 xloc[15] = (char)(times.ctime >> 16); 2788 xloc[16] = (char)(times.ctime >> 24); 2789 memcpy(zfi.cextra,zfi.extra,EB_C_UT_SIZE); 2790 zfi.cextra[EB_LEN] = EB_UT_LEN(1); 2791 2792 2793 // (1) Start by writing the local header: 2794 int r = putlocal(&zfi,swrite,this); 2795 if (r!=ZE_OK) {iclose(); return ZR_WRITE;} 2796 writ += 4 + LOCHEAD + (unsigned int)zfi.nam + (unsigned int)zfi.ext; 2797 if (oerr!=ZR_OK) {iclose(); return oerr;} 2798 2799 // (1.5) if necessary, write the encryption header 2800 keys[0]=305419896L; 2801 keys[1]=591751049L; 2802 keys[2]=878082192L; 2803 for (const char *cp=password; cp!=0 && *cp!=0; cp++) update_keys(keys,*cp); 2804 // generate some random bytes 2805 #ifdef ZIP_STD 2806 if (!has_seeded) srand((unsigned)time(0)); 2807 #else 2808 if (!has_seeded) srand(GetTickCount()^(unsigned long)GetDesktopWindow()); 2809 #endif 2810 char encbuf[12]; for (int i=0; i<12; i++) encbuf[i]=(char)((rand()>>7)&0xff); 2811 encbuf[11] = (char)((zfi.tim>>8)&0xff); 2812 for (int ei=0; ei<12; ei++) encbuf[ei]=zencode(keys,encbuf[ei]); 2813 if (password!=0 && !isdir) {swrite(this,encbuf,12); writ+=12;} 2814 2815 //(2) Write deflated/stored file to zip file 2816 ZRESULT writeres=ZR_OK; 2817 encwriting = (password!=0 && !isdir); // an object member variable to say whether we write to disk encrypted 2818 if (!isdir && method==DEFLATE) writeres=ideflate(&zfi); 2819 else if (!isdir && method==STORE) writeres=istore(); 2820 else if (isdir) csize=0; 2821 encwriting = false; 2822 iclose(); 2823 writ += csize; 2824 if (oerr!=ZR_OK) return oerr; 2825 if (writeres!=ZR_OK) return ZR_WRITE; 2826 2827 // (3) Either rewrite the local header with correct information... 2828 bool first_header_has_size_right = (zfi.siz==csize+passex); 2829 zfi.crc = crc; 2830 zfi.siz = csize+passex; 2831 zfi.len = isize; 2832 if (ocanseek && (password==0 || isdir)) 2833 { zfi.how = (ush)method; 2834 if ((zfi.flg & 1) == 0) zfi.flg &= ~8; // clear the extended local header flag 2835 zfi.lflg = zfi.flg; 2836 // rewrite the local header: 2837 if (!oseek(zfi.off-ooffset)) return ZR_SEEK; 2838 if ((r = putlocal(&zfi, swrite,this)) != ZE_OK) return ZR_WRITE; 2839 if (!oseek(writ)) return ZR_SEEK; 2840 } 2841 else 2842 { // (4) ... or put an updated header at the end 2843 if (zfi.how != (ush) method) return ZR_NOCHANGE; 2844 if (method==STORE && !first_header_has_size_right) return ZR_NOCHANGE; 2845 if ((r = putextended(&zfi, swrite,this)) != ZE_OK) return ZR_WRITE; 2846 writ += 16L; 2847 zfi.flg = zfi.lflg; // if flg modified by inflate, for the central index 2848 } 2849 if (oerr!=ZR_OK) return oerr; 2850 2851 // Keep a copy of the zipfileinfo, for our end-of-zip directory 2852 char *cextra = new char[zfi.cext]; memcpy(cextra,zfi.cextra,zfi.cext); zfi.cextra=cextra; 2853 TZipFileInfo *pzfi = new TZipFileInfo; memcpy(pzfi,&zfi,sizeof(zfi)); 2854 if (zfis==NULL) zfis=pzfi; 2855 else {TZipFileInfo *z=zfis; while (z->nxt!=NULL) z=z->nxt; z->nxt=pzfi;} 2856 return ZR_OK; 2857 } 2858 2859 ZRESULT TZip::AddCentral() 2860 { // write central directory 2861 int numentries = 0; 2862 ulg pos_at_start_of_central = writ; 2863 //ulg tot_unc_size=0, tot_compressed_size=0; 2864 bool okay=true; 2865 for (TZipFileInfo *zfi=zfis; zfi!=NULL; ) 2866 { if (okay) 2867 { int res = putcentral(zfi, swrite,this); 2868 if (res!=ZE_OK) okay=false; 2869 } 2870 writ += 4 + CENHEAD + (unsigned int)zfi->nam + (unsigned int)zfi->cext + (unsigned int)zfi->com; 2871 //tot_unc_size += zfi->len; 2872 //tot_compressed_size += zfi->siz; 2873 numentries++; 2874 // 2875 TZipFileInfo *zfinext = zfi->nxt; 2876 if (zfi->cextra!=0) delete[] zfi->cextra; 2877 delete zfi; 2878 zfi = zfinext; 2879 } 2880 ulg center_size = writ - pos_at_start_of_central; 2881 if (okay) 2882 { int res = putend(numentries, center_size, pos_at_start_of_central+ooffset, 0, NULL, swrite,this); 2883 if (res!=ZE_OK) okay=false; 2884 writ += 4 + ENDHEAD + 0; 2885 } 2886 if (!okay) return ZR_WRITE; 2887 return ZR_OK; 2888 } 2889 2890 2891 2892 2893 2894 ZRESULT lasterrorZ=ZR_OK; 2895 2896 unsigned int FormatZipMessageZ(ZRESULT code, char *buf,unsigned int len) 2897 { if (code==ZR_RECENT) code=lasterrorZ; 2898 const char *msg="unknown zip result code"; 2899 switch (code) 2900 { case ZR_OK: msg="Success"; break; 2901 case ZR_NODUPH: msg="Culdn't duplicate handle"; break; 2902 case ZR_NOFILE: msg="Couldn't create/open file"; break; 2903 case ZR_NOALLOC: msg="Failed to allocate memory"; break; 2904 case ZR_WRITE: msg="Error writing to file"; break; 2905 case ZR_NOTFOUND: msg="File not found in the zipfile"; break; 2906 case ZR_MORE: msg="Still more data to unzip"; break; 2907 case ZR_CORRUPT: msg="Zipfile is corrupt or not a zipfile"; break; 2908 case ZR_READ: msg="Error reading file"; break; 2909 case ZR_ARGS: msg="Caller: faulty arguments"; break; 2910 case ZR_PARTIALUNZ: msg="Caller: the file had already been partially unzipped"; break; 2911 case ZR_NOTMMAP: msg="Caller: can only get memory of a memory zipfile"; break; 2912 case ZR_MEMSIZE: msg="Caller: not enough space allocated for memory zipfile"; break; 2913 case ZR_FAILED: msg="Caller: there was a previous error"; break; 2914 case ZR_ENDED: msg="Caller: additions to the zip have already been ended"; break; 2915 case ZR_ZMODE: msg="Caller: mixing creation and opening of zip"; break; 2916 case ZR_NOTINITED: msg="Zip-bug: internal initialisation not completed"; break; 2917 case ZR_SEEK: msg="Zip-bug: trying to seek the unseekable"; break; 2918 case ZR_MISSIZE: msg="Zip-bug: the anticipated size turned out wrong"; break; 2919 case ZR_NOCHANGE: msg="Zip-bug: tried to change mind, but not allowed"; break; 2920 case ZR_FLATE: msg="Zip-bug: an internal error during flation"; break; 2921 } 2922 unsigned int mlen=(unsigned int)strlen(msg); 2923 if (buf==0 || len==0) return mlen; 2924 unsigned int n=mlen; if (n+1>len) n=len-1; 2925 strncpy(buf,msg,n); buf[n]=0; 2926 return mlen; 2927 } 2928 2929 2930 2931 typedef struct 2932 { DWORD flag; 2933 TZip *zip; 2934 } TZipHandleData; 2935 2936 2937 HZIP CreateZipInternal(void *z,unsigned int len,DWORD flags, const char *password) 2938 { TZip *zip = new TZip(password); 2939 lasterrorZ = zip->Create(z,len,flags); 2940 if (lasterrorZ!=ZR_OK) {delete zip; return 0;} 2941 TZipHandleData *han = new TZipHandleData; 2942 han->flag=2; han->zip=zip; return (HZIP)han; 2943 } 2944 HZIP CreateZipHandle(HANDLE h, const char *password) {return CreateZipInternal(h,0,ZIP_HANDLE,password);} 2945 HZIP CreateZip(const TCHAR *fn, const char *password) {return CreateZipInternal((void*)fn,0,ZIP_FILENAME,password);} 2946 HZIP CreateZip(void *z,unsigned int len, const char *password) {return CreateZipInternal(z,len,ZIP_MEMORY,password);} 2947 2948 2949 ZRESULT ZipAddInternal(HZIP hz,const TCHAR *dstzn, void *src,unsigned int len, DWORD flags) 2950 { if (hz==0) {lasterrorZ=ZR_ARGS;return ZR_ARGS;} 2951 TZipHandleData *han = (TZipHandleData*)hz; 2952 if (han->flag!=2) {lasterrorZ=ZR_ZMODE;return ZR_ZMODE;} 2953 TZip *zip = han->zip; 2954 lasterrorZ = zip->Add(dstzn,src,len,flags); 2955 return lasterrorZ; 2956 } 2957 ZRESULT ZipAdd(HZIP hz,const TCHAR *dstzn, const TCHAR *fn) {return ZipAddInternal(hz,dstzn,(void*)fn,0,ZIP_FILENAME);} 2958 ZRESULT ZipAdd(HZIP hz,const TCHAR *dstzn, void *src,unsigned int len) {return ZipAddInternal(hz,dstzn,src,len,ZIP_MEMORY);} 2959 ZRESULT ZipAddHandle(HZIP hz,const TCHAR *dstzn, HANDLE h) {return ZipAddInternal(hz,dstzn,h,0,ZIP_HANDLE);} 2960 ZRESULT ZipAddHandle(HZIP hz,const TCHAR *dstzn, HANDLE h, unsigned int len) {return ZipAddInternal(hz,dstzn,h,len,ZIP_HANDLE);} 2961 ZRESULT ZipAddFolder(HZIP hz,const TCHAR *dstzn) {return ZipAddInternal(hz,dstzn,0,0,ZIP_FOLDER);} 2962 2963 2964 2965 ZRESULT ZipGetMemory(HZIP hz, void **buf, unsigned long *len) 2966 { if (hz==0) {if (buf!=0) *buf=0; if (len!=0) *len=0; lasterrorZ=ZR_ARGS;return ZR_ARGS;} 2967 TZipHandleData *han = (TZipHandleData*)hz; 2968 if (han->flag!=2) {lasterrorZ=ZR_ZMODE;return ZR_ZMODE;} 2969 TZip *zip = han->zip; 2970 lasterrorZ = zip->GetMemory(buf,len); 2971 return lasterrorZ; 2972 } 2973 2974 ZRESULT CloseZipZ(HZIP hz) 2975 { if (hz==0) {lasterrorZ=ZR_ARGS;return ZR_ARGS;} 2976 TZipHandleData *han = (TZipHandleData*)hz; 2977 if (han->flag!=2) {lasterrorZ=ZR_ZMODE;return ZR_ZMODE;} 2978 TZip *zip = han->zip; 2979 lasterrorZ = zip->Close(); 2980 delete zip; 2981 delete han; 2982 return lasterrorZ; 2983 } 2984 2985 bool IsZipHandleZ(HZIP hz) 2986 { if (hz==0) return false; 2987 TZipHandleData *han = (TZipHandleData*)hz; 2988 return (han->flag==2); 2989 }
功不成,身已退