#include"stdafx.h"#include<windows.h>#include<stdio.h>#include<tchar.h>#include"zip.h"//THISFILEisalmostentirelybaseduponcodebyinfo-zip.//IthasbeenmodifiedbyLucianWischik.Themodifications//wereacompleterewriteofthebitofcodethatgeneratesthe//layoutofthezipfile,andsupportforzippingto/frommemory//orhandlesorpipesorpagefileordiskfiles,encryption,unicode.//Theoriginalcodemaybefoundathttp://www.info-zip.org//Theoriginalcopyrighttextfollows.////////Thisisversion1999-Oct-05oftheInfo-ZIPcopyrightandlicense.//Thedefinitiveversionofthisdocumentshouldbeavailableat//ftp://ftp.cdrom.com/pub/infozip/license.htmlindefinitely.////Copyright(c)1990-1999Info-ZIP.Allrightsreserved.////Forthepurposesofthiscopyrightandlicense,"Info-ZIP"isdefinedas//thefollowingsetofindividuals:////MarkAdler,JohnBush,KarlDavis,HaraldDenker,Jean-MichelDubois,//Jean-loupGailly,HunterGoatley,IanGorman,ChrisHerborth,DirkHaase,//GregHartwig,RobertHeath,JonathanHudson,PaulKienitz,DavidKirschbaum,//JohnnyLee,OnnovanderLinden,IgorMandrichenko,SteveP.Miller,//SergioMonesi,KeithOwens,GeorgePetrov,GregRoelofs,KaiUweRommel,//SteveSalisbury,DaveSmith,ChristianSpieler,AntoineVerheijen,//PaulvonBehren,RichWales,MikeWhite////Thissoftwareisprovided"as is,"withoutwarrantyofanykind,express//orimplied.InnoeventshallInfo-ZIPoritscontributorsbeheldliable//foranydirect,indirect,incidental,specialorconsequentialdamages//arisingoutoftheuseoforinabilitytousethissoftware.////Permissionisgrantedtoanyonetousethissoftwareforanypurpose,//includingcommercialapplications,andtoalteritandredistributeit//freely,subjecttothefollowingrestrictions:////1.Redistributionsofsourcecodemustretaintheabovecopyrightnotice,//definition,disclaimer,andthislistofconditions.////2.Redistributionsinbinaryformmustreproducetheabovecopyright//notice,definition,disclaimer,andthislistofconditionsin//documentationand/orothermaterialsprovidedwiththedistribution.////3.Alteredversions--including,butnotlimitedto,portstonewoperating//systems,existingportswithnewgraphicalinterfaces,anddynamic,//shared,orstaticlibraryversions--mustbeplainlymarkedassuch//andmustnotbemisrepresentedasbeingtheoriginalsource.Such//alteredversionsalsomustnotbemisrepresentedasbeingInfo-ZIP//releases--including,butnotlimitedto,labelingofthealtered//versionswiththenames"Info-ZIP"(oranyvariationthereof,including,//butnotlimitedto,differentcapitalizations),"Pocket UnZip,""WiZ"//or"MacZip"withouttheexplicitpermissionofInfo-ZIP.Suchaltered//versionsarefurtherprohibitedfrommisrepresentativeuseofthe//Zip-BugsorInfo-ZIPe-mailaddressesoroftheInfo-ZIPURL(s).////4.Info-ZIPretainstherighttousethenames"Info-ZIP,""Zip,""UnZip,"//"WiZ,""Pocket UnZip,""Pocket Zip,"and"MacZip"foritsownsourceand//binaryreleases.//typedefunsignedcharuch;//unsigned8-bitvaluetypedefunsignedshortush;//unsigned16-bitvaluetypedefunsignedlongulg;//unsigned32-bitvaluetypedefsize_textent;//filesizetypedefunsignedPos;//mustbeatleast32bitstypedefunsignedIPos;//APosisanindexinthecharacterwindow.Posisusedonlyforparameterpassing#ifndefEOF#defineEOF(-1)#endif//Errorreturnvalues.Thevalues0..4and12..18followtheconventions//ofPKZIP.Thevalues4..10areallassignedto"insufficient memory"//byPKZIP,sothecodes5..10areusedhereforotherpurposes.#defineZE_MISS-1//usedbyprocname(),zipbare()#defineZE_OK0//success#defineZE_EOF2//unexpectedendofzipfile#defineZE_FORM3//zipfilestructureerror#defineZE_MEM4//outofmemory#defineZE_LOGIC5//internallogicerror#defineZE_BIG6//entrytoolargetosplit#defineZE_NOTE7//invalidcommentformat#defineZE_TEST8//ziptest(-T)failedoroutofmemory#defineZE_ABORT9//userinterruptortermination#defineZE_TEMP10//errorusingatempfile#defineZE_READ11//readorseekerror#defineZE_NONE12//nothingtodo#defineZE_NAME13//missingoremptyzipfile#defineZE_WRITE14//errorwritingtoafile#defineZE_CREAT15//couldn'topentowrite#defineZE_PARMS16//badcommandline#defineZE_OPEN18//couldnotopenaspecifiedfiletoread#defineZE_MAXERR18//thehighesterrornumber//internalfileattribute#defineUNKNOWN(-1)#defineBINARY0#defineASCII1#defineBEST-1//Usebestmethod(deflationorstore)#defineSTORE0//Storemethod#defineDEFLATE8//Deflationmethod#defineCRCVAL_INITIAL0L//MSDOSfileordirectoryattributes#defineMSDOS_HIDDEN_ATTR0x02#defineMSDOS_DIR_ATTR0x10//Lengthsofheadersaftersignaturesinbytes#defineLOCHEAD26#defineCENHEAD42#defineENDHEAD18//Definitionsforextrafieldhandling:#defineEB_HEADSIZE4/* length of a extra field block header */#defineEB_LEN2/* offset of data length field in header */#defineEB_UT_MINLEN1/* minimal UT field contains Flags byte */#defineEB_UT_FLAGS0/* byte offset of Flags field */#defineEB_UT_TIME11/* byte offset of 1st time value */#defineEB_UT_FL_MTIME(1<<0)/* mtime present */#defineEB_UT_FL_ATIME(1<<1)/* atime present */#defineEB_UT_FL_CTIME(1<<2)/* ctime present */#defineEB_UT_LEN(n)(EB_UT_MINLEN+4*(n))#defineEB_L_UT_SIZE(EB_HEADSIZE+EB_UT_LEN(3))#defineEB_C_UT_SIZE(EB_HEADSIZE+EB_UT_LEN(1))//Macrosforwritingmachineintegerstolittle-endianformat#definePUTSH(a,f){char_putsh_c=(char)((a)&0xff);wfunc(param,&_putsh_c,1);_putsh_c=(char)((a)>>8);wfunc(param,&_putsh_c,1);}#definePUTLG(a,f){PUTSH((a)&0xffff,(f))PUTSH((a)>>16,(f))}//--StructureofaZIPfile--//Signaturesforzipfileinformationheaders#defineLOCSIG0x04034b50L#defineCENSIG0x02014b50L#defineENDSIG0x06054b50L#defineEXTLOCSIG0x08074b50L#defineMIN_MATCH3#defineMAX_MATCH258//Theminimumandmaximummatchlengths#defineWSIZE(0x8000)//Maximumwindowsize=32K.Ifyouarereallyshortofmemory,compile//withasmallerWSIZEbutthisreducesthecompressionratioforfiles//ofsize>WSIZE.WSIZEmustbeapoweroftwointhecurrentimplementation.//#defineMIN_LOOKAHEAD(MAX_MATCH+MIN_MATCH+1)//Minimumamountoflookahead,exceptattheendoftheinputfile.//Seedeflate.cforcommentsabouttheMIN_MATCH+1.//#defineMAX_DIST(WSIZE-MIN_LOOKAHEAD)//Inordertosimplifythecode,particularlyon16bitmachines,match//distancesarelimitedtoMAX_DISTinsteadofWSIZE.//#defineZIP_HANDLE1#defineZIP_FILENAME2#defineZIP_MEMORY3#defineZIP_FOLDER4//===========================================================================//Constants//#defineMAX_BITS15//AllcodesmustnotexceedMAX_BITSbits#defineMAX_BL_BITS7//BitlengthcodesmustnotexceedMAX_BL_BITSbits#defineLENGTH_CODES29//numberoflengthcodes,notcountingthespecialEND_BLOCKcode#defineLITERALS256//numberofliteralbytes0..255#defineEND_BLOCK256//endofblockliteralcode#defineL_CODES(LITERALS+1+LENGTH_CODES)//numberofLiteralorLengthcodes,includingtheEND_BLOCKcode#defineD_CODES30//numberofdistancecodes#defineBL_CODES19//numberofcodesusedtotransferthebitlengths#defineSTORED_BLOCK0#defineSTATIC_TREES1#defineDYN_TREES2//Thethreekindsofblocktype#defineLIT_BUFSIZE0x8000#defineDIST_BUFSIZELIT_BUFSIZE//Sizesofmatchbuffersforliterals/lengthsanddistances.Thereare//4reasonsforlimitingLIT_BUFSIZEto64K://-frequenciescanbekeptin16bitcounters//-ifcompressionisnotsuccessfulforthefirstblock,allinputdatais//stillinthewindowsowecanstillemitastoredblockevenwheninput//comesfromstandardinput.(Thiscanalsobedoneforallblocksif//LIT_BUFSIZEisnotgreaterthan32K.)//-ifcompressionisnotsuccessfulforafilesmallerthan64K,wecan//evenemitastoredfileinsteadofastoredblock(saving5bytes).//-creatingnewHuffmantreeslessfrequentlymaynotprovidefast//adaptationtochangesintheinputdatastatistics.(Takefor//exampleabinaryfilewithpoorlycompressiblecodefollowedby//ahighlycompressiblestringtable.)Smallerbuffersizesgive//fastadaptationbuthaveofcoursetheoverheadoftransmittingtrees//morefrequently.//-Ican'tcountabove4//ThecurrentcodeisgeneralandallowsDIST_BUFSIZE<LIT_BUFSIZE(tosave//memoryattheexpenseofcompression).Someoptimizationswouldbepossible//ifwerelyonDIST_BUFSIZE==LIT_BUFSIZE.//#defineREP_3_616//repeatpreviousbitlength3-6times(2bitsofrepeatcount)#defineREPZ_3_1017//repeatazerolength3-10times(3bitsofrepeatcount)#defineREPZ_11_13818//repeatazerolength11-138times(7bitsofrepeatcount)#defineHEAP_SIZE(2*L_CODES+1)//maximumheapsize//===========================================================================//Localdatausedbythe"bit string"routines.//#defineBuf_size(8*2*sizeof(char))//Numberofbitsusedwithinbi_buf.(bi_bufmaybeimplementedon//morethan16bitsonsomesystems.)//Outputa16bitvaluetothebitstream,lower(oldest)bytefirst#definePUTSHORT(state,w)\{if(state.bs.out_offset>=state.bs.out_size-1)\state.flush_outbuf(state.param,state.bs.out_buf,&state.bs.out_offset);\state.bs.out_buf[state.bs.out_offset++]=(char)((w)&0xff);\state.bs.out_buf[state.bs.out_offset++]=(char)((ush)(w)>>8);\}#definePUTBYTE(state,b)\{if(state.bs.out_offset>=state.bs.out_size)\state.flush_outbuf(state.param,state.bs.out_buf,&state.bs.out_offset);\state.bs.out_buf[state.bs.out_offset++]=(char)(b);\}//DEFLATE.CPPHEADER#defineHASH_BITS15//Forportabilityto16bitmachines,donotusevaluesabove15.#defineHASH_SIZE(unsigned)(1<<HASH_BITS)#defineHASH_MASK(HASH_SIZE-1)#defineWMASK(WSIZE-1)//HASH_SIZEandWSIZEmustbepowersoftwo#defineNIL0//Tailofhashchains#defineFAST4#defineSLOW2//speedoptionsforthegeneralpurposebitflag#defineTOO_FAR4096//Matchesoflength3arediscardediftheirdistanceexceedsTOO_FAR#defineEQUAL0//resultofmemcmpforequalstrings//===========================================================================//Localdatausedbythe"longest match"routines.#defineH_SHIFT((HASH_BITS+MIN_MATCH-1)/MIN_MATCH)//Numberofbitsbywhichins_handdel_hmustbeshiftedateach//inputstep.ItmustbesuchthatafterMIN_MATCHsteps,theoldest//bytenolongertakespartinthehashkey,thatis://H_SHIFT*MIN_MATCH>=HASH_BITS#definemax_insert_lengthmax_lazy_match//Insertnewstringsinthehashtableonlyifthematchlength//isnotgreaterthanthislength.Thissavestimebutdegradescompression.//max_insert_lengthisusedonlyforcompressionlevels<=3.constintextra_lbits[LENGTH_CODES]//extrabitsforeachlengthcode={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};constintextra_dbits[D_CODES]//extrabitsforeachdistancecode={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};constintextra_blbits[BL_CODES]//extrabitsforeachbitlengthcode={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};constuchbl_order[BL_CODES]={16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};//Thelengthsofthebitlengthcodesaresentinorderofdecreasing//probability,toavoidtransmittingthelengthsforunusedbitlengthcodes.typedefstructconfig{ushgood_length;//reducelazysearchabovethismatchlengthushmax_lazy;//donotperformlazysearchabovethismatchlengthushnice_length;//quitsearchabovethismatchlengthushmax_chain;}config;//Valuesformax_lazy_match,good_match,nice_matchandmax_chain_length,//dependingonthedesiredpacklevel(0..9).Thevaluesgivenbelowhave//beentunedtoexcludeworstcaseperformanceforpathologicalfiles.//Bettervaluesmaybefoundforspecificfiles.//constconfigconfiguration_table[10]={//goodlazynicechain{0,0,0,0},//0storeonly{4,4,8,4},//1maximumspeed,nolazymatches{4,5,16,8},//2{4,6,32,32},//3{4,4,16,16},//4lazymatches*/{8,16,32,32},//5{8,16,128,128},//6{8,32,128,256},//7{32,128,258,1024},//8{32,258,258,4096}};//9maximumcompression*///Note:thedeflate()coderequiresmax_lazy>=MIN_MATCHandmax_chain>=4//Fordeflate_fast()(levels<=3)goodisignoredandlazyhasadifferentmeaning.//Datastructuredescribingasinglevalueanditscodestring.typedefstructct_data{union{ushfreq;//frequencycountushcode;//bitstring}fc;union{ushdad;//fathernodeinHuffmantreeushlen;//lengthofbitstring}dl;}ct_data;typedefstructtree_desc{ct_data*dyn_tree;//thedynamictreect_data*static_tree;//correspondingstatictreeorNULLconstint*extra_bits;//extrabitsforeachcodeorNULLintextra_base;//baseindexforextra_bitsintelems;//maxnumberofelementsinthetreeintmax_length;//maxbitlengthforthecodesintmax_code;//largestcodewithnonzerofrequency}tree_desc;classTTreeState{public:TTreeState();ct_datadyn_ltree[HEAP_SIZE];//literalandlengthtreect_datadyn_dtree[2*D_CODES+1];//distancetreect_datastatic_ltree[L_CODES+2];//thestaticliteraltree...//...Sincethebitlengthsareimposed,thereisnoneedfortheL_CODES//extracodesusedduringheapconstruction.Howeverthecodes286and287//areneededtobuildacanonicaltree(seect_initbelow).ct_datastatic_dtree[D_CODES];//thestaticdistancetree...//...(Actuallyatrivialtreesinceallcodesuse5bits.)ct_databl_tree[2*BL_CODES+1];//Huffmantreeforthebitlengthstree_descl_desc;tree_descd_desc;tree_descbl_desc;ushbl_count[MAX_BITS+1];//numberofcodesateachbitlengthforanoptimaltreeintheap[2*L_CODES+1];//heapusedtobuildtheHuffmantreesintheap_len;//numberofelementsintheheapintheap_max;//elementoflargestfrequency//Thesonsofheap[n]areheap[2*n]andheap[2*n+1].heap[0]isnotused.//Thesameheaparrayisusedtobuildalltrees.uchdepth[2*L_CODES+1];//Depthofeachsubtreeusedastiebreakerfortreesofequalfrequencyuchlength_code[MAX_MATCH-MIN_MATCH+1];//lengthcodeforeachnormalizedmatchlength(0==MIN_MATCH)uchdist_code[512];//distancecodes.Thefirst256valuescorrespondtothedistances//3..258,thelast256valuescorrespondtothetop8bitsof//the15bitdistances.intbase_length[LENGTH_CODES];//Firstnormalizedlengthforeachcode(0=MIN_MATCH)intbase_dist[D_CODES];//Firstnormalizeddistanceforeachcode(0=distanceof1)uchfarl_buf[LIT_BUFSIZE];//bufferforliterals/lengthsushfard_buf[DIST_BUFSIZE];//bufferfordistancesuchflag_buf[(LIT_BUFSIZE/8)];//flag_bufisabitarraydistinguishingliteralsfromlengthsin//l_buf,andthusindicatingthepresenceorabsenceofadistance.unsignedlast_lit;//runningindexinl_bufunsignedlast_dist;//runningindexind_bufunsignedlast_flags;//runningindexinflag_bufuchflags;//currentflagsnotyetsavedinflag_bufuchflag_bit;//currentbitusedinflags//bitsarefilledinflagsstartingatbit0(leastsignificant).//Note:theseflagsareoverkillinthecurrentcodesincewedon't//takeadvantageofDIST_BUFSIZE==LIT_BUFSIZE.ulgopt_len;//bitlengthofcurrentblockwithoptimaltreesulgstatic_len;//bitlengthofcurrentblockwithstatictreesulgcmpr_bytelen;//totalbytelengthofcompressedfileulgcmpr_len_bits;//numberofbitspast'cmpr_bytelen'ulginput_len;//totalbytelengthofinputfile//input_lenisfordebuggingonlysincewecangetitbyothermeans.ush*file_type;//pointertoUNKNOWN,BINARYorASCII//int*file_method;//pointertoDEFLATEorSTORE};TTreeState::TTreeState(){tree_desca={dyn_ltree,static_ltree,extra_lbits,LITERALS+1,L_CODES,MAX_BITS,0};l_desc=a;tree_descb={dyn_dtree,static_dtree,extra_dbits,0,D_CODES,MAX_BITS,0};d_desc=b;tree_descc={bl_tree,NULL,extra_blbits,0,BL_CODES,MAX_BL_BITS,0};bl_desc=c;last_lit=0;last_dist=0;last_flags=0;}classTBitState{public:intflush_flg;//unsignedbi_buf;//Outputbuffer.bitsareinsertedstartingatthebottom(leastsignificant//bits).Thewidthofbi_bufmustbeatleast16bits.intbi_valid;//Numberofvalidbitsinbi_buf.Allbitsabovethelastvalidbit//arealwayszero.char*out_buf;//Currentoutputbuffer.unsignedout_offset;//Currentoffsetinoutputbuffer.//On16bitmachines,thebufferislimitedto64K.unsignedout_size;//Sizeofcurrentoutputbufferulgbits_sent;//bitlengthofthecompresseddataonlyneededfordebugging???};classTDeflateState{public:TDeflateState(){window_size=0;}uchwindow[2L*WSIZE];//Slidingwindow.Inputbytesarereadintothesecondhalfofthewindow,//andmovetothefirsthalflatertokeepadictionaryofatleastWSIZE//bytes.Withthisorganization,matchesarelimitedtoadistanceof//WSIZE-MAX_MATCHbytes,butthisensuresthatIOisalways//performedwithalengthmultipleoftheblocksize.Also,itlimits//thewindowsizeto64K,whichisquiteusefulonMSDOS.//Todo:limitthewindowsizetoWSIZE+CBSZifSMALL_MEM(thecodewould//belessefficientsincethedatawouldhavetobecopiedWSIZE/CBSZtimes)Posprev[WSIZE];//Linktoolderstringwithsamehashindex.Tolimitthesizeofthis//arrayto64K,thislinkismaintainedonlyforthelast32Kstrings.//Anindexinthisarrayisthusawindowindexmodulo32K.Poshead[HASH_SIZE];//HeadsofthehashchainsorNIL.Ifyourcompilerthinksthat//HASH_SIZEisadynamicvalue,recompilewith-DDYN_ALLOC.ulgwindow_size;//windowsize,2*WSIZEexceptforMMAPorBIG_MEM,whereitisthe//inputfilelengthplusMIN_LOOKAHEAD.longblock_start;//windowpositionatthebeginningofthecurrentoutputblock.Gets//negativewhenthewindowismovedbackwards.intsliding;//Settofalsewhentheinputfileisalreadyinmemoryunsignedins_h;//hashindexofstringtobeinsertedunsignedintprev_length;//Lengthofthebestmatchatpreviousstep.Matchesnotgreaterthanthis//arediscarded.Thisisusedinthelazymatchevaluation.unsignedstrstart;//startofstringtoinsertunsignedmatch_start;//startofmatchingstringinteofile;//flagsetatendofinputfileunsignedlookahead;//numberofvalidbytesaheadinwindowunsignedmax_chain_length;//Tospeedupdeflation,hashchainsareneversearchedbeyondthislength.//Ahigherlimitimprovescompressionratiobutdegradesthespeed.unsignedintmax_lazy_match;//Attempttofindabettermatchonlywhenthecurrentmatchisstrictly//smallerthanthisvalue.Thismechanismisusedonlyforcompression//levels>=4.unsignedgood_match;//Useafastersearchwhenthepreviousmatchislongerthanthisintnice_match;//Stopsearchingwhencurrentmatchexceedsthis};typedef__int64lutime_t;//defineitourselvessincewedon'tincludetime.htypedefstructiztimes{lutime_tatime,mtime,ctime;}iztimes;//access,modify,createtimestypedefstructzlist{ushvem,ver,flg,how;//Seecentralheaderinzipfile.cforwhatvem..offareulgtim,crc,siz,len;extentnam,ext,cext,com;//offsetofextmustbe>=LOCHEADushdsk,att,lflg;//offsetoflflgmustbe>=LOCHEADulgatx,off;charname[MAX_PATH];//Filenameinzipfilechar*extra;//Extrafield(setonlyifext!=0)char*cextra;//Extraincentral(setonlyifcext!=0)char*comment;//Comment(setonlyifcom!=0)chariname[MAX_PATH];//Internalfilenameaftercleanupcharzname[MAX_PATH];//Externalversionofinternalnameintmark;//Markerforfilestooperateoninttrash;//Markerforfilestodeleteintdosflag;//SettoforceMSDOSfileattributesstructzlistfar*nxt;//Pointertonextheaderinlist}TZipFileInfo;structTState;typedefunsigned(*READFUNC)(TState&state,char*buf,unsignedsize);typedefunsigned(*FLUSHFUNC)(void*param,constchar*buf,unsigned*size);typedefunsigned(*WRITEFUNC)(void*param,constchar*buf,unsignedsize);structTState{void*param;intlevel;boolseekable;READFUNCreadfunc;FLUSHFUNCflush_outbuf;TTreeStatets;TBitStatebs;TDeflateStateds;constchar*err;};voidAssert(TState&state,boolcond,constchar*msg){if(cond)return;state.err=msg;}void__cdeclTrace(constchar*x,...){va_listparamList;va_start(paramList,x);paramList;va_end(paramList);}void__cdeclTracec(bool,constchar*x,...){va_listparamList;va_start(paramList,x);paramList;va_end(paramList);}//===========================================================================//Local(static)routinesinthisfile.//voidinit_block(TState&);voidpqdownheap(TState&,ct_data*tree,intk);voidgen_bitlen(TState&,tree_desc*desc);voidgen_codes(TState&state,ct_data*tree,intmax_code);voidbuild_tree(TState&,tree_desc*desc);voidscan_tree(TState&,ct_data*tree,intmax_code);voidsend_tree(TState&state,ct_data*tree,intmax_code);intbuild_bl_tree(TState&);voidsend_all_trees(TState&state,intlcodes,intdcodes,intblcodes);voidcompress_block(TState&state,ct_data*ltree,ct_data*dtree);voidset_file_type(TState&);voidsend_bits(TState&state,intvalue,intlength);unsignedbi_reverse(unsignedcode,intlen);voidbi_windup(TState&state);voidcopy_block(TState&state,char*buf,unsignedlen,intheader);#definesend_code(state,c,tree)send_bits(state,tree[c].fc.code,tree[c].dl.len)//Sendacodeofthegiventree.candtreemustnothavesideeffects//alternatively...//#definesend_code(state,c,tree)//{if(state.verbose>1)fprintf(stderr,"\ncd %3d ",(c));//send_bits(state,tree[c].fc.code,tree[c].dl.len);}#defined_code(dist)((dist)<256?state.ts.dist_code[dist]:state.ts.dist_code[256+((dist)>>7)])//Mappingfromadistancetoadistancecode.dististhedistance-1and//mustnothavesideeffects.dist_code[256]anddist_code[257]areneverused.#defineMax(a,b)(a>=b?a:b)/* the arguments must not have side effects *//*===========================================================================*Allocatethematchbuffer,initializethevarioustablesandsavethe*locationoftheinternalfileattribute(ascii/binary)andmethod*(DEFLATE/STORE).*/voidct_init(TState&state,ush*attr){intn;/* iterates over tree elements */intbits;/* bit counter */intlength;/* length value */intcode;/* code value */intdist;/* distance index */state.ts.file_type=attr;//state.ts.file_method=method;state.ts.cmpr_bytelen=state.ts.cmpr_len_bits=0L;state.ts.input_len=0L;if(state.ts.static_dtree[0].dl.len!=0)return;/* ct_init already called *//* Initialize the mapping length (0..255) -> length code (0..28) */length=0;for(code=0;code<LENGTH_CODES-1;code++){state.ts.base_length[code]=length;for(n=0;n<(1<<extra_lbits[code]);n++){state.ts.length_code[length++]=(uch)code;}}Assert(state,length==256,"ct_init: length != 256");/*Notethatthelength255(matchlength258)canberepresented*intwodifferentways:code284+5bitsorcode285,sowe*overwritelength_code[255]tousethebestencoding:*/state.ts.length_code[length-1]=(uch)code;/* Initialize the mapping dist (0..32K) -> dist code (0..29) */dist=0;for(code=0;code<16;code++){state.ts.base_dist[code]=dist;for(n=0;n<(1<<extra_dbits[code]);n++){state.ts.dist_code[dist++]=(uch)code;}}Assert(state,dist==256,"ct_init: dist != 256");dist>>=7;/* from now on, all distances are divided by 128 */for(;code<D_CODES;code++){state.ts.base_dist[code]=dist<<7;for(n=0;n<(1<<(extra_dbits[code]-7));n++){state.ts.dist_code[256+dist++]=(uch)code;}}Assert(state,dist==256,"ct_init: 256+dist != 512");/* Construct the codes of the static literal tree */for(bits=0;bits<=MAX_BITS;bits++)state.ts.bl_count[bits]=0;n=0;while(n<=143)state.ts.static_ltree[n++].dl.len=8,state.ts.bl_count[8]++;while(n<=255)state.ts.static_ltree[n++].dl.len=9,state.ts.bl_count[9]++;while(n<=279)state.ts.static_ltree[n++].dl.len=7,state.ts.bl_count[7]++;while(n<=287)state.ts.static_ltree[n++].dl.len=8,state.ts.bl_count[8]++;/*fc.codes286and287donotexist,butwemustincludetheminthe*treeconstructiontogetacanonicalHuffmantree(longestcode*allones)*/gen_codes(state,(ct_data*)state.ts.static_ltree,L_CODES+1);/* The static distance tree is trivial: */for(n=0;n<D_CODES;n++){state.ts.static_dtree[n].dl.len=5;state.ts.static_dtree[n].fc.code=(ush)bi_reverse(n,5);}/* Initialize the first block of the first file: */init_block(state);}/*===========================================================================*Initializeanewblock.*/voidinit_block(TState&state){intn;/* iterates over tree elements *//* Initialize the trees. */for(n=0;n<L_CODES;n++)state.ts.dyn_ltree[n].fc.freq=0;for(n=0;n<D_CODES;n++)state.ts.dyn_dtree[n].fc.freq=0;for(n=0;n<BL_CODES;n++)state.ts.bl_tree[n].fc.freq=0;state.ts.dyn_ltree[END_BLOCK].fc.freq=1;state.ts.opt_len=state.ts.static_len=0L;state.ts.last_lit=state.ts.last_dist=state.ts.last_flags=0;state.ts.flags=0;state.ts.flag_bit=1;}#defineSMALLEST1/* Index within the heap array of least frequent node in the Huffman tree *//*===========================================================================*Removethesmallestelementfromtheheapandrecreatetheheapwith*onelesselement.Updatesheapandheap_len.*/#definepqremove(tree,top)\{\top=state.ts.heap[SMALLEST];\state.ts.heap[SMALLEST]=state.ts.heap[state.ts.heap_len--];\pqdownheap(state,tree,SMALLEST);\}/*===========================================================================*Comparestosubtrees,usingthetreedepthastiebreakerwhen*thesubtreeshaveequalfrequency.Thisminimizestheworstcaselength.*/#definesmaller(tree,n,m)\(tree[n].fc.freq<tree[m].fc.freq||\(tree[n].fc.freq==tree[m].fc.freq&&state.ts.depth[n]<=state.ts.depth[m]))/*===========================================================================*Restoretheheappropertybymovingdownthetreestartingatnodek,*exchanginganodewiththesmallestofitstwosonsifnecessary,stopping*whentheheappropertyisre-established(eachfathersmallerthanits*twosons).*/voidpqdownheap(TState&state,ct_data*tree,intk){intv=state.ts.heap[k];intj=k<<1;/* left son of k */inthtemp;/* required because of bug in SASC compiler */while(j<=state.ts.heap_len){/* Set j to the smallest of the two sons: */if(j<state.ts.heap_len&&smaller(tree,state.ts.heap[j+1],state.ts.heap[j]))j++;/* Exit if v is smaller than both sons */htemp=state.ts.heap[j];if(smaller(tree,v,htemp))break;/* Exchange v with the smallest son */state.ts.heap[k]=htemp;k=j;/* And continue down the tree, setting j to the left son of k */j<<=1;}state.ts.heap[k]=v;}/*===========================================================================*Computetheoptimalbitlengthsforatreeandupdatethetotalbitlength*forthecurrentblock.*INassertion:thefieldsfreqanddadareset,heap[heap_max]and*abovearethetreenodessortedbyincreasingfrequency.*OUTassertions:thefieldlenissettotheoptimalbitlength,the*arraybl_countcontainsthefrequenciesforeachbitlength.*Thelengthopt_lenisupdated;static_lenisalsoupdatedifstreeis*notnull.*/voidgen_bitlen(TState&state,tree_desc*desc){ct_data*tree=desc->dyn_tree;constint*extra=desc->extra_bits;intbase=desc->extra_base;intmax_code=desc->max_code;intmax_length=desc->max_length;ct_data*stree=desc->static_tree;inth;/* heap index */intn,m;/* iterate over the tree elements */intbits;/* bit length */intxbits;/* extra bits */ushf;/* frequency */intoverflow=0;/* number of elements with bit length too large */for(bits=0;bits<=MAX_BITS;bits++)state.ts.bl_count[bits]=0;/*Inafirstpass,computetheoptimalbitlengths(whichmay*overflowinthecaseofthebitlengthtree).*/tree[state.ts.heap[state.ts.heap_max]].dl.len=0;/* root of the heap */for(h=state.ts.heap_max+1;h<HEAP_SIZE;h++){n=state.ts.heap[h];bits=tree[tree[n].dl.dad].dl.len+1;if(bits>max_length)bits=max_length,overflow++;tree[n].dl.len=(ush)bits;/* We overwrite tree[n].dl.dad which is no longer needed */if(n>max_code)continue;/* not a leaf node */state.ts.bl_count[bits]++;xbits=0;if(n>=base)xbits=extra[n-base];f=tree[n].fc.freq;state.ts.opt_len+=(ulg)f*(bits+xbits);if(stree)state.ts.static_len+=(ulg)f*(stree[n].dl.len+xbits);}if(overflow==0)return;Trace("\nbit length overflow\n");/* This happens for example on obj2 and pic of the Calgary corpus *//* Find the first bit length which could increase: */do{bits=max_length-1;while(state.ts.bl_count[bits]==0)bits--;state.ts.bl_count[bits]--;/* move one leaf down the tree */state.ts.bl_count[bits+1]+=(ush)2;/* move one overflow item as its brother */state.ts.bl_count[max_length]--;/*Thebrotheroftheoverflowitemalsomovesonestepup,*butthisdoesnotaffectbl_count[max_length]*/overflow-=2;}while(overflow>0);/*Nowrecomputeallbitlengths,scanninginincreasingfrequency.*hisstillequaltoHEAP_SIZE.(Itissimplertoreconstructall*lengthsinsteadoffixingonlythewrongones.Thisideaistaken*from'ar'writtenbyHaruhikoOkumura.)*/for(bits=max_length;bits!=0;bits--){n=state.ts.bl_count[bits];while(n!=0){m=state.ts.heap[--h];if(m>max_code)continue;if(tree[m].dl.len!=(ush)bits){Trace("code %d bits %d->%d\n",m,tree[m].dl.len,bits);state.ts.opt_len+=((long)bits-(long)tree[m].dl.len)*(long)tree[m].fc.freq;tree[m].dl.len=(ush)bits;}n--;}}}/*===========================================================================*Generatethecodesforagiventreeandbitcounts(whichneednotbe*optimal).*INassertion:thearraybl_countcontainsthebitlengthstatisticsfor*thegiventreeandthefieldlenissetforalltreeelements.*OUTassertion:thefieldcodeissetforalltreeelementsofnon*zerocodelength.*/voidgen_codes(TState&state,ct_data*tree,intmax_code){ushnext_code[MAX_BITS+1];/* next code value for each bit length */ushcode=0;/* running code value */intbits;/* bit index */intn;/* code index *//*Thedistributioncountsarefirstusedtogeneratethecodevalues*withoutbitreversal.*/for(bits=1;bits<=MAX_BITS;bits++){next_code[bits]=code=(ush)((code+state.ts.bl_count[bits-1])<<1);}/*Checkthatthebitcountsinbl_countareconsistent.Thelastcode*mustbeallones.*/Assert(state,code+state.ts.bl_count[MAX_BITS]-1==(1<<((ush)MAX_BITS))-1,"inconsistent bit counts");Trace("\ngen_codes: max_code %d ",max_code);for(n=0;n<=max_code;n++){intlen=tree[n].dl.len;if(len==0)continue;/* Now reverse the bits */tree[n].fc.code=(ush)bi_reverse(next_code[len]++,len);//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);}}/*===========================================================================*ConstructoneHuffmantreeandassignsthecodebitstringsandlengths.*Updatethetotalbitlengthforthecurrentblock.*INassertion:thefieldfreqissetforalltreeelements.*OUTassertions:thefieldslenandcodearesettotheoptimalbitlength*andcorrespondingcode.Thelengthopt_lenisupdated;static_lenis*alsoupdatedifstreeisnotnull.Thefieldmax_codeisset.*/voidbuild_tree(TState&state,tree_desc*desc){ct_data*tree=desc->dyn_tree;ct_data*stree=desc->static_tree;intelems=desc->elems;intn,m;/* iterate over heap elements */intmax_code=-1;/* largest code with non zero frequency */intnode=elems;/* next internal node of the tree *//*Constructtheinitialheap,withleastfrequentelementin*heap[SMALLEST].Thesonsofheap[n]areheap[2*n]andheap[2*n+1].*heap[0]isnotused.*/state.ts.heap_len=0,state.ts.heap_max=HEAP_SIZE;for(n=0;n<elems;n++){if(tree[n].fc.freq!=0){state.ts.heap[++state.ts.heap_len]=max_code=n;state.ts.depth[n]=0;}else{tree[n].dl.len=0;}}/*Thepkzipformatrequiresthatatleastonedistancecodeexists,*andthatatleastonebitshouldbesentevenifthereisonlyone*possiblecode.Sotoavoidspecialcheckslateronweforceatleast*twocodesofnonzerofrequency.*/while(state.ts.heap_len<2){intnewcp=state.ts.heap[++state.ts.heap_len]=(max_code<2?++max_code:0);tree[newcp].fc.freq=1;state.ts.depth[newcp]=0;state.ts.opt_len--;if(stree)state.ts.static_len-=stree[newcp].dl.len;/* new is 0 or 1 so it does not have extra bits */}desc->max_code=max_code;/*Theelementsheap[heap_len/2+1..heap_len]areleavesofthetree,*establishsub-heapsofincreasinglengths:*/for(n=state.ts.heap_len/2;n>=1;n--)pqdownheap(state,tree,n);/*ConstructtheHuffmantreebyrepeatedlycombiningtheleasttwo*frequentnodes.*/do{pqremove(tree,n);/* n = node of least frequency */m=state.ts.heap[SMALLEST];/* m = node of next least frequency */state.ts.heap[--state.ts.heap_max]=n;/* keep the nodes sorted by frequency */state.ts.heap[--state.ts.heap_max]=m;/* Create a new node father of n and m */tree[node].fc.freq=(ush)(tree[n].fc.freq+tree[m].fc.freq);state.ts.depth[node]=(uch)(Max(state.ts.depth[n],state.ts.depth[m])+1);tree[n].dl.dad=tree[m].dl.dad=(ush)node;/* and insert the new node in the heap */state.ts.heap[SMALLEST]=node++;pqdownheap(state,tree,SMALLEST);}while(state.ts.heap_len>=2);state.ts.heap[--state.ts.heap_max]=state.ts.heap[SMALLEST];/*Atthispoint,thefieldsfreqanddadareset.Wecannow*generatethebitlengths.*/gen_bitlen(state,(tree_desc*)desc);/* The field len is now set, we can generate the bit codes */gen_codes(state,(ct_data*)tree,max_code);}/*===========================================================================*Scanaliteralordistancetreetodeterminethefrequenciesofthecodes*inthebitlengthtree.Updatesopt_lentotakeintoaccounttherepeat*counts.(Thecontributionofthebitlengthcodeswillbeaddedlater*duringtheconstructionofbl_tree.)*/voidscan_tree(TState&state,ct_data*tree,intmax_code){intn;/* iterates over all tree elements */intprevlen=-1;/* last emitted length */intcurlen;/* length of current code */intnextlen=tree[0].dl.len;/* length of next code */intcount=0;/* repeat count of the current code */intmax_count=7;/* max repeat count */intmin_count=4;/* min repeat count */if(nextlen==0)max_count=138,min_count=3;tree[max_code+1].dl.len=(ush)-1;/* guard */for(n=0;n<=max_code;n++){curlen=nextlen;nextlen=tree[n+1].dl.len;if(++count<max_count&&curlen==nextlen){continue;}elseif(count<min_count){state.ts.bl_tree[curlen].fc.freq=(ush)(state.ts.bl_tree[curlen].fc.freq+count);}elseif(curlen!=0){if(curlen!=prevlen)state.ts.bl_tree[curlen].fc.freq++;state.ts.bl_tree[REP_3_6].fc.freq++;}elseif(count<=10){state.ts.bl_tree[REPZ_3_10].fc.freq++;}else{state.ts.bl_tree[REPZ_11_138].fc.freq++;}count=0;prevlen=curlen;if(nextlen==0){max_count=138,min_count=3;}elseif(curlen==nextlen){max_count=6,min_count=3;}else{max_count=7,min_count=4;}}}/*===========================================================================*Sendaliteralordistancetreeincompressedform,usingthecodesin*bl_tree.*/voidsend_tree(TState&state,ct_data*tree,intmax_code){intn;/* iterates over all tree elements */intprevlen=-1;/* last emitted length */intcurlen;/* length of current code */intnextlen=tree[0].dl.len;/* length of next code */intcount=0;/* repeat count of the current code */intmax_count=7;/* max repeat count */intmin_count=4;/* min repeat count *//* tree[max_code+1].dl.len = -1; *//* guard already set */if(nextlen==0)max_count=138,min_count=3;for(n=0;n<=max_code;n++){curlen=nextlen;nextlen=tree[n+1].dl.len;if(++count<max_count&&curlen==nextlen){continue;}elseif(count<min_count){do{send_code(state,curlen,state.ts.bl_tree);}while(--count!=0);}elseif(curlen!=0){if(curlen!=prevlen){send_code(state,curlen,state.ts.bl_tree);count--;}Assert(state,count>=3&&count<=6," 3_6?");send_code(state,REP_3_6,state.ts.bl_tree);send_bits(state,count-3,2);}elseif(count<=10){send_code(state,REPZ_3_10,state.ts.bl_tree);send_bits(state,count-3,3);}else{send_code(state,REPZ_11_138,state.ts.bl_tree);send_bits(state,count-11,7);}count=0;prevlen=curlen;if(nextlen==0){max_count=138,min_count=3;}elseif(curlen==nextlen){max_count=6,min_count=3;}else{max_count=7,min_count=4;}}}/*===========================================================================*ConstructtheHuffmantreeforthebitlengthsandreturntheindexin*bl_orderofthelastbitlengthcodetosend.*/intbuild_bl_tree(TState&state){intmax_blindex;/* index of last bit length code of non zero freq *//* Determine the bit length frequencies for literal and distance trees */scan_tree(state,(ct_data*)state.ts.dyn_ltree,state.ts.l_desc.max_code);scan_tree(state,(ct_data*)state.ts.dyn_dtree,state.ts.d_desc.max_code);/* Build the bit length tree: */build_tree(state,(tree_desc*)(&state.ts.bl_desc));/*opt_lennowincludesthelengthofthetreerepresentations,except*thelengthsofthebitlengthscodesandthe5+5+4bitsforthecounts.*//*Determinethenumberofbitlengthcodestosend.Thepkzipformat*requiresthatatleast4bitlengthcodesbesent.(appnote.txtsays*3buttheactualvalueusedis4.)*/for(max_blindex=BL_CODES-1;max_blindex>=3;max_blindex--){if(state.ts.bl_tree[bl_order[max_blindex]].dl.len!=0)break;}/* Update opt_len to include the bit length tree and counts */state.ts.opt_len+=3*(max_blindex+1)+5+5+4;Trace("\ndyn trees: dyn %ld, stat %ld",state.ts.opt_len,state.ts.static_len);returnmax_blindex;}/*===========================================================================*SendtheheaderforablockusingdynamicHuffmantrees:thecounts,the*lengthsofthebitlengthcodes,theliteraltreeandthedistancetree.*INassertion:lcodes>=257,dcodes>=1,blcodes>=4.*/voidsend_all_trees(TState&state,intlcodes,intdcodes,intblcodes){intrank;/* index in bl_order */Assert(state,lcodes>=257&&dcodes>=1&&blcodes>=4,"not enough codes");Assert(state,lcodes<=L_CODES&&dcodes<=D_CODES&&blcodes<=BL_CODES,"too many codes");Trace("\nbl counts: ");send_bits(state,lcodes-257,5);/* not +255 as stated in appnote.txt 1.93a or -256 in 2.04c */send_bits(state,dcodes-1,5);send_bits(state,blcodes-4,4);/* not -3 as stated in appnote.txt */for(rank=0;rank<blcodes;rank++){Trace("\nbl code %2d ",bl_order[rank]);send_bits(state,state.ts.bl_tree[bl_order[rank]].dl.len,3);}Trace("\nbl tree: sent %ld",state.bs.bits_sent);send_tree(state,(ct_data*)state.ts.dyn_ltree,lcodes-1);/* send the literal tree */Trace("\nlit tree: sent %ld",state.bs.bits_sent);send_tree(state,(ct_data*)state.ts.dyn_dtree,dcodes-1);/* send the distance tree */Trace("\ndist tree: sent %ld",state.bs.bits_sent);}/*===========================================================================*Determinethebestencodingforthecurrentblock:dynamictrees,static*treesorstore,andoutputtheencodedblocktothezipfile.Thisfunction*returnsthetotalcompressedlength(inbytes)forthefilesofar.*/ulgflush_block(TState&state,char*buf,ulgstored_len,inteof){ulgopt_lenb,static_lenb;/* opt_len and static_len in bytes */intmax_blindex;/* index of last bit length code of non zero freq */state.ts.flag_buf[state.ts.last_flags]=state.ts.flags;/* Save the flags for the last 8 items *//* Check if the file is ascii or binary */if(*state.ts.file_type==(ush)UNKNOWN)set_file_type(state);/* Construct the literal and distance trees */build_tree(state,(tree_desc*)(&state.ts.l_desc));Trace("\nlit data: dyn %ld, stat %ld",state.ts.opt_len,state.ts.static_len);build_tree(state,(tree_desc*)(&state.ts.d_desc));Trace("\ndist data: dyn %ld, stat %ld",state.ts.opt_len,state.ts.static_len);/*Atthispoint,opt_lenandstatic_lenarethetotalbitlengthsof*thecompressedblockdata,excludingthetreerepresentations.*//*Buildthebitlengthtreefortheabovetwotrees,andgettheindex*inbl_orderofthelastbitlengthcodetosend.*/max_blindex=build_bl_tree(state);/* Determine the best encoding. Compute first the block length in bytes */opt_lenb=(state.ts.opt_len+3+7)>>3;static_lenb=(state.ts.static_len+3+7)>>3;state.ts.input_len+=stored_len;/* for debugging only */Trace("\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u dist %u ",opt_lenb,state.ts.opt_len,static_lenb,state.ts.static_len,stored_len,state.ts.last_lit,state.ts.last_dist);if(static_lenb<=opt_lenb)opt_lenb=static_lenb;//Originally,zipallowedthefiletobetransformedfromacompressed//intoastoredfileinthecasewherecompressionfailed,there//wasonlyoneblock,anditwasallowedtochange.I'veremovedthis//possibilitysincethecode'scleanerifnochangesareallowed.//if(stored_len<=opt_lenb&&eof&&state.ts.cmpr_bytelen==0L//&&state.ts.cmpr_len_bits==0L&&state.seekable)//{//&&state.ts.file_method!=NULL////SinceLIT_BUFSIZE<=2*WSIZE,theinputdatamustbethere://Assert(state,buf!=NULL,"block vanished");//copy_block(state,buf,(unsigned)stored_len,0);//withoutheader//state.ts.cmpr_bytelen=stored_len;//Assert(state,false,"unimplemented *state.ts.file_method = STORE;");////*state.ts.file_method=STORE;//}//elseif(stored_len+4<=opt_lenb&&buf!=(char*)NULL){/* 4: two words for the lengths *//*Thetestbuf!=NULLisonlynecessaryifLIT_BUFSIZE>WSIZE.*Otherwisewecan'thaveprocessedmorethanWSIZEinputbytessince*thelastblockflush,becausecompressionwouldhavebeen*successful.IfLIT_BUFSIZE<=WSIZE,itisnevertoolateto*transformablockintoastoredblock.*/send_bits(state,(STORED_BLOCK<<1)+eof,3);/* send block type */state.ts.cmpr_bytelen+=((state.ts.cmpr_len_bits+3+7)>>3)+stored_len+4;state.ts.cmpr_len_bits=0L;copy_block(state,buf,(unsigned)stored_len,1);/* with header */}elseif(static_lenb==opt_lenb){send_bits(state,(STATIC_TREES<<1)+eof,3);compress_block(state,(ct_data*)state.ts.static_ltree,(ct_data*)state.ts.static_dtree);state.ts.cmpr_len_bits+=3+state.ts.static_len;state.ts.cmpr_bytelen+=state.ts.cmpr_len_bits>>3;state.ts.cmpr_len_bits&=7L;}else{send_bits(state,(DYN_TREES<<1)+eof,3);send_all_trees(state,state.ts.l_desc.max_code+1,state.ts.d_desc.max_code+1,max_blindex+1);compress_block(state,(ct_data*)state.ts.dyn_ltree,(ct_data*)state.ts.dyn_dtree);state.ts.cmpr_len_bits+=3+state.ts.opt_len;state.ts.cmpr_bytelen+=state.ts.cmpr_len_bits>>3;state.ts.cmpr_len_bits&=7L;}Assert(state,((state.ts.cmpr_bytelen<<3)+state.ts.cmpr_len_bits)==state.bs.bits_sent,"bad compressed size");init_block(state);if(eof){//Assert(state,input_len==isize,"bad input size");bi_windup(state);state.ts.cmpr_len_bits+=7;/* align on byte boundary */}Trace("\n");returnstate.ts.cmpr_bytelen+(state.ts.cmpr_len_bits>>3);}/*===========================================================================*Savethematchinfoandtallythefrequencycounts.Returntrueif*thecurrentblockmustbeflushed.*/intct_tally(TState&state,intdist,intlc){state.ts.l_buf[state.ts.last_lit++]=(uch)lc;if(dist==0){/* lc is the unmatched char */state.ts.dyn_ltree[lc].fc.freq++;}else{/* Here, lc is the match length - MIN_MATCH */dist--;/* dist = match distance - 1 */Assert(state,(ush)dist<(ush)MAX_DIST&&(ush)lc<=(ush)(MAX_MATCH-MIN_MATCH)&&(ush)d_code(dist)<(ush)D_CODES,"ct_tally: bad match");state.ts.dyn_ltree[state.ts.length_code[lc]+LITERALS+1].fc.freq++;state.ts.dyn_dtree[d_code(dist)].fc.freq++;state.ts.d_buf[state.ts.last_dist++]=(ush)dist;state.ts.flags|=state.ts.flag_bit;}state.ts.flag_bit<<=1;/* Output the flags if they fill a byte: */if((state.ts.last_lit&7)==0){state.ts.flag_buf[state.ts.last_flags++]=state.ts.flags;state.ts.flags=0,state.ts.flag_bit=1;}/* Try to guess if it is profitable to stop the current block here */if(state.level>2&&(state.ts.last_lit&0xfff)==0){/* Compute an upper bound for the compressed length */ulgout_length=(ulg)state.ts.last_lit*8L;ulgin_length=(ulg)state.ds.strstart-state.ds.block_start;intdcode;for(dcode=0;dcode<D_CODES;dcode++){out_length+=(ulg)state.ts.dyn_dtree[dcode].fc.freq*(5L+extra_dbits[dcode]);}out_length>>=3;Trace("\nlast_lit %u, last_dist %u, in %ld, out ~%ld(%ld%%) ",state.ts.last_lit,state.ts.last_dist,in_length,out_length,100L-out_length*100L/in_length);if(state.ts.last_dist<state.ts.last_lit/2&&out_length<in_length/2)return1;}return(state.ts.last_lit==LIT_BUFSIZE-1||state.ts.last_dist==DIST_BUFSIZE);/*WeavoidequalitywithLIT_BUFSIZEbecauseofwraparoundat64K*on16bitmachinesandbecausestoredblocksarerestrictedto*64K-1bytes.*/}/*===========================================================================*SendtheblockdatacompressedusingthegivenHuffmantrees*/voidcompress_block(TState&state,ct_data*ltree,ct_data*dtree){unsigneddist;/* distance of matched string */intlc;/* match length or unmatched char (if dist == 0) */unsignedlx=0;/* running index in l_buf */unsigneddx=0;/* running index in d_buf */unsignedfx=0;/* running index in flag_buf */uchflag=0;/* current flags */unsignedcode;/* the code to send */intextra;/* number of extra bits to send */if(state.ts.last_lit!=0)do{if((lx&7)==0)flag=state.ts.flag_buf[fx++];lc=state.ts.l_buf[lx++];if((flag&1)==0){send_code(state,lc,ltree);/* send a literal byte */}else{/* Here, lc is the match length - MIN_MATCH */code=state.ts.length_code[lc];send_code(state,code+LITERALS+1,ltree);/* send the length code */extra=extra_lbits[code];if(extra!=0){lc-=state.ts.base_length[code];send_bits(state,lc,extra);/* send the extra length bits */}dist=state.ts.d_buf[dx++];/* Here, dist is the match distance - 1 */code=d_code(dist);Assert(state,code<D_CODES,"bad d_code");send_code(state,code,dtree);/* send the distance code */extra=extra_dbits[code];if(extra!=0){dist-=state.ts.base_dist[code];send_bits(state,dist,extra);/* send the extra distance bits */}}/* literal or match pair ? */flag>>=1;}while(lx<state.ts.last_lit);send_code(state,END_BLOCK,ltree);}/*===========================================================================*SetthefiletypetoASCIIorBINARY,usingacrudeapproximation:*binaryifmorethan20%ofthebytesare<=6or>=128,asciiotherwise.*INassertion:thefieldsfreqofdyn_ltreearesetandthetotalofall*frequenciesdoesnotexceed64K(tofitinaninton16bitmachines).*/voidset_file_type(TState&state){intn=0;unsignedascii_freq=0;unsignedbin_freq=0;while(n<7)bin_freq+=state.ts.dyn_ltree[n++].fc.freq;while(n<128)ascii_freq+=state.ts.dyn_ltree[n++].fc.freq;while(n<LITERALS)bin_freq+=state.ts.dyn_ltree[n++].fc.freq;*state.ts.file_type=(ush)(bin_freq>(ascii_freq>>2)?BINARY:ASCII);}/*===========================================================================*Initializethebitstringroutines.*/voidbi_init(TState&state,char*tgt_buf,unsignedtgt_size,intflsh_allowed){state.bs.out_buf=tgt_buf;state.bs.out_size=tgt_size;state.bs.out_offset=0;state.bs.flush_flg=flsh_allowed;state.bs.bi_buf=0;state.bs.bi_valid=0;state.bs.bits_sent=0L;}/*===========================================================================*Sendavalueonagivennumberofbits.*INassertion:length<=16andvaluefitsinlengthbits.*/voidsend_bits(TState&state,intvalue,intlength){Assert(state,length>0&&length<=15,"invalid length");state.bs.bits_sent+=(ulg)length;/*Ifnotenoughroominbi_buf,use(bi_valid)bitsfrombi_bufand*(Buf_size-bi_valid)bitsfromvaluetoflushthefilledbi_buf,*thenfillintherestof(value),leaving(length-(Buf_size-bi_valid))*unusedbitsinbi_buf.*/state.bs.bi_buf|=(value<<state.bs.bi_valid);state.bs.bi_valid+=length;if(state.bs.bi_valid>(int)Buf_size){PUTSHORT(state,state.bs.bi_buf);state.bs.bi_valid-=Buf_size;state.bs.bi_buf=(unsigned)value>>(length-state.bs.bi_valid);}}/*===========================================================================*Reversethefirstlenbitsofacode,usingstraightforwardcode(afaster*methodwoulduseatable)*INassertion:1<=len<=15*/unsignedbi_reverse(unsignedcode,intlen){registerunsignedres=0;do{res|=code&1;code>>=1,res<<=1;}while(--len>0);returnres>>1;}/*===========================================================================*Writeoutanyremainingbitsinanincompletebyte.*/voidbi_windup(TState&state){if(state.bs.bi_valid>8){PUTSHORT(state,state.bs.bi_buf);}elseif(state.bs.bi_valid>0){PUTBYTE(state,state.bs.bi_buf);}if(state.bs.flush_flg){state.flush_outbuf(state.param,state.bs.out_buf,&state.bs.out_offset);}state.bs.bi_buf=0;state.bs.bi_valid=0;state.bs.bits_sent=(state.bs.bits_sent+7)&~7;}/*===========================================================================*Copyastoredblocktothezipfile,storingfirstthelengthandits*one'scomplementifrequested.*/voidcopy_block(TState&state,char*block,unsignedlen,intheader){bi_windup(state);/* align on byte boundary */if(header){PUTSHORT(state,(ush)len);PUTSHORT(state,(ush)~len);state.bs.bits_sent+=2*16;}if(state.bs.flush_flg){state.flush_outbuf(state.param,state.bs.out_buf,&state.bs.out_offset);state.bs.out_offset=len;state.flush_outbuf(state.param,block,&state.bs.out_offset);}elseif(state.bs.out_offset+len>state.bs.out_size){Assert(state,false,"output buffer too small for in-memory compression");}else{memcpy(state.bs.out_buf+state.bs.out_offset,block,len);state.bs.out_offset+=len;}state.bs.bits_sent+=(ulg)len<<3;}/*===========================================================================*Prototypesforfunctions.*/voidfill_window(TState&state);ulgdeflate_fast(TState&state);intlongest_match(TState&state,IPoscur_match);/*===========================================================================*Updateahashvaluewiththegiveninputbyte*INassertion:allcallstotoUPDATE_HASHaremadewithconsecutive*inputcharacters,sothatarunninghashkeycanbecomputedfromthe*previouskeyinsteadofcompleterecalculationeachtime.*/#defineUPDATE_HASH(h,c)(h=(((h)<<H_SHIFT)^(c))&HASH_MASK)/*===========================================================================*Insertstringsinthedictionaryandsetmatch_headtotheprevioushead*ofthehashchain(themostrecentstringwithsamehashkey).Return*thepreviouslengthofthehashchain.*INassertion:allcallstotoINSERT_STRINGaremadewithconsecutive*inputcharactersandthefirstMIN_MATCHbytesofsarevalid*(exceptforthelastMIN_MATCH-1bytesoftheinputfile).*/#defineINSERT_STRING(s,match_head)\(UPDATE_HASH(state.ds.ins_h,state.ds.window[(s)+(MIN_MATCH-1)]),\state.ds.prev[(s)&WMASK]=match_head=state.ds.head[state.ds.ins_h],\state.ds.head[state.ds.ins_h]=(s))/*===========================================================================*Initializethe"longest match"routinesforanewfile**INassertion:window_sizeis>0iftheinputfileisalreadyreador*mmap'edinthewindow[]array,0otherwise.Inthefirstcase,*window_sizeissufficienttocontainthewholeinputfileplus*MIN_LOOKAHEADbytes(toavoidreferencingmemorybeyondtheend*ofwindow[]whenlookingformatchestowardstheend).*/voidlm_init(TState&state,intpack_level,ush*flags){registerunsignedj;Assert(state,pack_level>=1&&pack_level<=8,"bad pack level");/*Donotslidethewindowifthewholeinputisalreadyinmemory*(window_size>0)*/state.ds.sliding=0;if(state.ds.window_size==0L){state.ds.sliding=1;state.ds.window_size=(ulg)2L*WSIZE;}/*Initializethehashtable(avoiding64Koverflowfor16bitsystems).*prev[]willbeinitializedonthefly.*/state.ds.head[HASH_SIZE-1]=NIL;memset((char*)state.ds.head,NIL,(unsigned)(HASH_SIZE-1)*sizeof(*state.ds.head));/*Setthedefaultconfigurationparameters:*/state.ds.max_lazy_match=configuration_table[pack_level].max_lazy;state.ds.good_match=configuration_table[pack_level].good_length;state.ds.nice_match=configuration_table[pack_level].nice_length;state.ds.max_chain_length=configuration_table[pack_level].max_chain;if(pack_level<=2){*flags|=FAST;}elseif(pack_level>=8){*flags|=SLOW;}/* ??? reduce max_chain_length for binary files */state.ds.strstart=0;state.ds.block_start=0L;j=WSIZE;j<<=1;//Canread64Kinonestepstate.ds.lookahead=state.readfunc(state,(char*)state.ds.window,j);if(state.ds.lookahead==0||state.ds.lookahead==(unsigned)EOF){state.ds.eofile=1,state.ds.lookahead=0;return;}state.ds.eofile=0;/*Makesurethatwealwayshaveenoughlookahead.Thisisimportant*ifinputcomesfromadevicesuchasatty.*/if(state.ds.lookahead<MIN_LOOKAHEAD)fill_window(state);state.ds.ins_h=0;for(j=0;j<MIN_MATCH-1;j++)UPDATE_HASH(state.ds.ins_h,state.ds.window[j]);/*Iflookahead<MIN_MATCH,ins_hisgarbage,butthisis*notimportantsinceonlyliteralbyteswillbeemitted.*/}/*===========================================================================*Setmatch_starttothelongestmatchstartingatthegivenstringand*returnitslength.Matchesshorterorequaltoprev_lengtharediscarded,*inwhichcasetheresultisequaltoprev_lengthandmatch_startis*garbage.*INassertions:cur_matchistheheadofthehashchainforthecurrent*string(strstart)anditsdistanceis<=MAX_DIST,andprev_length>=1*///For80x86and680x0andARM,anoptimizedversionisinmatch.asmor//match.S.Thecodeisfunctionallyequivalent,soyoucanusetheCversion//ifdesired.WhichIdosodesire!intlongest_match(TState&state,IPoscur_match){unsignedchain_length=state.ds.max_chain_length;/* max hash chain length */registeruchfar*scan=state.ds.window+state.ds.strstart;/* current string */registeruchfar*match;/* matched string */registerintlen;/* length of current match */intbest_len=state.ds.prev_length;/* best match length so far */IPoslimit=state.ds.strstart>(IPos)MAX_DIST?state.ds.strstart-(IPos)MAX_DIST:NIL;/*Stopwhencur_matchbecomes<=limit.Tosimplifythecode,*wepreventmatcheswiththestringofwindowindex0.*///ThecodeisoptimizedforHASH_BITS>=8andMAX_MATCH-2multipleof16.//Itiseasytogetridofthisoptimizationifnecessary.Assert(state,HASH_BITS>=8&&MAX_MATCH==258,"Code too clever");registeruchfar*strend=state.ds.window+state.ds.strstart+MAX_MATCH;registeruchscan_end1=scan[best_len-1];registeruchscan_end=scan[best_len];/* Do not waste too much time if we already have a good match: */if(state.ds.prev_length>=state.ds.good_match){chain_length>>=2;}Assert(state,state.ds.strstart<=state.ds.window_size-MIN_LOOKAHEAD,"insufficient lookahead");do{Assert(state,cur_match<state.ds.strstart,"no future");match=state.ds.window+cur_match;/*Skiptonextmatchifthematchlengthcannotincrease*orifthematchlengthislessthan2:*/if(match[best_len]!=scan_end||match[best_len-1]!=scan_end1||*match!=*scan||*++match!=scan[1])continue;/*Thecheckatbest_len-1canberemovedbecauseitwillbemade*againlater.(Thisheuristicisnotalwaysawin.)*Itisnotnecessarytocomparescan[2]andmatch[2]sincethey*arealwaysequalwhentheotherbytesmatch,giventhat*thehashkeysareequalandthatHASH_BITS>=8.*/scan+=2,match++;/*Wecheckforinsufficientlookaheadonlyevery8thcomparison;*the256thcheckwillbemadeatstrstart+258.*/do{}while(*++scan==*++match&&*++scan==*++match&&*++scan==*++match&&*++scan==*++match&&*++scan==*++match&&*++scan==*++match&&*++scan==*++match&&*++scan==*++match&&scan<strend);Assert(state,scan<=state.ds.window+(unsigned)(state.ds.window_size-1),"wild scan");len=MAX_MATCH-(int)(strend-scan);scan=strend-MAX_MATCH;if(len>best_len){state.ds.match_start=cur_match;best_len=len;if(len>=state.ds.nice_match)break;scan_end1=scan[best_len-1];scan_end=scan[best_len];}}while((cur_match=state.ds.prev[cur_match&WMASK])>limit&&--chain_length!=0);returnbest_len;}#definecheck_match(state,start,match,length)//oralternatively...//voidcheck_match(TState&state,IPosstart,IPosmatch,intlength)//{//checkthatthematchisindeedamatch//if(memcmp((char*)state.ds.window+match,//(char*)state.ds.window+start,length)!=EQUAL){//fprintf(stderr,//" start %d, match %d, length %d\n",//start,match,length);//error("invalid match");//}//if(state.verbose>1){//fprintf(stderr,"\\[%d,%d]",start-match,length);//do{fprintf(stdout,"%c",state.ds.window[start++]);}while(--length!=0);//}//}/*===========================================================================*Fillthewindowwhenthelookaheadbecomesinsufficient.*Updatesstrstartandlookahead,andsetseofileifendofinputfile.**INassertion:lookahead<MIN_LOOKAHEAD&&strstart+lookahead>0*OUTassertions:strstart<=window_size-MIN_LOOKAHEAD*Atleastonebytehasbeenread,oreofileisset;filereadsare*performedforatleasttwobytes(requiredforthetranslate_eoloption).*/voidfill_window(TState&state){registerunsignedn,m;unsignedmore;/* Amount of free space at the end of the window. */do{more=(unsigned)(state.ds.window_size-(ulg)state.ds.lookahead-(ulg)state.ds.strstart);/*Ifthewindowisalmostfullandthereisinsufficientlookahead,*movetheupperhalftotheloweronetomakeroomintheupperhalf.*/if(more==(unsigned)EOF){/*Veryunlikely,butpossibleon16bitmachineifstrstart==0*andlookahead==1(inputdoneonebyteattime)*/more--;/*ForMMAPorBIG_MEM,thewholeinputfileisalreadyinmemoryso*wemustnotperformsliding.Wemusthowevercall(*read_buf)()in*ordertocomputethecrc,updatelookaheadandpossiblyseteofile.*/}elseif(state.ds.strstart>=WSIZE+MAX_DIST&&state.ds.sliding){/*BytheINassertion,thewindowisnotemptysowecan'tconfuse*more==0withmore==64Kona16bitmachine.*/memcpy((char*)state.ds.window,(char*)state.ds.window+WSIZE,(unsigned)WSIZE);state.ds.match_start-=WSIZE;state.ds.strstart-=WSIZE;/* we now have strstart >= MAX_DIST: */state.ds.block_start-=(long)WSIZE;for(n=0;n<HASH_SIZE;n++){m=state.ds.head[n];state.ds.head[n]=(Pos)(m>=WSIZE?m-WSIZE:NIL);}for(n=0;n<WSIZE;n++){m=state.ds.prev[n];state.ds.prev[n]=(Pos)(m>=WSIZE?m-WSIZE:NIL);/*Ifnisnotonanyhashchain,prev[n]isgarbagebut*itsvaluewillneverbeused.*/}more+=WSIZE;}if(state.ds.eofile)return;/*Iftherewasnosliding:*strstart<=WSIZE+MAX_DIST-1&&lookahead<=MIN_LOOKAHEAD-1&&*more==window_size-lookahead-strstart*=>more>=window_size-(MIN_LOOKAHEAD-1+WSIZE+MAX_DIST-1)*=>more>=window_size-2*WSIZE+2*IntheMMAPorBIG_MEMcase(notyetsupportedingzip),*window_size==input_size+MIN_LOOKAHEAD&&*strstart+lookahead<=input_size=>more>=MIN_LOOKAHEAD.*Otherwise,window_size==2*WSIZEsomore>=2.*Iftherewassliding,more>=WSIZE.Soinallcases,more>=2.*/Assert(state,more>=2,"more < 2");n=state.readfunc(state,(char*)state.ds.window+state.ds.strstart+state.ds.lookahead,more);if(n==0||n==(unsigned)EOF){state.ds.eofile=1;}else{state.ds.lookahead+=n;}}while(state.ds.lookahead<MIN_LOOKAHEAD&&!state.ds.eofile);}/*===========================================================================*Flushthecurrentblock,withgivenend-of-fileflag.*INassertion:strstartissettotheendofthecurrentmatch.*/#defineFLUSH_BLOCK(state,eof)\flush_block(state,state.ds.block_start>=0L?(char*)&state.ds.window[(unsigned)state.ds.block_start]:\(char*)NULL,(long)state.ds.strstart-state.ds.block_start,(eof))/*===========================================================================*Processesanewinputfileandreturnitscompressedlength.This*functiondoesnotperformlazyevaluationofmatchesandinserts*newstringsinthedictionaryonlyforunmatchedstringsorforshort*matches.Itisusedonlyforthefastcompressionoptions.*/ulgdeflate_fast(TState&state){IPoshash_head=NIL;/* head of the hash chain */intflush;/* set if current block must be flushed */unsignedmatch_length=0;/* length of best match */state.ds.prev_length=MIN_MATCH-1;while(state.ds.lookahead!=0){/*Insertthestringwindow[strstart..strstart+2]inthe*dictionary,andsethash_headtotheheadofthehashchain:*/if(state.ds.lookahead>=MIN_MATCH)INSERT_STRING(state.ds.strstart,hash_head);/*Findthelongestmatch,discardingthose<=prev_length.*Atthispointwehavealwaysmatch_length<MIN_MATCH*/if(hash_head!=NIL&&state.ds.strstart-hash_head<=MAX_DIST){/*Tosimplifythecode,wepreventmatcheswiththestring*ofwindowindex0(inparticularwehavetoavoidamatch*ofthestringwithitselfatthestartoftheinputfile).*//*Donotlookformatchesbeyondtheendoftheinput.*Thisisnecessarytomakedeflatedeterministic.*/if((unsigned)state.ds.nice_match>state.ds.lookahead)state.ds.nice_match=(int)state.ds.lookahead;match_length=longest_match(state,hash_head);/* longest_match() sets match_start */if(match_length>state.ds.lookahead)match_length=state.ds.lookahead;}if(match_length>=MIN_MATCH){check_match(state,state.ds.strstart,state.ds.match_start,match_length);flush=ct_tally(state,state.ds.strstart-state.ds.match_start,match_length-MIN_MATCH);state.ds.lookahead-=match_length;/*Insertnewstringsinthehashtableonlyifthematchlength*isnottoolarge.Thissavestimebutdegradescompression.*/if(match_length<=state.ds.max_insert_length&&state.ds.lookahead>=MIN_MATCH){match_length--;/* string at strstart already in hash table */do{state.ds.strstart++;INSERT_STRING(state.ds.strstart,hash_head);/*strstartneverexceedsWSIZE-MAX_MATCH,sothereare*alwaysMIN_MATCHbytesahead.*/}while(--match_length!=0);state.ds.strstart++;}else{state.ds.strstart+=match_length;match_length=0;state.ds.ins_h=state.ds.window[state.ds.strstart];UPDATE_HASH(state.ds.ins_h,state.ds.window[state.ds.strstart+1]);Assert(state,MIN_MATCH==3,"Call UPDATE_HASH() MIN_MATCH-3 more times");}}else{/* No match, output a literal byte */flush=ct_tally(state,0,state.ds.window[state.ds.strstart]);state.ds.lookahead--;state.ds.strstart++;}if(flush)FLUSH_BLOCK(state,0),state.ds.block_start=state.ds.strstart;/*Makesurethatwealwayshaveenoughlookahead,except*attheendoftheinputfile.WeneedMAX_MATCHbytes*forthenextmatch,plusMIN_MATCHbytestoinsertthe*stringfollowingthenextmatch.*/if(state.ds.lookahead<MIN_LOOKAHEAD)fill_window(state);}returnFLUSH_BLOCK(state,1);/* eof */}/*===========================================================================*Sameasabove,butachievesbettercompression.Weusealazy*evaluationformatches:amatchisfinallyadoptedonlyifthereis*nobettermatchatthenextwindowposition.*/ulgdeflate(TState&state){IPoshash_head=NIL;/* head of hash chain */IPosprev_match;/* previous match */intflush;/* set if current block must be flushed */intmatch_available=0;/* set if previous match exists */registerunsignedmatch_length=MIN_MATCH-1;/* length of best match */if(state.level<=3)returndeflate_fast(state);/* optimized for speed *//* Process the input block. */while(state.ds.lookahead!=0){/*Insertthestringwindow[strstart..strstart+2]inthe*dictionary,andsethash_headtotheheadofthehashchain:*/if(state.ds.lookahead>=MIN_MATCH)INSERT_STRING(state.ds.strstart,hash_head);/*Findthelongestmatch,discardingthose<=prev_length.*/state.ds.prev_length=match_length,prev_match=state.ds.match_start;match_length=MIN_MATCH-1;if(hash_head!=NIL&&state.ds.prev_length<state.ds.max_lazy_match&&state.ds.strstart-hash_head<=MAX_DIST){/*Tosimplifythecode,wepreventmatcheswiththestring*ofwindowindex0(inparticularwehavetoavoidamatch*ofthestringwithitselfatthestartoftheinputfile).*//*Donotlookformatchesbeyondtheendoftheinput.*Thisisnecessarytomakedeflatedeterministic.*/if((unsigned)state.ds.nice_match>state.ds.lookahead)state.ds.nice_match=(int)state.ds.lookahead;match_length=longest_match(state,hash_head);/* longest_match() sets match_start */if(match_length>state.ds.lookahead)match_length=state.ds.lookahead;/* Ignore a length 3 match if it is too distant: */if(match_length==MIN_MATCH&&state.ds.strstart-state.ds.match_start>TOO_FAR){/*Ifprev_matchisalsoMIN_MATCH,match_startisgarbage*butwewillignorethecurrentmatchanyway.*/match_length=MIN_MATCH-1;}}/*Iftherewasamatchatthepreviousstepandthecurrent*matchisnotbetter,outputthepreviousmatch:*/if(state.ds.prev_length>=MIN_MATCH&&match_length<=state.ds.prev_length){unsignedmax_insert=state.ds.strstart+state.ds.lookahead-MIN_MATCH;check_match(state,state.ds.strstart-1,prev_match,state.ds.prev_length);flush=ct_tally(state,state.ds.strstart-1-prev_match,state.ds.prev_length-MIN_MATCH);/*Insertinhashtableallstringsuptotheendofthematch.*strstart-1andstrstartarealreadyinserted.*/state.ds.lookahead-=state.ds.prev_length-1;state.ds.prev_length-=2;do{if(++state.ds.strstart<=max_insert){INSERT_STRING(state.ds.strstart,hash_head);/*strstartneverexceedsWSIZE-MAX_MATCH,sothereare*alwaysMIN_MATCHbytesahead.*/}}while(--state.ds.prev_length!=0);state.ds.strstart++;match_available=0;match_length=MIN_MATCH-1;if(flush)FLUSH_BLOCK(state,0),state.ds.block_start=state.ds.strstart;}elseif(match_available){/*Iftherewasnomatchatthepreviousposition,outputa*singleliteral.Iftherewasamatchbutthecurrentmatch*islonger,truncatethepreviousmatchtoasingleliteral.*/if(ct_tally(state,0,state.ds.window[state.ds.strstart-1])){FLUSH_BLOCK(state,0),state.ds.block_start=state.ds.strstart;}state.ds.strstart++;state.ds.lookahead--;}else{/*Thereisnopreviousmatchtocomparewith,waitfor*thenextsteptodecide.*/match_available=1;state.ds.strstart++;state.ds.lookahead--;}//Assert(state,strstart<=isize&&lookahead<=isize,"a bit too far");/*Makesurethatwealwayshaveenoughlookahead,except*attheendoftheinputfile.WeneedMAX_MATCHbytes*forthenextmatch,plusMIN_MATCHbytestoinsertthe*stringfollowingthenextmatch.*/if(state.ds.lookahead<MIN_LOOKAHEAD)fill_window(state);}if(match_available)ct_tally(state,0,state.ds.window[state.ds.strstart-1]);returnFLUSH_BLOCK(state,1);/* eof */}intputlocal(structzlistfar*z,WRITEFUNCwfunc,void*param){//Writealocalheaderdescribedby*ztofile*f.ReturnaZE_errorcode.PUTLG(LOCSIG,f);PUTSH(z->ver,f);PUTSH(z->lflg,f);PUTSH(z->how,f);PUTLG(z->tim,f);PUTLG(z->crc,f);PUTLG(z->siz,f);PUTLG(z->len,f);PUTSH(z->nam,f);PUTSH(z->ext,f);size_tres=(size_t)wfunc(param,z->iname,(unsignedint)z->nam);if(res!=z->nam)returnZE_TEMP;if(z->ext){res=(size_t)wfunc(param,z->extra,(unsignedint)z->ext);if(res!=z->ext)returnZE_TEMP;}returnZE_OK;}intputextended(structzlistfar*z,WRITEFUNCwfunc,void*param){//Writeanextendedlocalheaderdescribedby*ztofile*f.ReturnsaZE_codePUTLG(EXTLOCSIG,f);PUTLG(z->crc,f);PUTLG(z->siz,f);PUTLG(z->len,f);returnZE_OK;}intputcentral(structzlistfar*z,WRITEFUNCwfunc,void*param){//Writeacentralheaderentryof*ztofile*f.ReturnsaZE_code.PUTLG(CENSIG,f);PUTSH(z->vem,f);PUTSH(z->ver,f);PUTSH(z->flg,f);PUTSH(z->how,f);PUTLG(z->tim,f);PUTLG(z->crc,f);PUTLG(z->siz,f);PUTLG(z->len,f);PUTSH(z->nam,f);PUTSH(z->cext,f);PUTSH(z->com,f);PUTSH(z->dsk,f);PUTSH(z->att,f);PUTLG(z->atx,f);PUTLG(z->off,f);if((size_t)wfunc(param,z->iname,(unsignedint)z->nam)!=z->nam||(z->cext&&(size_t)wfunc(param,z->cextra,(unsignedint)z->cext)!=z->cext)||(z->com&&(size_t)wfunc(param,z->comment,(unsignedint)z->com)!=z->com))returnZE_TEMP;returnZE_OK;}intputend(intn,ulgs,ulgc,extentm,char*z,WRITEFUNCwfunc,void*param){//writetheendofthecentral-directory-datatofile*f.PUTLG(ENDSIG,f);PUTSH(0,f);PUTSH(0,f);PUTSH(n,f);PUTSH(n,f);PUTLG(s,f);PUTLG(c,f);PUTSH(m,f);//Writethecomment,ifanyif(m&&wfunc(param,z,(unsignedint)m)!=m)returnZE_TEMP;returnZE_OK;}constulgcrc_table[256]={0x00000000L,0x77073096L,0xee0e612cL,0x990951baL,0x076dc419L,0x706af48fL,0xe963a535L,0x9e6495a3L,0x0edb8832L,0x79dcb8a4L,0xe0d5e91eL,0x97d2d988L,0x09b64c2bL,0x7eb17cbdL,0xe7b82d07L,0x90bf1d91L,0x1db71064L,0x6ab020f2L,0xf3b97148L,0x84be41deL,0x1adad47dL,0x6ddde4ebL,0xf4d4b551L,0x83d385c7L,0x136c9856L,0x646ba8c0L,0xfd62f97aL,0x8a65c9ecL,0x14015c4fL,0x63066cd9L,0xfa0f3d63L,0x8d080df5L,0x3b6e20c8L,0x4c69105eL,0xd56041e4L,0xa2677172L,0x3c03e4d1L,0x4b04d447L,0xd20d85fdL,0xa50ab56bL,0x35b5a8faL,0x42b2986cL,0xdbbbc9d6L,0xacbcf940L,0x32d86ce3L,0x45df5c75L,0xdcd60dcfL,0xabd13d59L,0x26d930acL,0x51de003aL,0xc8d75180L,0xbfd06116L,0x21b4f4b5L,0x56b3c423L,0xcfba9599L,0xb8bda50fL,0x2802b89eL,0x5f058808L,0xc60cd9b2L,0xb10be924L,0x2f6f7c87L,0x58684c11L,0xc1611dabL,0xb6662d3dL,0x76dc4190L,0x01db7106L,0x98d220bcL,0xefd5102aL,0x71b18589L,0x06b6b51fL,0x9fbfe4a5L,0xe8b8d433L,0x7807c9a2L,0x0f00f934L,0x9609a88eL,0xe10e9818L,0x7f6a0dbbL,0x086d3d2dL,0x91646c97L,0xe6635c01L,0x6b6b51f4L,0x1c6c6162L,0x856530d8L,0xf262004eL,0x6c0695edL,0x1b01a57bL,0x8208f4c1L,0xf50fc457L,0x65b0d9c6L,0x12b7e950L,0x8bbeb8eaL,0xfcb9887cL,0x62dd1ddfL,0x15da2d49L,0x8cd37cf3L,0xfbd44c65L,0x4db26158L,0x3ab551ceL,0xa3bc0074L,0xd4bb30e2L,0x4adfa541L,0x3dd895d7L,0xa4d1c46dL,0xd3d6f4fbL,0x4369e96aL,0x346ed9fcL,0xad678846L,0xda60b8d0L,0x44042d73L,0x33031de5L,0xaa0a4c5fL,0xdd0d7cc9L,0x5005713cL,0x270241aaL,0xbe0b1010L,0xc90c2086L,0x5768b525L,0x206f85b3L,0xb966d409L,0xce61e49fL,0x5edef90eL,0x29d9c998L,0xb0d09822L,0xc7d7a8b4L,0x59b33d17L,0x2eb40d81L,0xb7bd5c3bL,0xc0ba6cadL,0xedb88320L,0x9abfb3b6L,0x03b6e20cL,0x74b1d29aL,0xead54739L,0x9dd277afL,0x04db2615L,0x73dc1683L,0xe3630b12L,0x94643b84L,0x0d6d6a3eL,0x7a6a5aa8L,0xe40ecf0bL,0x9309ff9dL,0x0a00ae27L,0x7d079eb1L,0xf00f9344L,0x8708a3d2L,0x1e01f268L,0x6906c2feL,0xf762575dL,0x806567cbL,0x196c3671L,0x6e6b06e7L,0xfed41b76L,0x89d32be0L,0x10da7a5aL,0x67dd4accL,0xf9b9df6fL,0x8ebeeff9L,0x17b7be43L,0x60b08ed5L,0xd6d6a3e8L,0xa1d1937eL,0x38d8c2c4L,0x4fdff252L,0xd1bb67f1L,0xa6bc5767L,0x3fb506ddL,0x48b2364bL,0xd80d2bdaL,0xaf0a1b4cL,0x36034af6L,0x41047a60L,0xdf60efc3L,0xa867df55L,0x316e8eefL,0x4669be79L,0xcb61b38cL,0xbc66831aL,0x256fd2a0L,0x5268e236L,0xcc0c7795L,0xbb0b4703L,0x220216b9L,0x5505262fL,0xc5ba3bbeL,0xb2bd0b28L,0x2bb45a92L,0x5cb36a04L,0xc2d7ffa7L,0xb5d0cf31L,0x2cd99e8bL,0x5bdeae1dL,0x9b64c2b0L,0xec63f226L,0x756aa39cL,0x026d930aL,0x9c0906a9L,0xeb0e363fL,0x72076785L,0x05005713L,0x95bf4a82L,0xe2b87a14L,0x7bb12baeL,0x0cb61b38L,0x92d28e9bL,0xe5d5be0dL,0x7cdcefb7L,0x0bdbdf21L,0x86d3d2d4L,0xf1d4e242L,0x68ddb3f8L,0x1fda836eL,0x81be16cdL,0xf6b9265bL,0x6fb077e1L,0x18b74777L,0x88085ae6L,0xff0f6a70L,0x66063bcaL,0x11010b5cL,0x8f659effL,0xf862ae69L,0x616bffd3L,0x166ccf45L,0xa00ae278L,0xd70dd2eeL,0x4e048354L,0x3903b3c2L,0xa7672661L,0xd06016f7L,0x4969474dL,0x3e6e77dbL,0xaed16a4aL,0xd9d65adcL,0x40df0b66L,0x37d83bf0L,0xa9bcae53L,0xdebb9ec5L,0x47b2cf7fL,0x30b5ffe9L,0xbdbdf21cL,0xcabac28aL,0x53b39330L,0x24b4a3a6L,0xbad03605L,0xcdd70693L,0x54de5729L,0x23d967bfL,0xb3667a2eL,0xc4614ab8L,0x5d681b02L,0x2a6f2b94L,0xb40bbe37L,0xc30c8ea1L,0x5a05df1bL,0x2d02ef8dL};#defineCRC32(c,b)(crc_table[((int)(c)^(b))&0xff]^((c)>>8))#defineDO1(buf)crc=CRC32(crc,*buf++)#defineDO2(buf)DO1(buf);DO1(buf)#defineDO4(buf)DO2(buf);DO2(buf)#defineDO8(buf)DO4(buf);DO4(buf)ulgcrc32(ulgcrc,constuch*buf,extentlen){if(buf==NULL)return0L;crc=crc^0xffffffffL;while(len>=8){DO8(buf);len-=8;}if(len)do{DO1(buf);}while(--len);returncrc^0xffffffffL;//(insteadof~cfor64-bitmachines)}voidupdate_keys(unsignedlong*keys,charc){keys[0]=CRC32(keys[0],c);keys[1]+=keys[0]&0xFF;keys[1]=keys[1]*134775813L+1;keys[2]=CRC32(keys[2],keys[1]>>24);}chardecrypt_byte(unsignedlong*keys){unsignedtemp=((unsigned)keys[2]&0xffff)|2;return(char)(((temp*(temp^1))>>8)&0xff);}charzencode(unsignedlong*keys,charc){intt=decrypt_byte(keys);update_keys(keys,c);return(char)(t^c);}boolHasZipSuffix(constTCHAR*fn){constTCHAR*ext=fn+_tcslen(fn);while(ext>fn&&*ext!='.')ext--;if(ext==fn&&*ext!='.')returnfalse;if(_tcsicmp(ext,_T(".Z"))==0)returntrue;if(_tcsicmp(ext,_T(".zip"))==0)returntrue;if(_tcsicmp(ext,_T(".zoo"))==0)returntrue;if(_tcsicmp(ext,_T(".arc"))==0)returntrue;if(_tcsicmp(ext,_T(".lzh"))==0)returntrue;if(_tcsicmp(ext,_T(".arj"))==0)returntrue;if(_tcsicmp(ext,_T(".gz"))==0)returntrue;if(_tcsicmp(ext,_T(".tgz"))==0)returntrue;returnfalse;}lutime_tfiletime2timet(constFILETIMEft){__int64i=*(__int64*)&ft;return(lutime_t)((i-116444736000000000)/10000000);}voidfiletime2dosdatetime(constFILETIMEft,WORD*dosdate,WORD*dostime){//date:bits0-4aredayofmonth1-31.Bits5-8aremonth1..12.Bits9-15areyear-1980//time:bits0-4areseconds/2,bits5-10areminute0..59.Bits11-15arehour0..23SYSTEMTIMEst;FileTimeToSystemTime(&ft,&st);*dosdate=(WORD)(((st.wYear-1980)&0x7f)<<9);*dosdate|=(WORD)((st.wMonth&0xf)<<5);*dosdate|=(WORD)((st.wDay&0x1f));*dostime=(WORD)((st.wHour&0x1f)<<11);*dostime|=(WORD)((st.wMinute&0x3f)<<5);*dostime|=(WORD)((st.wSecond*2)&0x1f);}ZRESULTGetFileInfo(HANDLEhf,ulg*attr,long*size,iztimes*times,ulg*timestamp){//Thehandlemustbeahandletoafile//Thedateandtimeisreturnedinalongwiththedatemostsignificanttoallow//unsignedintegercomparisonofabsolutetimes.Theattributeshavetwo//highbytesunixattr,andtwolowbytesamappingofthattoDOSattr.//structstats;intres=stat(fn,&s);if(res!=0)returnfalse;//translatewindowsfileattributesintozipones.BY_HANDLE_FILE_INFORMATIONbhi;BOOLres=GetFileInformationByHandle(hf,&bhi);if(!res)returnZR_NOFILE;DWORDfa=bhi.dwFileAttributes;ulga=0;//Zipusesthelowerwordforitsinterpretationofwindowsstuffif(fa&FILE_ATTRIBUTE_READONLY)a|=0x01;if(fa&FILE_ATTRIBUTE_HIDDEN)a|=0x02;if(fa&FILE_ATTRIBUTE_SYSTEM)a|=0x04;if(fa&FILE_ATTRIBUTE_DIRECTORY)a|=0x10;if(fa&FILE_ATTRIBUTE_ARCHIVE)a|=0x20;//Itusestheupperwordforstandardunixattr,whichwemanuallyconstructif(fa&FILE_ATTRIBUTE_DIRECTORY)a|=0x40000000;//directoryelsea|=0x80000000;//normalfilea|=0x01000000;//readableif(fa&FILE_ATTRIBUTE_READONLY){}elsea|=0x00800000;//writeable//nowjustasmallheuristictocheckifit'sanexecutable:DWORDred,hsize=GetFileSize(hf,NULL);if(hsize>40){SetFilePointer(hf,0,NULL,FILE_BEGIN);unsignedshortmagic;ReadFile(hf,&magic,sizeof(magic),&red,NULL);SetFilePointer(hf,36,NULL,FILE_BEGIN);unsignedlonghpos;ReadFile(hf,&hpos,sizeof(hpos),&red,NULL);if(magic==0x54AD&&hsize>hpos+4+20+28){SetFilePointer(hf,hpos,NULL,FILE_BEGIN);unsignedlongsignature;ReadFile(hf,&signature,sizeof(signature),&red,NULL);if(signature==IMAGE_DOS_SIGNATURE||signature==IMAGE_OS2_SIGNATURE||signature==IMAGE_OS2_SIGNATURE_LE||signature==IMAGE_NT_SIGNATURE){a|=0x00400000;//executable}}}//if(attr!=NULL)*attr=a;if(size!=NULL)*size=hsize;if(times!=NULL){//lutime_tis32bitnumberofsecondselapsedsince0:0:0GMT,Jan1,1970.//butFILETIMEis64bitnumberof100-nanosecssinceJan1,1601times->atime=filetime2timet(bhi.ftLastAccessTime);times->mtime=filetime2timet(bhi.ftLastWriteTime);times->ctime=filetime2timet(bhi.ftCreationTime);}if(timestamp!=NULL){WORDdosdate,dostime;filetime2dosdatetime(bhi.ftLastWriteTime,&dosdate,&dostime);*timestamp=(WORD)dostime|(((DWORD)dosdate)<<16);}returnZR_OK;}classTZip{public:TZip(constchar*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=newchar[strlen(pwd)+1];strcpy(password,pwd);}}~TZip(){if(state!=0)deletestate;state=0;if(encbuf!=0)delete[]encbuf;encbuf=0;if(password!=0)delete[]password;password=0;}//Thesevariablessayaboutthefilewe'rewritinginto//Wecanwritetopipe,file-by-handle,file-by-name,memory-to-memmapfilechar*password;//keepacopyofthepasswordHANDLEhfout;//ifvalid,we'llwritehere(forfilesorpipes)boolmustclosehfout;//iftrue,weareresponsibleforclosinghfoutHANDLEhmapout;//otherwise,we'llwritehere(formemmap)unsignedooffset;//forhfout,thisiswherethepointerwasinitiallyZRESULToerr;//didawriteoperationgiverisetoanerror?unsignedwrit;//howfarhavewewritten.ThisismaintainedbyAdd,notwrite(),toavoidconfusionoverseeksboolocanseek;//canweseek?char*obuf;//thisiswherewe'velockedmmaptoview.unsignedintopos;//currentposinthemmapunsignedintmapsize;//thesizeofthemapwecreatedboolhasputcen;//haveweyetplacedthecentraldirectory?boolencwriting;//iftrue,thenwe'llencryptstuffusing'keys'beforewewriteittodiskunsignedlongkeys[3];//keysareinitialisedinsideAdd()char*encbuf;//ifencrypting,thenthisisatemporaryworkspaceforencryptingthedataunsignedintencbufsize;//(tobeusedandresizedinsidewrite(),anddeletedinthedestructor)//TZipFileInfo*zfis;//eachfilegetsaddedontothislist,forwritingthetableattheendTState*state;//weusejustonestateobjectperzip,becauseit'sbig(500k)ZRESULTCreate(void*z,unsignedintlen,DWORDflags);staticunsignedsflush(void*param,constchar*buf,unsigned*size);staticunsignedswrite(void*param,constchar*buf,unsignedsize);unsignedintwrite(constchar*buf,unsignedintsize);booloseek(unsignedintpos);ZRESULTGetMemory(void**pbuf,unsignedlong*plen);ZRESULTClose();//somevariablestodowiththefilecurrentlybeingread://Ihaven'tdoneitobject-orientedlyhere,justputthemall//together,sinceOOdidn'tseemtomakethedesignanyclearer.ulgattr;iztimestimes;ulgtimestamp;//allopen_*methodssetthesebooliseekable;longisize,ired;//sizeisnotsetuntilclose()onpipsulgcrc;//crcisnotsetuntilclose().iwritiscumulativeHANDLEhfin;boolselfclosehf;//forinputfilesandpipesconstchar*bufin;unsignedintlenin,posin;//formemory//andavariableforwhatwe'vedonewiththeinput:(i.e.compressedit!)ulgcsize;//compressedsize,setbythecompressionroutines//andthisisusedbysomeofthecompressionroutinescharbuf[16384];ZRESULTopen_file(constTCHAR*fn);ZRESULTopen_handle(HANDLEhf,unsignedintlen);ZRESULTopen_mem(void*src,unsignedintlen);ZRESULTopen_dir();staticunsignedsread(TState&s,char*buf,unsignedsize);unsignedread(char*buf,unsignedsize);ZRESULTiclose();ZRESULTideflate(TZipFileInfo*zfi);ZRESULTistore();ZRESULTAdd(constTCHAR*odstzn,void*src,unsignedintlen,DWORDflags);ZRESULTAddCentral();};ZRESULTTZip::Create(void*z,unsignedintlen,DWORDflags){if(hfout!=0||hmapout!=0||obuf!=0||writ!=0||oerr!=ZR_OK||hasputcen)returnZR_NOTINITED;//if(flags==ZIP_HANDLE){HANDLEhf=(HANDLE)z;hfout=hf;mustclosehfout=false;#ifdefDuplicateHandleBOOLres=DuplicateHandle(GetCurrentProcess(),hf,GetCurrentProcess(),&hfout,0,FALSE,DUPLICATE_SAME_ACCESS);if(res)mustclosehandle=true;#endif//nowwehavehfout.Eitherweduplicatedthehandleandwecloseitourselves//(whilethecallercloseshthemselves),orwecouldn'tduplicateit.DWORDres=SetFilePointer(hfout,0,0,FILE_CURRENT);ocanseek=(res!=0xFFFFFFFF);if(ocanseek)ooffset=res;elseooffset=0;returnZR_OK;}elseif(flags==ZIP_FILENAME){constTCHAR*fn=(constTCHAR*)z;hfout=CreateFile(fn,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);if(hfout==INVALID_HANDLE_VALUE){hfout=0;returnZR_NOFILE;}ocanseek=true;ooffset=0;mustclosehfout=true;returnZR_OK;}elseif(flags==ZIP_MEMORY){unsignedintsize=len;if(size==0)returnZR_MEMSIZE;if(z!=0)obuf=(char*)z;else{hmapout=CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,size,NULL);if(hmapout==NULL)returnZR_NOALLOC;obuf=(char*)MapViewOfFile(hmapout,FILE_MAP_ALL_ACCESS,0,0,size);if(obuf==0){CloseHandle(hmapout);hmapout=0;returnZR_NOALLOC;}}ocanseek=true;opos=0;mapsize=size;returnZR_OK;}elsereturnZR_ARGS;}unsignedTZip::sflush(void*param,constchar*buf,unsigned*size){//staticif(*size==0)return0;TZip*zip=(TZip*)param;unsignedintwrit=zip->write(buf,*size);if(writ!=0)*size=0;returnwrit;}unsignedTZip::swrite(void*param,constchar*buf,unsignedsize){//staticif(size==0)return0;TZip*zip=(TZip*)param;returnzip->write(buf,size);}unsignedintTZip::write(constchar*buf,unsignedintsize){constchar*srcbuf=buf;if(encwriting){if(encbuf!=0&&encbufsize<size){delete[]encbuf;encbuf=0;}if(encbuf==0){encbuf=newchar[size*2];encbufsize=size;}memcpy(encbuf,buf,size);for(unsignedinti=0;i<size;i++)encbuf[i]=zencode(keys,encbuf[i]);srcbuf=encbuf;}if(obuf!=0){if(opos+size>=mapsize){oerr=ZR_MEMSIZE;return0;}memcpy(obuf+opos,srcbuf,size);opos+=size;returnsize;}elseif(hfout!=0){DWORDwrit;WriteFile(hfout,srcbuf,size,&writ,NULL);returnwrit;}oerr=ZR_NOTINITED;return0;}boolTZip::oseek(unsignedintpos){if(!ocanseek){oerr=ZR_SEEK;returnfalse;}if(obuf!=0){if(pos>=mapsize){oerr=ZR_MEMSIZE;returnfalse;}opos=pos;returntrue;}elseif(hfout!=0){SetFilePointer(hfout,pos+ooffset,NULL,FILE_BEGIN);returntrue;}oerr=ZR_NOTINITED;return0;}ZRESULTTZip::GetMemory(void**pbuf,unsignedlong*plen){//WhentheusercallsGetMemory,they'represumablyattheend//ofalltheiradding.Inanycase,wehavetoaddthecentral//directorynow,otherwisethememorywetellthemwon'tbecomplete.if(!hasputcen)AddCentral();hasputcen=true;if(pbuf!=NULL)*pbuf=(void*)obuf;if(plen!=NULL)*plen=writ;if(obuf==NULL)returnZR_NOTMMAP;returnZR_OK;}ZRESULTTZip::Close(){//ifthedirectoryhadn'talreadybeenaddedthroughacalltoGetMemory,//thenwedoitnowZRESULTres=ZR_OK;if(!hasputcen)res=AddCentral();hasputcen=true;if(obuf!=0&&hmapout!=0)UnmapViewOfFile(obuf);obuf=0;if(hmapout!=0)CloseHandle(hmapout);hmapout=0;if(hfout!=0&&mustclosehfout)CloseHandle(hfout);hfout=0;mustclosehfout=false;returnres;}ZRESULTTZip::open_file(constTCHAR*fn){hfin=0;bufin=0;selfclosehf=false;crc=CRCVAL_INITIAL;isize=0;csize=0;ired=0;if(fn==0)returnZR_ARGS;HANDLEhf=CreateFile(fn,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);if(hf==INVALID_HANDLE_VALUE)returnZR_NOFILE;ZRESULTres=open_handle(hf,0);if(res!=ZR_OK){CloseHandle(hf);returnres;}selfclosehf=true;returnZR_OK;}ZRESULTTZip::open_handle(HANDLEhf,unsignedintlen){hfin=0;bufin=0;selfclosehf=false;crc=CRCVAL_INITIAL;isize=0;csize=0;ired=0;if(hf==0||hf==INVALID_HANDLE_VALUE)returnZR_ARGS;DWORDres=SetFilePointer(hfout,0,0,FILE_CURRENT);if(res!=0xFFFFFFFF){ZRESULTres=GetFileInfo(hf,&attr,&isize,×,×tamp);if(res!=ZR_OK)returnres;SetFilePointer(hf,0,NULL,FILE_BEGIN);//becauseGetFileInfowillhavescreweditupiseekable=true;hfin=hf;returnZR_OK;}else{attr=0x80000000;//justanormalfileisize=-1;//can'tknowsizeuntilattheendif(len!=0)isize=len;//unlessweweretoldexplicitly!iseekable=false;SYSTEMTIMEst;GetLocalTime(&st);FILETIMEft;SystemTimeToFileTime(&st,&ft);WORDdosdate,dostime;filetime2dosdatetime(ft,&dosdate,&dostime);times.atime=filetime2timet(ft);times.mtime=times.atime;times.ctime=times.atime;timestamp=(WORD)dostime|(((DWORD)dosdate)<<16);hfin=hf;returnZR_OK;}}ZRESULTTZip::open_mem(void*src,unsignedintlen){hfin=0;bufin=(constchar*)src;selfclosehf=false;crc=CRCVAL_INITIAL;ired=0;csize=0;ired=0;lenin=len;posin=0;if(src==0||len==0)returnZR_ARGS;attr=0x80000000;//justanormalfileisize=len;iseekable=true;SYSTEMTIMEst;GetLocalTime(&st);FILETIMEft;SystemTimeToFileTime(&st,&ft);WORDdosdate,dostime;filetime2dosdatetime(ft,&dosdate,&dostime);times.atime=filetime2timet(ft);times.mtime=times.atime;times.ctime=times.atime;timestamp=(WORD)dostime|(((DWORD)dosdate)<<16);returnZR_OK;}ZRESULTTZip::open_dir(){hfin=0;bufin=0;selfclosehf=false;crc=CRCVAL_INITIAL;isize=0;csize=0;ired=0;attr=0x41C00010;//areadablewritabledirectory,andagaindirectoryisize=0;iseekable=false;SYSTEMTIMEst;GetLocalTime(&st);FILETIMEft;SystemTimeToFileTime(&st,&ft);WORDdosdate,dostime;filetime2dosdatetime(ft,&dosdate,&dostime);times.atime=filetime2timet(ft);times.mtime=times.atime;times.ctime=times.atime;timestamp=(WORD)dostime|(((DWORD)dosdate)<<16);returnZR_OK;}unsignedTZip::sread(TState&s,char*buf,unsignedsize){//staticTZip*zip=(TZip*)s.param;returnzip->read(buf,size);}unsignedTZip::read(char*buf,unsignedsize){if(bufin!=0){if(posin>=lenin)return0;//endofinputulgred=lenin-posin;if(red>size)red=size;memcpy(buf,bufin+posin,red);posin+=red;ired+=red;crc=crc32(crc,(uch*)buf,red);returnred;}elseif(hfin!=0){DWORDred;BOOLok=ReadFile(hfin,buf,size,&red,NULL);if(!ok)return0;ired+=red;crc=crc32(crc,(uch*)buf,red);returnred;}else{oerr=ZR_NOTINITED;return0;}}ZRESULTTZip::iclose(){if(selfclosehf&&hfin!=0)CloseHandle(hfin);hfin=0;boolmismatch=(isize!=-1&&isize!=ired);isize=ired;//andcrchasbeenbeingupdatedanywayif(mismatch)returnZR_MISSIZE;elsereturnZR_OK;}ZRESULTTZip::ideflate(TZipFileInfo*zfi){if(state==0)state=newTState();//It'saverybigobject!500k!Weallocateitontheheap,becausePocketPC's//stackbreaksifwetrytoputitallonthestack.Itwillbedeletedlazilystate->err=0;state->readfunc=sread;state->flush_outbuf=sflush;state->param=this;state->level=8;state->seekable=iseekable;state->err=NULL;//thefollowinglinewillmakect_initrealiseithastoperformtheinitstate->ts.static_dtree[0].dl.len=0;//ThankstoAlvin77forthiscrucialfix:state->ds.window_size=0;//Ithinkthatcoverseverythingthatneedstobeinitted.//bi_init(*state,buf,sizeof(buf),TRUE);//itusedtobejust1024-size,not16384asherect_init(*state,&zfi->att);lm_init(*state,state->level,&zfi->flg);ulgsz=deflate(*state);csize=sz;ZRESULTr=ZR_OK;if(state->err!=NULL)r=ZR_FLATE;returnr;}ZRESULTTZip::istore(){ulgsize=0;for(;;){unsignedintcin=read(buf,16384);if(cin<=0||cin==(unsignedint)EOF)break;unsignedintcout=write(buf,cin);if(cout!=cin)returnZR_MISSIZE;size+=cin;}csize=size;returnZR_OK;}boolhas_seeded=false;ZRESULTTZip::Add(constTCHAR*odstzn,void*src,unsignedintlen,DWORDflags){if(oerr)returnZR_FAILED;if(hasputcen)returnZR_ENDED;//ifweusepasswordencryption,theneveryisizeandcsizeis12bytesbiggerintpassex=0;if(password!=0&&flags!=ZIP_FOLDER)passex=12;//ziphasitsownnotionofwhatitsnamesshouldlooklike:i.e.dir/file.stuffTCHARdstzn[MAX_PATH];_tcscpy(dstzn,odstzn);if(*dstzn==0)returnZR_ARGS;TCHAR*d=dstzn;while(*d!=0){if(*d=='\\')*d='/';d++;}boolisdir=(flags==ZIP_FOLDER);boolneeds_trailing_slash=(isdir&&dstzn[_tcslen(dstzn)-1]!='/');intmethod=DEFLATE;if(isdir||HasZipSuffix(dstzn))method=STORE;//nowopenwhateverwasourinputsource:ZRESULTopenres;if(flags==ZIP_FILENAME)openres=open_file((constTCHAR*)src);elseif(flags==ZIP_HANDLE)openres=open_handle((HANDLE)src,len);elseif(flags==ZIP_MEMORY)openres=open_mem(src,len);elseif(flags==ZIP_FOLDER)openres=open_dir();elsereturnZR_ARGS;if(openres!=ZR_OK)returnopenres;//Azip"entry"consistsofalocalheader(whichincludesthefilename),//thenthecompresseddata,andpossiblyanextendedlocalheader.//InitializethelocalheaderTZipFileInfozfi;zfi.nxt=NULL;strcpy(zfi.name,"");#ifdefUNICODEWideCharToMultiByte(CP_UTF8,0,dstzn,-1,zfi.iname,MAX_PATH,0,0);#elsestrcpy(zfi.iname,dstzn);#endifzfi.nam=strlen(zfi.iname);if(needs_trailing_slash){strcat(zfi.iname,"/");zfi.nam++;}strcpy(zfi.zname,"");zfi.extra=NULL;zfi.ext=0;//extraheadertogoafterthiscompresseddata,anditslengthzfi.cextra=NULL;zfi.cext=0;//extraheadertogointhecentralend-of-zipdirectory,anditslengthzfi.comment=NULL;zfi.com=0;//comment,anditslengthzfi.mark=1;zfi.dosflag=0;zfi.att=(ush)BINARY;zfi.vem=(ush)0xB17;//0xB00iswin32os-code.0x17is23indecimal:zip2.3zfi.ver=(ush)20;//NeedsPKUNZIP2.0tounzipitzfi.tim=timestamp;//Eventhoughwewritetheheadernow,itwillhavetoberewritten,sincewedon'tknowcompressedsizeorcrc.zfi.crc=0;//tobeupdatedlaterzfi.flg=8;//8means'thereisanextraheader'.Assumeforthemomentthatweneedit.if(password!=0&&!isdir)zfi.flg=9;//and1means'password-encrypted'zfi.lflg=zfi.flg;//tobeupdatedlaterzfi.how=(ush)method;//tobeupdatedlaterzfi.siz=(ulg)(method==STORE&&isize>=0?isize+passex:0);//tobeupdatedlaterzfi.len=(ulg)(isize);//tobeupdatedlaterzfi.dsk=0;zfi.atx=attr;zfi.off=writ+ooffset;//offsetwithinfileofthestartofthislocalrecord//stuffthe'times'structureintozfi.extra//nb.apparentlythere'saproblemwithPocketPCCE(zip)->CE(unzip)fails.Andremovingthefollowingblockfixesitup.charxloc[EB_L_UT_SIZE];zfi.extra=xloc;zfi.ext=EB_L_UT_SIZE;charxcen[EB_C_UT_SIZE];zfi.cextra=xcen;zfi.cext=EB_C_UT_SIZE;xloc[0]='U';xloc[1]='T';xloc[2]=EB_UT_LEN(3);//lengthofdatapartofe.f.xloc[3]=0;xloc[4]=EB_UT_FL_MTIME|EB_UT_FL_ATIME|EB_UT_FL_CTIME;xloc[5]=(char)(times.mtime);xloc[6]=(char)(times.mtime>>8);xloc[7]=(char)(times.mtime>>16);xloc[8]=(char)(times.mtime>>24);xloc[9]=(char)(times.atime);xloc[10]=(char)(times.atime>>8);xloc[11]=(char)(times.atime>>16);xloc[12]=(char)(times.atime>>24);xloc[13]=(char)(times.ctime);xloc[14]=(char)(times.ctime>>8);xloc[15]=(char)(times.ctime>>16);xloc[16]=(char)(times.ctime>>24);memcpy(zfi.cextra,zfi.extra,EB_C_UT_SIZE);zfi.cextra[EB_LEN]=EB_UT_LEN(1);//(1)Startbywritingthelocalheader:intr=putlocal(&zfi,swrite,this);if(r!=ZE_OK){iclose();returnZR_WRITE;}writ+=4+LOCHEAD+(unsignedint)zfi.nam+(unsignedint)zfi.ext;if(oerr!=ZR_OK){iclose();returnoerr;}//(1.5)ifnecessary,writetheencryptionheaderkeys[0]=305419896L;keys[1]=591751049L;keys[2]=878082192L;for(constchar*cp=password;cp!=0&&*cp!=0;cp++)update_keys(keys,*cp);//generatesomerandombytesif(!has_seeded)srand(GetTickCount()^(unsignedlong)GetDesktopWindow());charencbuf[12];for(inti=0;i<12;i++)encbuf[i]=(char)((rand()>>7)&0xff);encbuf[11]=(char)((zfi.tim>>8)&0xff);for(intei=0;ei<12;ei++)encbuf[ei]=zencode(keys,encbuf[ei]);if(password!=0&&!isdir){swrite(this,encbuf,12);writ+=12;}//(2)Writedeflated/storedfiletozipfileZRESULTwriteres=ZR_OK;encwriting=(password!=0&&!isdir);//anobjectmembervariabletosaywhetherwewritetodiskencryptedif(!isdir&&method==DEFLATE)writeres=ideflate(&zfi);elseif(!isdir&&method==STORE)writeres=istore();elseif(isdir)csize=0;encwriting=false;iclose();writ+=csize;if(oerr!=ZR_OK)returnoerr;if(writeres!=ZR_OK)returnZR_WRITE;//(3)Eitherrewritethelocalheaderwithcorrectinformation...boolfirst_header_has_size_right=(zfi.siz==csize+passex);zfi.crc=crc;zfi.siz=csize+passex;zfi.len=isize;if(ocanseek&&(password==0||isdir)){zfi.how=(ush)method;if((zfi.flg&1)==0)zfi.flg&=~8;//cleartheextendedlocalheaderflagzfi.lflg=zfi.flg;//rewritethelocalheader:if(!oseek(zfi.off-ooffset))returnZR_SEEK;if((r=putlocal(&zfi,swrite,this))!=ZE_OK)returnZR_WRITE;if(!oseek(writ))returnZR_SEEK;}else{//(4)...orputanupdatedheaderattheendif(zfi.how!=(ush)method)returnZR_NOCHANGE;if(method==STORE&&!first_header_has_size_right)returnZR_NOCHANGE;if((r=putextended(&zfi,swrite,this))!=ZE_OK)returnZR_WRITE;writ+=16L;zfi.flg=zfi.lflg;//ifflgmodifiedbyinflate,forthecentralindex}if(oerr!=ZR_OK)returnoerr;//Keepacopyofthezipfileinfo,forourend-of-zipdirectorychar*cextra=newchar[zfi.cext];memcpy(cextra,zfi.cextra,zfi.cext);zfi.cextra=cextra;TZipFileInfo*pzfi=newTZipFileInfo;memcpy(pzfi,&zfi,sizeof(zfi));if(zfis==NULL)zfis=pzfi;else{TZipFileInfo*z=zfis;while(z->nxt!=NULL)z=z->nxt;z->nxt=pzfi;}returnZR_OK;}ZRESULTTZip::AddCentral(){//writecentraldirectoryintnumentries=0;ulgpos_at_start_of_central=writ;//ulgtot_unc_size=0,tot_compressed_size=0;boolokay=true;for(TZipFileInfo*zfi=zfis;zfi!=NULL;){if(okay){intres=putcentral(zfi,swrite,this);if(res!=ZE_OK)okay=false;}writ+=4+CENHEAD+(unsignedint)zfi->nam+(unsignedint)zfi->cext+(unsignedint)zfi->com;//tot_unc_size+=zfi->len;//tot_compressed_size+=zfi->siz;numentries++;//TZipFileInfo*zfinext=zfi->nxt;if(zfi->cextra!=0)delete[]zfi->cextra;deletezfi;zfi=zfinext;}ulgcenter_size=writ-pos_at_start_of_central;if(okay){intres=putend(numentries,center_size,pos_at_start_of_central+ooffset,0,NULL,swrite,this);if(res!=ZE_OK)okay=false;writ+=4+ENDHEAD+0;}if(!okay)returnZR_WRITE;returnZR_OK;}ZRESULTlasterrorZ=ZR_OK;unsignedintFormatZipMessageZ(ZRESULTcode,char*buf,unsignedintlen){if(code==ZR_RECENT)code=lasterrorZ;constchar*msg="unknown zip result code";switch(code){caseZR_OK:msg="Success";break;caseZR_NODUPH:msg="Culdn't duplicate handle";break;caseZR_NOFILE:msg="Couldn't create/open file";break;caseZR_NOALLOC:msg="Failed to allocate memory";break;caseZR_WRITE:msg="Error writing to file";break;caseZR_NOTFOUND:msg="File not found in the zipfile";break;caseZR_MORE:msg="Still more data to unzip";break;caseZR_CORRUPT:msg="Zipfile is corrupt or not a zipfile";break;caseZR_READ:msg="Error reading file";break;caseZR_ARGS:msg="Caller: faulty arguments";break;caseZR_PARTIALUNZ:msg="Caller: the file had already been partially unzipped";break;caseZR_NOTMMAP:msg="Caller: can only get memory of a memory zipfile";break;caseZR_MEMSIZE:msg="Caller: not enough space allocated for memory zipfile";break;caseZR_FAILED:msg="Caller: there was a previous error";break;caseZR_ENDED:msg="Caller: additions to the zip have already been ended";break;caseZR_ZMODE:msg="Caller: mixing creation and opening of zip";break;caseZR_NOTINITED:msg="Zip-bug: internal initialisation not completed";break;caseZR_SEEK:msg="Zip-bug: trying to seek the unseekable";break;caseZR_MISSIZE:msg="Zip-bug: the anticipated size turned out wrong";break;caseZR_NOCHANGE:msg="Zip-bug: tried to change mind, but not allowed";break;caseZR_FLATE:msg="Zip-bug: an internal error during flation";break;}unsignedintmlen=(unsignedint)strlen(msg);if(buf==0||len==0)returnmlen;unsignedintn=mlen;if(n+1>len)n=len-1;strncpy(buf,msg,n);buf[n]=0;returnmlen;}typedefstruct{DWORDflag;TZip*zip;}TZipHandleData;HZIPCreateZipInternal(void*z,unsignedintlen,DWORDflags,constchar*password){TZip*zip=newTZip(password);lasterrorZ=zip->Create(z,len,flags);if(lasterrorZ!=ZR_OK){deletezip;return0;}TZipHandleData*han=newTZipHandleData;han->flag=2;han->zip=zip;return(HZIP)han;}HZIPCreateZipHandle(HANDLEh,constchar*password){returnCreateZipInternal(h,0,ZIP_HANDLE,password);}HZIPCreateZip(constTCHAR*fn,constchar*password){returnCreateZipInternal((void*)fn,0,ZIP_FILENAME,password);}HZIPCreateZip(void*z,unsignedintlen,constchar*password){returnCreateZipInternal(z,len,ZIP_MEMORY,password);}ZRESULTZipAddInternal(HZIPhz,constTCHAR*dstzn,void*src,unsignedintlen,DWORDflags){if(hz==0){lasterrorZ=ZR_ARGS;returnZR_ARGS;}TZipHandleData*han=(TZipHandleData*)hz;if(han->flag!=2){lasterrorZ=ZR_ZMODE;returnZR_ZMODE;}TZip*zip=han->zip;lasterrorZ=zip->Add(dstzn,src,len,flags);returnlasterrorZ;}ZRESULTZipAdd(HZIPhz,constTCHAR*dstzn,constTCHAR*fn){returnZipAddInternal(hz,dstzn,(void*)fn,0,ZIP_FILENAME);}ZRESULTZipAdd(HZIPhz,constTCHAR*dstzn,void*src,unsignedintlen){returnZipAddInternal(hz,dstzn,src,len,ZIP_MEMORY);}ZRESULTZipAddHandle(HZIPhz,constTCHAR*dstzn,HANDLEh){returnZipAddInternal(hz,dstzn,h,0,ZIP_HANDLE);}ZRESULTZipAddHandle(HZIPhz,constTCHAR*dstzn,HANDLEh,unsignedintlen){returnZipAddInternal(hz,dstzn,h,len,ZIP_HANDLE);}ZRESULTZipAddFolder(HZIPhz,constTCHAR*dstzn){returnZipAddInternal(hz,dstzn,0,0,ZIP_FOLDER);}ZRESULTZipGetMemory(HZIPhz,void**buf,unsignedlong*len){if(hz==0){if(buf!=0)*buf=0;if(len!=0)*len=0;lasterrorZ=ZR_ARGS;returnZR_ARGS;}TZipHandleData*han=(TZipHandleData*)hz;if(han->flag!=2){lasterrorZ=ZR_ZMODE;returnZR_ZMODE;}TZip*zip=han->zip;lasterrorZ=zip->GetMemory(buf,len);returnlasterrorZ;}ZRESULTCloseZipZ(HZIPhz){if(hz==0){lasterrorZ=ZR_ARGS;returnZR_ARGS;}TZipHandleData*han=(TZipHandleData*)hz;if(han->flag!=2){lasterrorZ=ZR_ZMODE;returnZR_ZMODE;}TZip*zip=han->zip;lasterrorZ=zip->Close();deletezip;deletehan;returnlasterrorZ;}boolIsZipHandleZ(HZIPhz){if(hz==0)returnfalse;TZipHandleData*han=(TZipHandleData*)hz;return(han->flag==2);}