| 3798 | } |
| 3799 | |
| 3800 | ZRESULT TUnzip::Get(int index,ZIPENTRY *ze) |
| 3801 | { if (index<-1 || index>=(int)uf->gi.number_entry) return ZR_ARGS; |
| 3802 | if (currentfile!=-1) unzCloseCurrentFile(uf); currentfile=-1; |
| 3803 | if (index==czei && index!=-1) {memcpy(ze,&cze,sizeof(ZIPENTRY)); return ZR_OK;} |
| 3804 | if (index==-1) |
| 3805 | { ze->index = uf->gi.number_entry; |
| 3806 | ze->name[0]=0; |
| 3807 | ze->attr=0; |
| 3808 | ze->atime.dwLowDateTime=0; ze->atime.dwHighDateTime=0; |
| 3809 | ze->ctime.dwLowDateTime=0; ze->ctime.dwHighDateTime=0; |
| 3810 | ze->mtime.dwLowDateTime=0; ze->mtime.dwHighDateTime=0; |
| 3811 | ze->comp_size=0; |
| 3812 | ze->unc_size=0; |
| 3813 | return ZR_OK; |
| 3814 | } |
| 3815 | if (index<(int)uf->num_file) unzGoToFirstFile(uf); |
| 3816 | while ((int)uf->num_file<index) unzGoToNextFile(uf); |
| 3817 | unz_file_info ufi; char fn[MAX_PATH]; |
| 3818 | unzGetCurrentFileInfo(uf,&ufi,fn,MAX_PATH,NULL,0,NULL,0); |
| 3819 | // now get the extra header. We do this ourselves, instead of |
| 3820 | // calling unzOpenCurrentFile &c., to avoid allocating more than necessary. |
| 3821 | unsigned int extralen,iSizeVar; unsigned long offset; |
| 3822 | int res = unzlocal_CheckCurrentFileCoherencyHeader(uf,&iSizeVar,&offset,&extralen); |
| 3823 | if (res!=UNZ_OK) return ZR_CORRUPT; |
| 3824 | if (lufseek(uf->file,offset,SEEK_SET)!=0) return ZR_READ; |
| 3825 | unsigned char *extra = new unsigned char[extralen]; |
| 3826 | if (lufread(extra,1,(uInt)extralen,uf->file)!=extralen) {delete[] extra; return ZR_READ;} |
| 3827 | // |
| 3828 | ze->index=uf->num_file; |
| 3829 | TCHAR tfn[MAX_PATH]; |
| 3830 | #ifdef UNICODE |
| 3831 | MultiByteToWideChar(CP_UTF8,0,fn,-1,tfn,MAX_PATH); |
| 3832 | #else |
| 3833 | strcpy(tfn,fn); |
| 3834 | #endif |
| 3835 | // As a safety feature: if the zip filename had sneaky stuff |
| 3836 | // like "c:\windows\file.txt" or "\windows\file.txt" or "fred\..\..\..\windows\file.txt" |
| 3837 | // then we get rid of them all. That way, when the programmer does UnzipItem(hz,i,ze.name), |
| 3838 | // it won't be a problem. (If the programmer really did want to get the full evil information, |
| 3839 | // then they can edit out this security feature from here). |
| 3840 | // In particular, we chop off any prefixes that are "c:\" or "\" or "/" or "[stuff]\.." or "[stuff]/.." |
| 3841 | const TCHAR *sfn=tfn; |
| 3842 | for (;;) |
| 3843 | { if (sfn[0]!=0 && sfn[1]==':') {sfn+=2; continue;} |
| 3844 | if (sfn[0]=='\\') {sfn++; continue;} |
| 3845 | if (sfn[0]=='/') {sfn++; continue;} |
| 3846 | const TCHAR *c; |
| 3847 | c=_tcsstr(sfn,_T("\\..\\")); if (c!=0) {sfn=c+4; continue;} |
| 3848 | c=_tcsstr(sfn,_T("\\../")); if (c!=0) {sfn=c+4; continue;} |
| 3849 | c=_tcsstr(sfn,_T("/../")); if (c!=0) {sfn=c+4; continue;} |
| 3850 | c=_tcsstr(sfn,_T("/..\\")); if (c!=0) {sfn=c+4; continue;} |
| 3851 | break; |
| 3852 | } |
| 3853 | _tcscpy_s(ze->name, MAX_PATH, sfn); |
| 3854 | |
| 3855 | |
| 3856 | // zip has an 'attribute' 32bit value. Its lower half is windows stuff |
| 3857 | // its upper half is standard unix stat.st_mode. We'll start trying |
no test coverage detected