📄 unzipfile.cpp
字号:
uDoCopy);
uf.pfile_in_zip_read->rest_read_uncompressed-=uDoCopy;
uf.pfile_in_zip_read->stream.avail_in -= uDoCopy;
uf.pfile_in_zip_read->stream.avail_out -= uDoCopy;
uf.pfile_in_zip_read->stream.next_out += uDoCopy;
uf.pfile_in_zip_read->stream.next_in += uDoCopy;
uf.pfile_in_zip_read->stream.total_out += uDoCopy;
iRead += uDoCopy;
}
else
{
uLong uTotalOutBefore = uf.pfile_in_zip_read->stream.total_out;
const Bytef *bufBefore = uf.pfile_in_zip_read->stream.next_out;
int flush=Z_SYNC_FLUSH;
/*
if ((uf.pfile_in_zip_read->rest_read_uncompressed ==
uf.pfile_in_zip_read->stream.avail_out) &&
(uf.pfile_in_zip_read->rest_read_compressed == 0))
flush = Z_FINISH;
*/
int err = inflate(&uf.pfile_in_zip_read->stream,flush);
uLong uTotalOutAfter = uf.pfile_in_zip_read->stream.total_out;
uLong uOutThis = uTotalOutAfter-uTotalOutBefore;
uf.pfile_in_zip_read->crc32 =
crc32(uf.pfile_in_zip_read->crc32,bufBefore,
(uInt)(uOutThis));
uf.pfile_in_zip_read->rest_read_uncompressed -=
uOutThis;
iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
if (err==Z_STREAM_END)
return iRead;
CheckForError(err);
}
}
return iRead;
}
/*
Read extra field from the current file (opened by OpenCurrentFile)
This is the local-header version of the extra field (sometimes, there is
more info in the local-header version than in the central-header)
if buf==NULL, it return the size of the local extra field that can be read
if buf!=NULL, len is the size of the buffer, the extra header is copied in
buf.
the return value is the number of bytes copied in buf
*/
int CUnzipFile::GetLocalExtrafield (void* buf, UINT len)
{
if (!uf.pfile_in_zip_read)
ThrowError(UNZ_PARAMERROR);
uLong size_to_read = (uf.pfile_in_zip_read->size_local_extrafield -
uf.pfile_in_zip_read->pos_local_extrafield);
if (!buf)
return (int)size_to_read;
uInt read_now;
if (len>size_to_read)
read_now = (uInt)size_to_read;
else
read_now = (uInt)len ;
if (!read_now)
return 0;
uf.file.Seek(uf.pfile_in_zip_read->offset_local_extrafield +
uf.pfile_in_zip_read->pos_local_extrafield, CFile::begin);
return (int)uf.file.Read(buf, read_now);
}
/*
Get the global comment string of the ZipFile, in the szComment buffer.
uSizeBuf is the size of the szComment buffer.
return the number of byte copied
*/
int CUnzipFile::GetGlobalComment (char* szComment, uLong uSizeBuf)
{
uLong uReadThis = uSizeBuf;
if (uReadThis > uf.gi.size_comment)
uReadThis = uf.gi.size_comment;
uf.file.Seek(uf.central_pos+22, CFile::begin);
if (uReadThis)
{
*szComment = '\0';
uReadThis = uf.file.Read(szComment, (uInt)uReadThis);
}
if (szComment && (uSizeBuf > uf.gi.size_comment))
*(szComment+uf.gi.size_comment)='\0';
return (int)uReadThis;
}
/*
Give the current position in uncompressed data
*/
z_off_t CUnzipFile::tell()
{
if (!uf.pfile_in_zip_read)
ThrowError(UNZ_PARAMERROR);
return (z_off_t)uf.pfile_in_zip_read->stream.total_out;
}
/*
return true if the end of file was reached, false elsewhere
*/
bool CUnzipFile::eof()
{
if (!uf.pfile_in_zip_read)
ThrowError(UNZ_PARAMERROR);
return uf.pfile_in_zip_read->rest_read_uncompressed == 0;
}
CUnzipFile::~CUnzipFile()
{
// Close(); // cannot be here: if an exception is thrown strange things can happen
}
void CUnzipFile::unzlocal_getByte(int & pi)
{
unsigned char c;
uf.file.Read(&c, 1);
pi = (int)c;
}
void CUnzipFile::unzlocal_getShort (uLong & pX)
{
int i;
unzlocal_getByte(i);
uLong x = (uLong)i;
unzlocal_getByte(i);
x += ((uLong)i)<<8;
pX = x;
}
void CUnzipFile::unzlocal_getLong (uLong & pX)
{
uLong x;
unzlocal_getShort(x);
uLong y;
unzlocal_getShort(y);
x += y << 16;
pX = x;
}
// Compare two filename (fileName1,fileName2).
int CUnzipFile::StringFileNameCompare(CString fileName1, CString fileName2, bool caseSensitive)
{
return caseSensitive ? fileName1.Collate(fileName2) : fileName1.CollateNoCase(fileName2);
}
/*
Locate the Central directory of a zipfile (at the end, just before
the global comment)
*/
uLong CUnzipFile::unzlocal_SearchCentralDir()
{
uLong uMaxBack=0xffff; /* maximum size of global comment */
uLong uSizeFile = uf.file.GetLength();
if (uMaxBack > uSizeFile)
uMaxBack = uSizeFile;
char* buf = new char[BUFREADCOMMENT + 4];
uLong uBackRead = 4;
uLong uPosFound = 0;
try
{
while ((uBackRead < uMaxBack) && !uPosFound)
{
uLong uReadSize,uReadPos ;
if (uBackRead + BUFREADCOMMENT > uMaxBack)
uBackRead = uMaxBack;
else
uBackRead += BUFREADCOMMENT;
uReadPos = uSizeFile - uBackRead ;
uReadSize = ((BUFREADCOMMENT + 4) < (uSizeFile - uReadPos)) ?
(BUFREADCOMMENT + 4) : (uSizeFile - uReadPos);
uf.file.Seek(uReadPos, CFile::begin);
uf.file.Read(buf, uReadSize);
for (int i= (int)uReadSize - 3; (i--) > 0 ;)
if (((*(buf+i)) == 0x50) && ((*(buf+i+1))==0x4b) &&
((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
{
uPosFound = uReadPos + i;
break;
}
}
}
catch (CException*)
{
delete[] buf;
throw;
}
delete[] buf;
if (!uPosFound)
ThrowError(UNZ_BADZIPFILE);
return uPosFound;
}
/*
Translate date/time from Dos format to tm_unz (readable more easilty)
*/
void CUnzipFile::unzlocal_DosDateToTmuDate(unz_file_info &file_info)
{
CTime t(HIWORD(file_info.dosDate), LOWORD(file_info.dosDate));
file_info.tmu_date = t;
}
/*
Get Info about the current file in the zipfile, with internal only info
*/
void CUnzipFile::unzlocal_GetCurrentFileInfoInternal( unz_file_info & file_info,
unz_file_info_internal & file_info_internal,
LPSTR szFileName,
uLong fileNameBufferSize,
void *extraField,
uLong extraFieldBufferSize,
LPSTR szComment,
uLong commentBufferSize)
{
uf.file.Seek(uf.pos_in_central_dir + uf.byte_before_the_zipfile, CFile::begin);
uLong uMagic;
/* we check the magic */
unzlocal_getLong(uMagic);
if (uMagic != 0x02014b50)
ThrowError(UNZ_BADZIPFILE);
unzlocal_getShort(file_info.version);
unzlocal_getShort(file_info.version_needed);
unzlocal_getShort(file_info.flag);
unzlocal_getShort(file_info.compression_method);
unzlocal_getLong(file_info.dosDate);
unzlocal_DosDateToTmuDate(file_info);
unzlocal_getLong(file_info.crc);
unzlocal_getLong(file_info.compressed_size);
unzlocal_getLong(file_info.uncompressed_size);
unzlocal_getShort(file_info.size_filename);
unzlocal_getShort(file_info.size_file_extra);
unzlocal_getShort(file_info.size_file_comment);
unzlocal_getShort(file_info.disk_num_start);
unzlocal_getShort(file_info.internal_fa);
unzlocal_getLong(file_info.external_fa);
unzlocal_getLong(file_info_internal.offset_curfile);
uLong lSeek = file_info.size_filename;
if (szFileName)
{
uLong uSizeRead ;
if (file_info.size_filename < fileNameBufferSize)
{
*(szFileName + file_info.size_filename) = '\0';
uSizeRead = file_info.size_filename;
}
else
uSizeRead = fileNameBufferSize;
if ((file_info.size_filename>0) && (fileNameBufferSize>0))
uf.file.Read(szFileName, uSizeRead);
lSeek -= uSizeRead;
}
if (extraField)
{
uLong uSizeRead ;
if (file_info.size_file_extra < extraFieldBufferSize)
uSizeRead = file_info.size_file_extra;
else
uSizeRead = extraFieldBufferSize;
if (lSeek != 0)
{
uf.file.Seek(lSeek, CFile::begin);
lSeek=0;
}
if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
uf.file.Read(extraField, uSizeRead);
lSeek += file_info.size_file_extra - uSizeRead;
}
else
lSeek+=file_info.size_file_extra;
if (szComment)
{
uLong uSizeRead ;
if (file_info.size_file_comment<commentBufferSize)
{
*(szComment+file_info.size_file_comment)='\0';
uSizeRead = file_info.size_file_comment;
}
else
uSizeRead = commentBufferSize;
if (lSeek != 0)
{
uf.file.Seek(lSeek, CFile::begin);
lSeek=0;
}
if ((file_info.size_file_comment>0) && (commentBufferSize>0))
uf.file.Read(szComment, uSizeRead);
lSeek+=file_info.size_file_comment - uSizeRead;
}
else
lSeek+=file_info.size_file_comment;
}
void CUnzipFile::Open(LPCTSTR lpszPath)
{
if (!IsClosed())
return;
CFileException* e = new CFileException;
if (!uf.file.Open(lpszPath, CFile::modeRead | CFile::shareDenyWrite, e))
throw e;
e->Delete();
uLong central_pos = unzlocal_SearchCentralDir();
uf.file.Seek(central_pos, CFile::begin);
/* the signature, already checked */
uLong uL;
unzlocal_getLong(uL);
uLong number_disk; /* number of the current dist, used for
spaning ZIP, unsupported, always 0*/
unzlocal_getShort(number_disk);
uLong number_disk_with_CD; /* number the the disk with central dir, used
for spaning ZIP, unsupported, always 0*/
unzlocal_getShort(number_disk_with_CD);
/* number of the disk with the start of the central directory */
unzlocal_getShort(uf.gi.number_entry);
uLong number_entry_CD; /* total number of entries in
the central dir
(same than number_entry on nospan) */
unzlocal_getShort(number_entry_CD);
if ( (number_entry_CD != uf.gi.number_entry) ||
(number_disk_with_CD != 0) ||
(number_disk != 0))
ThrowError(UNZ_BADZIPFILE);
/* size of the central directory */
unzlocal_getLong(uf.size_central_dir);
/* offset of start of central directory with respect to the
starting disk number */
unzlocal_getLong(uf.offset_central_dir);
/* zipfile comment length */
unzlocal_getShort(uf.gi.size_comment);
if ( central_pos < uf.offset_central_dir + uf.size_central_dir)
ThrowError(UNZ_BADZIPFILE);
uf.byte_before_the_zipfile = central_pos -
(uf.offset_central_dir + uf.size_central_dir);
uf.central_pos = central_pos;
GoToFirstFile();
}
void CUnzipFile::UpdateFileStatus(CFile &f, unz_file_info &ui)
{
CString s = f.GetFilePath();
f.Close();
CFileStatus fs;
fs.m_ctime = fs.m_atime = CTime::GetCurrentTime();
fs.m_attribute = 0;
fs.m_mtime = ui.tmu_date;
CFile::SetStatus(s, fs);
SetFileAttributes(s, ui.external_fa);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -