unzip.pp 96 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320
  1. {
  2. }
  3. UNIT Unzip;
  4. {
  5. Unzips deflated, imploded, shrunk and stored files
  6. ** COMPATIBLE WITH
  7. * Turbo Pascal v7.x (DOS)
  8. * Borland Pascal v7.x (Dos, DPMI, and Windows)
  9. * Delphi v1.x
  10. * Delphi v2.x
  11. * Delphi v3.x
  12. * Virtual Pascal v2.0 (OS/2, Win32)
  13. * Free Pascal Compiler (DOS, OS/2, Win32, Linux, FreeBSD, NetBSD)
  14. }
  15. {
  16. Original version (1.x): Christian Ghisler
  17. C code by info-zip group, translated to pascal by Christian Ghisler
  18. based on unz51g.zip;
  19. Special thanks go to Mark Adler,who wrote the main inflate and
  20. explode code, and did NOT copyright it!!!
  21. v2.00: March 1998: Dr Abimbola Olowofoyeku (The African Chief)
  22. Homepage: http://ourworld.compuserve.com/homepages/African_Chief
  23. * modified to compile for Delphi v2.x and Delphi v3.x
  24. v2.01: April 1998: Dr Abimbola Olowofoyeku (The African Chief)
  25. * source files merged into a single source (this) file
  26. * several high level functions added - i.e.,
  27. FileUnzip()
  28. FileUnzipEx()
  29. ViewZip()
  30. UnzipSize()
  31. SetUnzipReportProc()
  32. SetUnzipQuestionProc()
  33. ChfUnzip_Init()
  34. * callbacks added
  35. * modified to support Virtual Pascal v2.0 (Win32)
  36. * Delphi component added (chfunzip.pas)
  37. v2.01a: December 1998: Tomas Hajny, [email protected]
  38. * extended to support other 32-bit compilers/platforms (OS/2, GO32, ...);
  39. search for (* TH ... *)
  40. v2.01b: December 1998: Peter Vreman
  41. * modifications needed for Linux
  42. }
  43. INTERFACE
  44. {$IFDEF FPC}
  45. {$DEFINE BIT32}
  46. {$ENDIF}
  47. {$IFDEF OS2}
  48. {$DEFINE BIT32}
  49. {$ENDIF}
  50. {$IFDEF WIN32}
  51. {$DEFINE BIT32}
  52. {$ENDIF}
  53. {$IFNDEF FPC}
  54. {$F+}
  55. {$ENDIF}
  56. {$R-} {No range checking}
  57. USES
  58. {$ifdef windows}
  59. wintypes,
  60. winprocs,
  61. {$ifdef Delphi}
  62. Messages,
  63. Sysutils,
  64. {$else Delphi}
  65. strings,
  66. windos,
  67. {$endif Delphi}
  68. {$else Windows}
  69. strings,
  70. dos,
  71. {$endif Windows}
  72. ziptypes;
  73. {**********************************************************************}
  74. {**********************************************************************}
  75. {****** HIGH LEVEL FUNCTIONS: BY THE AFRICAN CHIEF ********************}
  76. {**********************************************************************}
  77. {**********************************************************************}
  78. FUNCTION FileUnzip
  79. ( SourceZipFile, TargetDirectory, FileSpecs : pChar;
  80. Report : UnzipReportProc;Question : UnzipQuestionProc ) : integer;
  81. {$ifdef Windows}{$ifdef Win32}STDCALL;{$else}EXPORT;{$endif Win32}{$endif Windows}
  82. {$ifdef DPMI} EXPORT; {$endif DPMI}
  83. {
  84. high level unzip
  85. usage:
  86. SourceZipFile: source zip file;
  87. TargetDirectory: target directory
  88. FileSpecs: "*.*", etc.
  89. Report: Report callback or Nil;
  90. Question: Question callback (for confirmation of whether to replace existing
  91. files) or Nil;
  92. * REFER to ZIPTYPES.PAS for information on callback functions
  93. e.g.,
  94. Count := FileUnzip('test.zip', 'c:\temp', '*.*', MyReportProc, Nil);
  95. }
  96. FUNCTION FileUnzipEx ( SourceZipFile, TargetDirectory, FileSpecs : pChar ) : integer;
  97. {$ifdef Windows}{$ifdef Win32}STDCALL;{$else}EXPORT;{$endif Win32}{$endif Windows}
  98. {$ifdef DPMI} EXPORT; {$endif DPMI}
  99. {
  100. high level unzip with no callback parameters;
  101. passes ZipReport & ZipQuestion internally, so you
  102. can use SetZipReportProc and SetZipQuestionProc before calling this;
  103. e.g.,
  104. Count := FileUnzipEx('test.zip', 'c:\temp', '*.*');
  105. }
  106. FUNCTION ViewZip ( SourceZipFile, FileSpecs : pChar; Report : UnzipReportProc ) : integer;
  107. {$ifdef Windows}{$ifdef Win32}STDCALL;{$else}EXPORT;{$endif Win32}{$endif Windows}
  108. {$ifdef DPMI} EXPORT; {$endif DPMI}
  109. {
  110. view contents of zip file
  111. usage:
  112. SourceZipFile: source zip file;
  113. FileSpecs: "*.*", etc.
  114. Report: callback procedure to process the reported contents of ZIP file;
  115. * REFER to ZIPTYPES.PAS for information on callback functions
  116. e.g.,
  117. ViewZip('test.zip', '*.*', MyReportProc);
  118. }
  119. FUNCTION SetUnZipReportProc ( aProc : UnzipReportProc ) : Pointer;
  120. {$ifdef Windows}{$ifdef Win32}STDCALL;{$else}EXPORT;{$endif Win32}{$endif Windows}
  121. {$ifdef DPMI} EXPORT; {$endif DPMI}
  122. {
  123. sets the internal unzip report procedure to aproc
  124. Returns: pointer to the original report procedure
  125. (return value should normally be ignored)
  126. e.g.,
  127. SetUnZipReportProc(MyReportProc);
  128. }
  129. FUNCTION SetUnZipQuestionProc ( aProc : UnzipQuestionProc ) : Pointer;
  130. {$ifdef Windows}{$ifdef Win32}STDCALL;{$else}EXPORT;{$endif Win32}{$endif Windows}
  131. {$ifdef DPMI} EXPORT; {$endif DPMI}
  132. {
  133. sets the internal unzip question procedure to aproc
  134. Returns: pointer to the original "question" procedure
  135. (return value should normally be ignored)
  136. e.g.,
  137. SetUnZipQuestionProc(QueryFileExistProc);
  138. }
  139. FUNCTION UnzipSize ( SourceZipFile : pChar;VAR Compressed : Longint ) : longint;
  140. {$ifdef Windows}{$ifdef Win32}STDCALL;{$else}EXPORT;{$endif Win32}{$endif Windows}
  141. {$ifdef DPMI} EXPORT; {$endif DPMI}
  142. { uncompressed and compressed zip size
  143. usage:
  144. SourceZipFile = the zip file
  145. Compressed = the compressed size of the files in the archive
  146. Returns: the uncompressed size of the ZIP archive
  147. e.g.,
  148. Var
  149. Size,CSize:longint;
  150. begin
  151. Size := UnzipSize('test.zip', CSize);
  152. end;
  153. }
  154. PROCEDURE ChfUnzip_Init;
  155. {$ifdef Windows}{$ifdef Win32}STDCALL;{$else}EXPORT;{$endif Win32}{$endif Windows}
  156. {$ifdef DPMI} EXPORT; {$endif DPMI}
  157. {
  158. initialise or reinitialise the shared data: !!! use with care !!!
  159. }
  160. FUNCTION SetNoRecurseDirs ( DontRecurse : Boolean ) : Boolean;
  161. {$ifdef Windows}{$ifdef Win32}STDCALL;{$else}EXPORT;{$endif Win32}{$endif Windows}
  162. {$ifdef DPMI} EXPORT; {$endif DPMI}
  163. {
  164. determine whether the UNZIP function should recreate
  165. the subdirectory structure;
  166. DontRecurse = TRUE : don't recurse
  167. DontRecurse = FALSE : recurse (default)
  168. }
  169. {**********************************************************************}
  170. {**********************************************************************}
  171. {************ LOW LEVEL FUNCTIONS: BY CHRISTIAN GHISLER ***************}
  172. {**********************************************************************}
  173. {**********************************************************************}
  174. FUNCTION GetSupportedMethods : longint;
  175. {$ifdef Windows}{$ifdef Win32}STDCALL;{$else}EXPORT;{$endif Win32}{$endif Windows}
  176. {$ifdef DPMI} EXPORT; {$endif DPMI}
  177. {Checks which pack methods are supported by the dll}
  178. {bit 8=1 -> Format 8 supported, etc.}
  179. FUNCTION UnzipFile ( in_name : pchar;out_name : pchar;offset : longint;hFileAction : word;cm_index : integer ) : integer;
  180. {$ifdef Windows}{$ifdef Win32}STDCALL;{$else}EXPORT;{$endif Win32}{$endif Windows}
  181. {$ifdef DPMI} EXPORT; {$endif DPMI}
  182. {usage:
  183. in_name: name of zip file with full path
  184. out_name: desired name for out file
  185. offset: header position of desired file in zipfile
  186. hFileAction: handle to dialog box showing advance of decompression (optional)
  187. cm_index: notification code sent in a wm_command message to the dialog
  188. to update percent-bar
  189. Return value: one of the above unzip_xxx codes
  190. Example for handling the cm_index message in a progress dialog:
  191. unzipfile(......,cm_showpercent);
  192. ...
  193. procedure TFileActionDialog.wmcommand(var msg:tmessage);
  194. var ppercent:^word;
  195. begin
  196. TDialog.WMCommand(msg);
  197. if msg.wparam=cm_showpercent then begin
  198. ppercent:=pointer(lparam);
  199. if ppercent<>nil then begin
  200. if (ppercent^>=0) and (ppercent^<=100) then
  201. SetProgressBar(ppercent^);
  202. if UserPressedAbort then
  203. ppercent^:=$ffff
  204. else
  205. ppercent^:=0;
  206. end;
  207. end;
  208. end;
  209. end;
  210. }
  211. FUNCTION GetFirstInZip ( zipfilename : pchar;VAR zprec : tZipRec ) : integer;
  212. {$ifdef Windows}{$ifdef Win32}STDCALL;{$else}EXPORT;{$endif Win32}{$endif Windows}
  213. {$ifdef DPMI} EXPORT; {$endif DPMI}
  214. {
  215. Get first entry from ZIP file
  216. e.g.,
  217. rc:=GetFirstInZip('test.zip', myZipRec);
  218. }
  219. FUNCTION GetNextInZip ( VAR Zprec : tZiprec ) : integer;
  220. {$ifdef Windows}{$ifdef Win32}STDCALL;{$else}EXPORT;{$endif Win32}{$endif Windows}
  221. {$ifdef DPMI} EXPORT; {$endif DPMI}
  222. {
  223. Get next entry from ZIP file
  224. e.g.,
  225. rc:=GetNextInZip(myZipRec);
  226. }
  227. FUNCTION IsZip ( filename : pchar ) : boolean;
  228. {$ifdef Windows}{$ifdef Win32}STDCALL;{$else}EXPORT;{$endif Win32}{$endif Windows}
  229. {$ifdef DPMI} EXPORT; {$endif DPMI}
  230. {
  231. VERY simple test for zip file
  232. e.g.,
  233. ItsaZipFile := IsZip('test.zip');
  234. }
  235. PROCEDURE CloseZipFile ( VAR Zprec : tZiprec ); {Only free buffer, file only open in Getfirstinzip}
  236. {$ifdef Windows}{$ifdef Win32}STDCALL;{$else}EXPORT;{$endif Win32}{$endif Windows}
  237. {$ifdef DPMI} EXPORT; {$endif DPMI}
  238. {
  239. free ZIP buffers
  240. e.g.,
  241. CloseZipFile(myZipRec);
  242. }
  243. IMPLEMENTATION
  244. VAR
  245. ZipReport : UnzipReportProc; {Global Status Report Callback}
  246. ZipQuestion : UnzipQuestionProc; {Global "Question" Callback}
  247. ZipRec : TReportRec; {Global ZIP record for callbacks}
  248. NoRecurseDirs : Boolean; {Global Recurse variable}
  249. {*************************************************************************}
  250. {$ifdef Delphi}
  251. PROCEDURE SetCurDir ( p : pChar );
  252. BEGIN
  253. Chdir ( strpas ( p ) );
  254. END;
  255. FUNCTION DosError : integer; {Delphi DosError kludge}
  256. BEGIN
  257. Result := Ioresult;
  258. END;
  259. FUNCTION SetFTime ( VAR f : File; CONST l : longint ) : integer;
  260. BEGIN
  261. {$ifdef Win32}Result := {$endif}FileSetDate ( TFileRec ( f ) .Handle, l );
  262. END;
  263. PROCEDURE CreateDir ( p : pchar );
  264. BEGIN
  265. mkdir ( strpas ( p ) );
  266. END;
  267. {/////////////////////////////////////////////////////////}
  268. {$endif Delphi}
  269. {.$I z_global.pas} {global constants, types and variables}
  270. {Include file for unzip.pas: global constants, types and variables}
  271. {C code by info-zip group, translated to pascal by Christian Ghisler}
  272. {based on unz51g.zip}
  273. CONST {Error codes returned by huft_build}
  274. huft_complete = 0; {Complete tree}
  275. huft_incomplete = 1; {Incomplete tree <- sufficient in some cases!}
  276. huft_error = 2; {bad tree constructed}
  277. huft_outofmem = 3; {not enough memory}
  278. (* TH - use of the new BIT32 conditional (was WIN32 only previously) *)
  279. MaxMax = {$ifdef BIT32}256 * 1024 {BIT32 = 256kb buffer}
  280. {$else}Maxint -1{$endif}; {16-bit = 32kb buffer}
  281. CONST wsize = $8000; {Size of sliding dictionary}
  282. INBUFSIZ = 1024 * 4; {Size of input buffer}
  283. CONST lbits : integer = 9;
  284. dbits : integer = 6;
  285. CONST b_max = 16;
  286. n_max = 288;
  287. BMAX = 16;
  288. TYPE push = ^ush;
  289. ush = word;
  290. pbyte = ^byte;
  291. pushlist = ^ushlist;
  292. ushlist = ARRAY [ 0..maxmax ] of ush; {only pseudo-size!!}
  293. pword = ^word;
  294. pwordarr = ^twordarr;
  295. twordarr = ARRAY [ 0..maxmax ] of word;
  296. iobuf = ARRAY [ 0..inbufsiz -1 ] of byte;
  297. TYPE pphuft = ^phuft;
  298. phuft = ^huft;
  299. phuftlist = ^huftlist;
  300. huft = PACKED RECORD
  301. e, {# of extra bits}
  302. b : byte; {# of bits in code}
  303. v_n : ush;
  304. v_t : phuftlist; {Linked List}
  305. END;
  306. huftlist = ARRAY [ 0..8190 ] of huft;
  307. TYPE li = PACKED RECORD
  308. lo, hi : word;
  309. END;
  310. {pkzip header in front of every file in archive}
  311. TYPE
  312. plocalheader = ^tlocalheader;
  313. tlocalheader = PACKED RECORD
  314. signature : ARRAY [ 0..3 ] of char; {'PK'#1#2}
  315. extract_ver,
  316. bit_flag,
  317. zip_type : word;
  318. file_timedate : longint;
  319. crc_32,
  320. compress_size,
  321. uncompress_size : longint;
  322. filename_len,
  323. extra_field_len : word;
  324. END;
  325. VAR slide : pchar; {Sliding dictionary for unzipping}
  326. inbuf : iobuf; {input buffer}
  327. inpos, readpos : integer; {position in input buffer, position read from file}
  328. {$ifdef windows}
  329. dlghandle : word; {optional: handle of a cancel and "%-done"-dialog}
  330. dlgnotify : integer; {notification code to tell dialog how far the decompression is}
  331. {$endif}
  332. VAR w : longint; {Current Position in slide}
  333. b : longint; {Bit Buffer}
  334. k : byte; {Bits in bit buffer}
  335. infile, {handle to zipfile}
  336. outfile : file; {handle to extracted file}
  337. compsize, {comressed size of file}
  338. reachedsize, {number of bytes read from zipfile}
  339. uncompsize : longint; {uncompressed size of file}
  340. crc32val : cardinal; {crc calculated from data}
  341. hufttype : word; {coding type=bit_flag from header}
  342. totalabort, {User pressed abort button, set in showpercent!}
  343. zipeof : boolean; {read over end of zip section for this file}
  344. inuse : boolean; {is unit already in use -> don't call it again!!!}
  345. {$ifdef windows}
  346. oldpercent : integer; {last percent value shown}
  347. lastusedtime : longint; {Time of last usage in timer ticks for timeout!}
  348. {$endif}
  349. (***************************************************************************)
  350. {.$I z_tables.pas} {Tables for bit masking, huffman codes and CRC checking}
  351. {include file for unzip.pas: Tables for bit masking, huffman codes and CRC checking}
  352. {C code by info-zip group, translated to Pascal by Christian Ghisler}
  353. {based on unz51g.zip}
  354. {b and mask_bits[i] gets lower i bits out of i}
  355. CONST mask_bits : ARRAY [ 0..16 ] of word =
  356. ( $0000,
  357. $0001, $0003, $0007, $000f, $001f, $003f, $007f, $00ff,
  358. $01ff, $03ff, $07ff, $0fff, $1fff, $3fff, $7fff, $ffff );
  359. { Tables for deflate from PKZIP's appnote.txt. }
  360. CONST border : ARRAY [ 0..18 ] of byte = { Order of the bit length code lengths }
  361. ( 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 );
  362. CONST cplens : ARRAY [ 0..30 ] of word = { Copy lengths for literal codes 257..285 }
  363. ( 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
  364. 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 );
  365. { note: see note #13 above about the 258 in this list.}
  366. CONST cplext : ARRAY [ 0..30 ] of word = { Extra bits for literal codes 257..285 }
  367. ( 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
  368. 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99 ); { 99==invalid }
  369. CONST cpdist : ARRAY [ 0..29 ] of word = { Copy offsets for distance codes 0..29 }
  370. ( 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
  371. 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
  372. 8193, 12289, 16385, 24577 );
  373. CONST cpdext : ARRAY [ 0..29 ] of word = { Extra bits for distance codes }
  374. ( 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
  375. 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
  376. 12, 12, 13, 13 );
  377. { Tables for explode }
  378. CONST cplen2 : ARRAY [ 0..63 ] of word = ( 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
  379. 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
  380. 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
  381. 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65 );
  382. CONST cplen3 : ARRAY [ 0..63 ] of word = ( 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
  383. 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
  384. 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
  385. 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66 );
  386. CONST extra : ARRAY [ 0..63 ] of word = ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  387. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  388. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  389. 8 );
  390. CONST cpdist4 : ARRAY [ 0..63 ] of word = ( 1, 65, 129, 193, 257, 321, 385, 449, 513, 577, 641, 705,
  391. 769, 833, 897, 961, 1025, 1089, 1153, 1217, 1281, 1345, 1409, 1473,
  392. 1537, 1601, 1665, 1729, 1793, 1857, 1921, 1985, 2049, 2113, 2177,
  393. 2241, 2305, 2369, 2433, 2497, 2561, 2625, 2689, 2753, 2817, 2881,
  394. 2945, 3009, 3073, 3137, 3201, 3265, 3329, 3393, 3457, 3521, 3585,
  395. 3649, 3713, 3777, 3841, 3905, 3969, 4033 );
  396. CONST cpdist8 : ARRAY [ 0..63 ] of word = ( 1, 129, 257, 385, 513, 641, 769, 897, 1025, 1153, 1281,
  397. 1409, 1537, 1665, 1793, 1921, 2049, 2177, 2305, 2433, 2561, 2689,
  398. 2817, 2945, 3073, 3201, 3329, 3457, 3585, 3713, 3841, 3969, 4097,
  399. 4225, 4353, 4481, 4609, 4737, 4865, 4993, 5121, 5249, 5377, 5505,
  400. 5633, 5761, 5889, 6017, 6145, 6273, 6401, 6529, 6657, 6785, 6913,
  401. 7041, 7169, 7297, 7425, 7553, 7681, 7809, 7937, 8065 );
  402. {************************************ CRC-Calculation ************************************}
  403. CONST crc_32_tab : ARRAY [ 0..255 ] of cardinal =
  404. (
  405. $00000000, $77073096, $ee0e612c, $990951ba, $076dc419,
  406. $706af48f, $e963a535, $9e6495a3, $0edb8832, $79dcb8a4,
  407. $e0d5e91e, $97d2d988, $09b64c2b, $7eb17cbd, $e7b82d07,
  408. $90bf1d91, $1db71064, $6ab020f2, $f3b97148, $84be41de,
  409. $1adad47d, $6ddde4eb, $f4d4b551, $83d385c7, $136c9856,
  410. $646ba8c0, $fd62f97a, $8a65c9ec, $14015c4f, $63066cd9,
  411. $fa0f3d63, $8d080df5, $3b6e20c8, $4c69105e, $d56041e4,
  412. $a2677172, $3c03e4d1, $4b04d447, $d20d85fd, $a50ab56b,
  413. $35b5a8fa, $42b2986c, $dbbbc9d6, $acbcf940, $32d86ce3,
  414. $45df5c75, $dcd60dcf, $abd13d59, $26d930ac, $51de003a,
  415. $c8d75180, $bfd06116, $21b4f4b5, $56b3c423, $cfba9599,
  416. $b8bda50f, $2802b89e, $5f058808, $c60cd9b2, $b10be924,
  417. $2f6f7c87, $58684c11, $c1611dab, $b6662d3d, $76dc4190,
  418. $01db7106, $98d220bc, $efd5102a, $71b18589, $06b6b51f,
  419. $9fbfe4a5, $e8b8d433, $7807c9a2, $0f00f934, $9609a88e,
  420. $e10e9818, $7f6a0dbb, $086d3d2d, $91646c97, $e6635c01,
  421. $6b6b51f4, $1c6c6162, $856530d8, $f262004e, $6c0695ed,
  422. $1b01a57b, $8208f4c1, $f50fc457, $65b0d9c6, $12b7e950,
  423. $8bbeb8ea, $fcb9887c, $62dd1ddf, $15da2d49, $8cd37cf3,
  424. $fbd44c65, $4db26158, $3ab551ce, $a3bc0074, $d4bb30e2,
  425. $4adfa541, $3dd895d7, $a4d1c46d, $d3d6f4fb, $4369e96a,
  426. $346ed9fc, $ad678846, $da60b8d0, $44042d73, $33031de5,
  427. $aa0a4c5f, $dd0d7cc9, $5005713c, $270241aa, $be0b1010,
  428. $c90c2086, $5768b525, $206f85b3, $b966d409, $ce61e49f,
  429. $5edef90e, $29d9c998, $b0d09822, $c7d7a8b4, $59b33d17,
  430. $2eb40d81, $b7bd5c3b, $c0ba6cad, $edb88320, $9abfb3b6,
  431. $03b6e20c, $74b1d29a, $ead54739, $9dd277af, $04db2615,
  432. $73dc1683, $e3630b12, $94643b84, $0d6d6a3e, $7a6a5aa8,
  433. $e40ecf0b, $9309ff9d, $0a00ae27, $7d079eb1, $f00f9344,
  434. $8708a3d2, $1e01f268, $6906c2fe, $f762575d, $806567cb,
  435. $196c3671, $6e6b06e7, $fed41b76, $89d32be0, $10da7a5a,
  436. $67dd4acc, $f9b9df6f, $8ebeeff9, $17b7be43, $60b08ed5,
  437. $d6d6a3e8, $a1d1937e, $38d8c2c4, $4fdff252, $d1bb67f1,
  438. $a6bc5767, $3fb506dd, $48b2364b, $d80d2bda, $af0a1b4c,
  439. $36034af6, $41047a60, $df60efc3, $a867df55, $316e8eef,
  440. $4669be79, $cb61b38c, $bc66831a, $256fd2a0, $5268e236,
  441. $cc0c7795, $bb0b4703, $220216b9, $5505262f, $c5ba3bbe,
  442. $b2bd0b28, $2bb45a92, $5cb36a04, $c2d7ffa7, $b5d0cf31,
  443. $2cd99e8b, $5bdeae1d, $9b64c2b0, $ec63f226, $756aa39c,
  444. $026d930a, $9c0906a9, $eb0e363f, $72076785, $05005713,
  445. $95bf4a82, $e2b87a14, $7bb12bae, $0cb61b38, $92d28e9b,
  446. $e5d5be0d, $7cdcefb7, $0bdbdf21, $86d3d2d4, $f1d4e242,
  447. $68ddb3f8, $1fda836e, $81be16cd, $f6b9265b, $6fb077e1,
  448. $18b74777, $88085ae6, $ff0f6a70, $66063bca, $11010b5c,
  449. $8f659eff, $f862ae69, $616bffd3, $166ccf45, $a00ae278,
  450. $d70dd2ee, $4e048354, $3903b3c2, $a7672661, $d06016f7,
  451. $4969474d, $3e6e77db, $aed16a4a, $d9d65adc, $40df0b66,
  452. $37d83bf0, $a9bcae53, $debb9ec5, $47b2cf7f, $30b5ffe9,
  453. $bdbdf21c, $cabac28a, $53b39330, $24b4a3a6, $bad03605,
  454. $cdd70693, $54de5729, $23d967bf, $b3667a2e, $c4614ab8,
  455. $5d681b02, $2a6f2b94, $b40bbe37, $c30c8ea1, $5a05df1b,
  456. $2d02ef8d ); { end crc_32_tab[] }
  457. (***************************************************************************)
  458. {.$I z_generl.pas} {General functions used by both inflate and explode}
  459. {include for unzip.pas: General functions used by both inflate and explode}
  460. {C code by info-zip group, translated to Pascal by Christian Ghisler}
  461. {based on unz51g.zip}
  462. {*********************************** CRC Checking ********************************}
  463. PROCEDURE UpdateCRC ( VAR s : iobuf;len : word );
  464. VAR i : word;
  465. BEGIN
  466. {$ifndef assembler}
  467. If len = 0 then exit;
  468. FOR i := 0 TO Pred ( len ) DO BEGIN
  469. { update running CRC calculation with contents of a buffer }
  470. crc32val := crc_32_tab [ ( byte ( crc32val ) XOR s [ i ] ) AND $ff ] XOR ( crc32val SHR 8 );
  471. END;
  472. {$else}
  473. ASM
  474. les di, s
  475. mov ax, li.lo ( crc32val )
  476. mov dx, li.hi ( crc32val )
  477. mov si, offset crc_32_tab {Segment remains DS!!!}
  478. mov cx, len
  479. OR cx, cx
  480. jz @finished
  481. @again :
  482. mov bl, al {byte(crcval)}
  483. mov al, ah {shift DX:AX by 8 bits to the right}
  484. mov ah, dl
  485. mov dl, dh
  486. XOR dh, dh
  487. XOR bh, bh
  488. XOR bl, es : [ di ] {xor s^}
  489. inc di
  490. SHL bx, 1 {Offset: Index*4}
  491. SHL bx, 1
  492. XOR ax, [ si + bx ]
  493. XOR dx, [ si + bx + 2 ]
  494. dec cx
  495. jnz @again
  496. @finished :
  497. mov li.lo ( crc32val ), ax
  498. mov li.hi ( crc32val ), dx
  499. END;
  500. {$endif}
  501. END;
  502. {************************* tell dialog to show % ******************************}
  503. {$ifdef windows}
  504. PROCEDURE messageloop;
  505. VAR msg : tmsg;
  506. BEGIN
  507. lastusedtime := gettickcount;
  508. WHILE PeekMessage ( Msg, 0, 0, 0, PM_Remove ) DO
  509. IF ( dlghandle = 0 ) OR NOT IsDialogMessage ( dlghandle, msg ) THEN BEGIN
  510. TranslateMessage ( Msg );
  511. DispatchMessage ( Msg );
  512. END;
  513. END;
  514. PROCEDURE showpercent; {use this with the low level functions only !!!}
  515. VAR percent : word;
  516. BEGIN
  517. IF compsize <> 0 THEN BEGIN
  518. percent := reachedsize * 100 DIV compsize;
  519. IF percent > 100 THEN percent := 100;
  520. IF ( percent <> oldpercent ) THEN BEGIN
  521. oldpercent := percent;
  522. IF dlghandle <> 0 THEN BEGIN {Use dialog box for aborting}
  523. {Sendmessage returns directly -> ppercent contains result}
  524. sendmessage ( dlghandle, wm_command, dlgnotify, longint ( @percent ) );
  525. totalabort := ( percent = $FFFF ); {Abort pressed!}
  526. END ELSE
  527. IF dlgnotify <> 0 THEN
  528. totalabort := getasynckeystate ( dlgnotify ) < 0; {break Key pressed!}
  529. END;
  530. END;
  531. END;
  532. {$endif}
  533. {************************** fill inbuf from infile *********************}
  534. PROCEDURE readbuf;
  535. BEGIN
  536. IF reachedsize > compsize + 2 THEN BEGIN {+2: last code is smaller than requested!}
  537. readpos := sizeof ( inbuf ); {Simulates reading -> no blocking}
  538. zipeof := TRUE
  539. END ELSE BEGIN
  540. {$ifdef windows}
  541. messageloop; {Other programs, or in DOS: keypressed?}
  542. showpercent; {Before, because it shows the data processed, not read!}
  543. {$endif}
  544. {$I-}
  545. blockread ( infile, inbuf, sizeof ( inbuf ), readpos );
  546. {$I+}
  547. IF ( ioresult <> 0 ) OR ( readpos = 0 ) THEN BEGIN {readpos=0: kein Fehler gemeldet!!!}
  548. readpos := sizeof ( inbuf ); {Simulates reading -> CRC error}
  549. zipeof := TRUE;
  550. END;
  551. inc ( reachedsize, readpos );
  552. dec ( readpos ); {Reason: index of inbuf starts at 0}
  553. END;
  554. inpos := 0;
  555. END;
  556. {**** read byte, only used by explode ****}
  557. PROCEDURE READBYTE ( VAR bt : byte );
  558. BEGIN
  559. IF inpos > readpos THEN readbuf;
  560. bt := inbuf [ inpos ];
  561. inc ( inpos );
  562. END;
  563. {*********** read at least n bits into the global variable b *************}
  564. PROCEDURE NEEDBITS ( n : byte );
  565. VAR nb : longint;
  566. BEGIN
  567. {$ifndef assembler}
  568. WHILE k < n DO BEGIN
  569. IF inpos > readpos THEN readbuf;
  570. nb := inbuf [ inpos ];
  571. inc ( inpos );
  572. b := b OR nb SHL k;
  573. inc ( k, 8 );
  574. END;
  575. {$else}
  576. ASM
  577. mov si, offset inbuf
  578. mov ch, n
  579. mov cl, k
  580. mov bx, inpos {bx=inpos}
  581. @again :
  582. cmp cl, ch
  583. JAE @finished {k>=n -> finished}
  584. cmp bx, readpos
  585. jg @readbuf
  586. @fullbuf :
  587. mov al, [ si + bx ] {dx:ax=nb}
  588. XOR ah, ah
  589. XOR dx, dx
  590. cmp cl, 8 {cl>=8 -> shift into DX or directly by 1 byte}
  591. JAE @bigger8
  592. SHL ax, cl {Normal shifting!}
  593. jmp @continue
  594. @bigger8 :
  595. mov di, cx {save cx}
  596. mov ah, al {shift by 8}
  597. XOR al, al
  598. sub cl, 8 {8 bits shifted}
  599. @rotate :
  600. OR cl, cl
  601. jz @continue1 {all shifted -> finished}
  602. SHL ah, 1 {al ist empty!}
  603. rcl dx, 1
  604. dec cl
  605. jmp @rotate
  606. @continue1 :
  607. mov cx, di
  608. @continue :
  609. OR li.hi ( b ), dx {b=b or nb shl k}
  610. OR li.lo ( b ), ax
  611. inc bx {inpos}
  612. add cl, 8 {inc k by 8 Bits}
  613. jmp @again
  614. @readbuf :
  615. push si
  616. push cx
  617. call readbuf {readbuf not critical, called only every 2000 bytes}
  618. pop cx
  619. pop si
  620. mov bx, inpos {New inpos}
  621. jmp @fullbuf
  622. @finished :
  623. mov k, cl
  624. mov inpos, bx
  625. END;
  626. {$endif}
  627. END;
  628. {***************** dump n bits no longer needed from global variable b *************}
  629. PROCEDURE DUMPBITS ( n : byte );
  630. BEGIN
  631. {$ifndef assembler}
  632. b := b SHR n;
  633. k := k -n;
  634. {$else}
  635. ASM
  636. mov cl, n
  637. mov ax, li.lo ( b )
  638. mov dx, li.hi ( b )
  639. mov ch, cl
  640. OR ch, ch
  641. jz @finished
  642. @rotate :
  643. SHR dx, 1 {Lower Bit in Carry}
  644. rcr ax, 1
  645. dec ch
  646. jnz @rotate
  647. @finished :
  648. mov li.lo ( b ), ax
  649. mov li.hi ( b ), dx
  650. sub k, cl
  651. END;
  652. {$endif}
  653. END;
  654. {********************* Flush w bytes directly from slide to file ******************}
  655. FUNCTION flush ( w : word ) : boolean;
  656. VAR n : nword; {True wenn OK}
  657. b : boolean;
  658. BEGIN
  659. {$I-}
  660. blockwrite ( outfile, slide [ 0 ], w, n );
  661. {$I+}
  662. b := ( n = w ) AND ( ioresult = 0 ); {True-> alles ok}
  663. UpdateCRC ( iobuf ( pointer ( @slide [ 0 ] ) ^ ), w );
  664. {--}
  665. {$IFDEF FPC}
  666. IF ( b = TRUE ) AND Assigned(ZipReport) {callback report for high level functions}
  667. {$ELSE}
  668. IF ( b = TRUE ) AND ( @ZipReport <> NIL ) {callback report for high level functions}
  669. {$ENDIF}
  670. THEN BEGIN
  671. WITH ZipRec DO BEGIN
  672. Status := file_unzipping;
  673. ZipReport ( n, @ZipRec ); {report the actual bytes written}
  674. END;
  675. END; {report}
  676. flush := b;
  677. END;
  678. {******************************* Break string into tokens ****************************}
  679. VAR
  680. _Token : PChar;
  681. FUNCTION StrTok ( Source : PChar; Token : CHAR ) : PChar;
  682. VAR P : PChar;
  683. BEGIN
  684. IF Source <> NIL THEN _Token := Source;
  685. IF _Token = NIL THEN BEGIN
  686. strTok := NIL;
  687. exit
  688. END;
  689. P := StrScan ( _Token, Token );
  690. StrTok := _Token;
  691. IF P <> NIL THEN BEGIN
  692. P^ := #0;
  693. Inc ( P );
  694. END;
  695. _Token := P;
  696. END;
  697. (***************************************************************************)
  698. {.$I z_huft.pas} {Huffman tree generating and destroying}
  699. {include for unzip.pas: Huffman tree generating and destroying}
  700. {C code by info-zip group, translated to Pascal by Christian Ghisler}
  701. {based on unz51g.zip}
  702. {*************** free huffman tables starting with table where t points to ************}
  703. PROCEDURE huft_free ( t : phuftlist );
  704. VAR p, q : phuftlist;
  705. z : integer;
  706. BEGIN
  707. p := pointer ( t );
  708. WHILE p <> NIL DO BEGIN
  709. dec ( ptrint ( p ), sizeof ( huft ) );
  710. q := p^ [ 0 ].v_t;
  711. z := p^ [ 0 ].v_n; {Size in Bytes, required by TP ***}
  712. freemem ( p, ( z + 1 ) * sizeof ( huft ) );
  713. p := q
  714. END;
  715. END;
  716. {*********** build huffman table from code lengths given by array b^ *******************}
  717. FUNCTION huft_build ( b : pword;n : word;s : word;d, e : pushlist;t : pphuft;VAR m : integer ) : integer;
  718. VAR a : word; {counter for codes of length k}
  719. c : ARRAY [ 0..b_max + 1 ] of word; {bit length count table}
  720. f : word; {i repeats in table every f entries}
  721. g, {max. code length}
  722. h : integer; {table level}
  723. i, {counter, current code}
  724. j : word; {counter}
  725. k : integer; {number of bits in current code}
  726. p : pword; {pointer into c, b and v}
  727. q : phuftlist; {points to current table}
  728. r : huft; {table entry for structure assignment}
  729. u : ARRAY [ 0..b_max ] of phuftlist;{table stack}
  730. v : ARRAY [ 0..n_max ] of word; {values in order of bit length}
  731. w : integer; {bits before this table}
  732. x : ARRAY [ 0..b_max + 1 ] of word; {bit offsets, then code stack}
  733. l : ARRAY [ -1..b_max + 1 ] of word; {l[h] bits in table of level h}
  734. xp : ^word; {pointer into x}
  735. y : integer; {number of dummy codes added}
  736. z : word; {number of entries in current table}
  737. tryagain : boolean; {bool for loop}
  738. pt : phuft; {for test against bad input}
  739. el : word; {length of eob code=code 256}
  740. BEGIN
  741. IF n > 256 THEN el := pword ( longint ( b ) + 256 * sizeof ( word ) ) ^
  742. ELSE el := BMAX;
  743. {generate counts for each bit length}
  744. fillchar ( c, sizeof ( c ), #0 );
  745. p := b; i := n; {p points to array of word}
  746. REPEAT
  747. IF p^ > b_max THEN BEGIN
  748. t^ := NIL;
  749. m := 0;
  750. huft_build := huft_error;
  751. exit
  752. END;
  753. inc ( c [ p^ ] );
  754. inc ( ptrint ( p ), sizeof ( word ) ); {point to next item}
  755. dec ( i );
  756. UNTIL i = 0;
  757. IF c [ 0 ] = n THEN BEGIN
  758. t^ := NIL;
  759. m := 0;
  760. huft_build := huft_complete;
  761. exit
  762. END;
  763. {find minimum and maximum length, bound m by those}
  764. j := 1;
  765. WHILE ( j <= b_max ) AND ( c [ j ] = 0 ) DO inc ( j );
  766. k := j;
  767. IF m < j THEN m := j;
  768. i := b_max;
  769. WHILE ( i > 0 ) AND ( c [ i ] = 0 ) DO dec ( i );
  770. g := i;
  771. IF m > i THEN m := i;
  772. {adjust last length count to fill out codes, if needed}
  773. y := 1 SHL j;
  774. WHILE j < i DO BEGIN
  775. y := y -c [ j ];
  776. IF y < 0 THEN BEGIN
  777. huft_build := huft_error;
  778. exit
  779. END;
  780. y := y SHL 1;
  781. inc ( j );
  782. END;
  783. dec ( y, c [ i ] );
  784. IF y < 0 THEN BEGIN
  785. huft_build := huft_error;
  786. exit
  787. END;
  788. inc ( c [ i ], y );
  789. {generate starting offsets into the value table for each length}
  790. x [ 1 ] := 0;
  791. j := 0;
  792. p := @c; inc ( ptrint ( p ), sizeof ( word ) );
  793. xp := @x;inc ( ptrint ( xp ), 2 * sizeof ( word ) );
  794. dec ( i );
  795. WHILE i <> 0 DO BEGIN
  796. inc ( j, p^ );
  797. xp^ := j;
  798. inc ( ptrint ( p ), 2 );
  799. inc ( ptrint ( xp ), 2 );
  800. dec ( i );
  801. END;
  802. {make table of values in order of bit length}
  803. p := b; i := 0;
  804. REPEAT
  805. j := p^;
  806. inc ( ptrint ( p ), sizeof ( word ) );
  807. IF j <> 0 THEN BEGIN
  808. v [ x [ j ] ] := i;
  809. inc ( x [ j ] );
  810. END;
  811. inc ( i );
  812. UNTIL i >= n;
  813. {generate huffman codes and for each, make the table entries}
  814. x [ 0 ] := 0; i := 0;
  815. p := @v;
  816. h := -1;
  817. l [ -1 ] := 0;
  818. w := 0;
  819. u [ 0 ] := NIL;
  820. q := NIL;
  821. z := 0;
  822. {go through the bit lengths (k already is bits in shortest code)}
  823. FOR k := k TO g DO BEGIN
  824. FOR a := c [ k ] DOWNTO 1 DO BEGIN
  825. {here i is the huffman code of length k bits for value p^}
  826. WHILE k > w + l [ h ] DO BEGIN
  827. inc ( w, l [ h ] ); {Length of tables to this position}
  828. inc ( h );
  829. z := g -w;
  830. IF z > m THEN z := m;
  831. j := k -w;
  832. f := 1 SHL j;
  833. IF f > a + 1 THEN BEGIN
  834. dec ( f, a + 1 );
  835. xp := @c [ k ];
  836. inc ( j );
  837. tryagain := TRUE;
  838. WHILE ( j < z ) AND tryagain DO BEGIN
  839. f := f SHL 1;
  840. inc ( ptrint ( xp ), sizeof ( word ) );
  841. IF f <= xp^ THEN tryagain := FALSE
  842. ELSE BEGIN
  843. dec ( f, xp^ );
  844. inc ( j );
  845. END;
  846. END;
  847. END;
  848. IF ( w + j > el ) AND ( w < el ) THEN
  849. j := el -w; {Make eob code end at table}
  850. IF w = 0 THEN BEGIN
  851. j := m; {*** Fix: main table always m bits!}
  852. END;
  853. z := 1 SHL j;
  854. l [ h ] := j;
  855. {allocate and link new table}
  856. getmem ( q, ( z + 1 ) * sizeof ( huft ) );
  857. IF q = NIL THEN BEGIN
  858. IF h <> 0 THEN huft_free ( pointer ( u [ 0 ] ) );
  859. huft_build := huft_outofmem;
  860. exit
  861. END;
  862. fillchar ( q^, ( z + 1 ) * sizeof ( huft ), #0 );
  863. q^ [ 0 ].v_n := z; {Size of table, needed in freemem ***}
  864. t^ := @q^ [ 1 ]; {first item starts at 1}
  865. t := @q^ [ 0 ].v_t;
  866. t^ := NIL;
  867. q := @q^ [ 1 ]; {pointer(longint(q)+sizeof(huft));} {???}
  868. u [ h ] := q;
  869. {connect to last table, if there is one}
  870. IF h <> 0 THEN BEGIN
  871. x [ h ] := i;
  872. r.b := l [ h -1 ];
  873. r.e := 16 + j;
  874. r.v_t := q;
  875. j := ( i AND ( ( 1 SHL w ) -1 ) ) SHR ( w -l [ h -1 ] );
  876. {test against bad input!}
  877. pt := phuft ( longint ( u [ h -1 ] ) -sizeof ( huft ) );
  878. IF j > pt^.v_n THEN BEGIN
  879. huft_free ( pointer ( u [ 0 ] ) );
  880. huft_build := huft_error;
  881. exit
  882. END;
  883. pt := @u [ h -1 ]^ [ j ];
  884. pt^ := r;
  885. END;
  886. END;
  887. {set up table entry in r}
  888. r.b := word ( k -w );
  889. r.v_t := NIL; {Unused} {***********}
  890. IF longint ( p ) >= longint ( @v [ n ] ) THEN r.e := 99
  891. ELSE IF p^ < s THEN BEGIN
  892. IF p^ < 256 THEN r.e := 16 ELSE r.e := 15;
  893. r.v_n := p^;
  894. inc ( ptrint ( p ), sizeof ( word ) );
  895. END ELSE BEGIN
  896. IF ( d = NIL ) OR ( e = NIL ) THEN BEGIN
  897. huft_free ( pointer ( u [ 0 ] ) );
  898. huft_build := huft_error;
  899. exit
  900. END;
  901. r.e := word ( e^ [ p^ -s ] );
  902. r.v_n := d^ [ p^ -s ];
  903. inc ( ptrint ( p ), sizeof ( word ) );
  904. END;
  905. {fill code like entries with r}
  906. f := 1 SHL ( k -w );
  907. j := i SHR w;
  908. WHILE j < z DO BEGIN
  909. q^ [ j ] := r;
  910. inc ( j, f );
  911. END;
  912. {backwards increment the k-bit code i}
  913. j := 1 SHL ( k -1 );
  914. WHILE ( i AND j ) <> 0 DO BEGIN
  915. {i:=i^j;}
  916. i := i XOR j;
  917. j := j SHR 1;
  918. END;
  919. i := i XOR j;
  920. {backup over finished tables}
  921. WHILE ( ( i AND ( ( 1 SHL w ) -1 ) ) <> x [ h ] ) DO BEGIN
  922. dec ( h );
  923. dec ( w, l [ h ] ); {Size of previous table!}
  924. END;
  925. END;
  926. END;
  927. IF ( y <> 0 ) AND ( g <> 1 ) THEN huft_build := huft_incomplete
  928. ELSE huft_build := huft_complete;
  929. END;
  930. (***************************************************************************)
  931. {.$I z_inflat.pas} {Inflate deflated file}
  932. {include for unzip.pas: Inflate deflated file}
  933. {C code by info-zip group, translated to Pascal by Christian Ghisler}
  934. {based on unz51g.zip}
  935. FUNCTION inflate_codes ( tl, td : phuftlist;bl, bd : integer ) : integer;
  936. VAR
  937. n, d, e1, {length and index for copy}
  938. ml, md : longint; {masks for bl and bd bits}
  939. t : phuft; {pointer to table entry}
  940. e : byte; {table entry flag/number of extra bits}
  941. BEGIN
  942. { inflate the coded data }
  943. ml := mask_bits [ bl ]; {precompute masks for speed}
  944. md := mask_bits [ bd ];
  945. WHILE NOT ( totalabort OR zipeof ) DO BEGIN
  946. NEEDBITS ( bl );
  947. t := @tl^ [ b AND ml ];
  948. e := t^.e;
  949. IF e > 16 THEN REPEAT {then it's a literal}
  950. IF e = 99 THEN BEGIN
  951. inflate_codes := unzip_ZipFileErr;
  952. exit
  953. END;
  954. DUMPBITS ( t^.b );
  955. dec ( e, 16 );
  956. NEEDBITS ( e );
  957. t := @t^.v_t^ [ b AND mask_bits [ e ] ];
  958. e := t^.e;
  959. UNTIL e <= 16;
  960. DUMPBITS ( t^.b );
  961. IF e = 16 THEN BEGIN
  962. slide [ w ] := char ( t^.v_n );
  963. inc ( w );
  964. IF w = WSIZE THEN BEGIN
  965. IF NOT flush ( w ) THEN BEGIN
  966. inflate_codes := unzip_WriteErr;
  967. exit;
  968. END;
  969. w := 0
  970. END;
  971. END ELSE BEGIN {it's an EOB or a length}
  972. IF e = 15 THEN BEGIN {Ende} {exit if end of block}
  973. inflate_codes := unzip_Ok;
  974. exit;
  975. END;
  976. NEEDBITS ( e ); {get length of block to copy}
  977. n := t^.v_n + ( b AND mask_bits [ e ] );
  978. DUMPBITS ( e );
  979. NEEDBITS ( bd ); {decode distance of block to copy}
  980. t := @td^ [ b AND md ];
  981. e := t^.e;
  982. IF e > 16 THEN REPEAT
  983. IF e = 99 THEN BEGIN
  984. inflate_codes := unzip_ZipFileErr;
  985. exit
  986. END;
  987. DUMPBITS ( t^.b );
  988. dec ( e, 16 );
  989. NEEDBITS ( e );
  990. t := @t^.v_t^ [ b AND mask_bits [ e ] ];
  991. e := t^.e;
  992. UNTIL e <= 16;
  993. DUMPBITS ( t^.b );
  994. NEEDBITS ( e );
  995. d := w -t^.v_n -b AND mask_bits [ e ];
  996. DUMPBITS ( e );
  997. {do the copy}
  998. REPEAT
  999. d := d AND ( WSIZE -1 );
  1000. IF d > w THEN e1 := WSIZE -d
  1001. ELSE e1 := WSIZE -w;
  1002. IF e1 > n THEN e1 := n;
  1003. dec ( n, e1 );
  1004. IF ( longint(w) -d >= e1 ) THEN BEGIN
  1005. move ( slide [ d ], slide [ w ], e1 );
  1006. inc ( w, e1 );
  1007. inc ( d, e1 );
  1008. END ELSE REPEAT
  1009. slide [ w ] := slide [ d ];
  1010. inc ( w );
  1011. inc ( d );
  1012. dec ( e1 );
  1013. UNTIL ( e1 = 0 );
  1014. IF w = WSIZE THEN BEGIN
  1015. IF NOT flush ( w ) THEN BEGIN
  1016. inflate_codes := unzip_WriteErr;
  1017. exit;
  1018. END;
  1019. w := 0;
  1020. END;
  1021. UNTIL n = 0;
  1022. END;
  1023. END;
  1024. IF totalabort THEN
  1025. inflate_codes := unzip_userabort
  1026. ELSE
  1027. inflate_codes := unzip_readErr;
  1028. END;
  1029. {**************************** "decompress" stored block **************************}
  1030. FUNCTION inflate_stored : integer;
  1031. VAR n : word; {number of bytes in block}
  1032. BEGIN
  1033. {go to byte boundary}
  1034. n := k AND 7;
  1035. dumpbits ( n );
  1036. {get the length and its complement}
  1037. NEEDBITS ( 16 );
  1038. n := b AND $ffff;
  1039. DUMPBITS ( 16 );
  1040. NEEDBITS ( 16 );
  1041. IF ( n <> ( NOT b ) AND $ffff ) THEN BEGIN
  1042. inflate_stored := unzip_zipFileErr;
  1043. exit
  1044. END;
  1045. DUMPBITS ( 16 );
  1046. WHILE ( n > 0 ) AND NOT ( totalabort OR zipeof ) DO BEGIN {read and output the compressed data}
  1047. dec ( n );
  1048. NEEDBITS ( 8 );
  1049. slide [ w ] := char ( b );
  1050. inc ( w );
  1051. IF w = WSIZE THEN BEGIN
  1052. IF NOT flush ( w ) THEN BEGIN
  1053. inflate_stored := unzip_WriteErr;
  1054. exit
  1055. END;
  1056. w := 0;
  1057. END;
  1058. DUMPBITS ( 8 );
  1059. END;
  1060. IF totalabort THEN inflate_stored := unzip_UserAbort
  1061. ELSE IF zipeof THEN inflate_stored := unzip_readErr
  1062. ELSE inflate_stored := unzip_Ok;
  1063. END;
  1064. {**************************** decompress fixed block **************************}
  1065. FUNCTION inflate_fixed : integer;
  1066. VAR i : integer; {temporary variable}
  1067. tl, {literal/length code table}
  1068. td : phuftlist; {distance code table}
  1069. bl, bd : integer; {lookup bits for tl/bd}
  1070. l : ARRAY [ 0..287 ] of word; {length list for huft_build}
  1071. BEGIN
  1072. {set up literal table}
  1073. FOR i := 0 TO 143 DO l [ i ] := 8;
  1074. FOR i := 144 TO 255 DO l [ i ] := 9;
  1075. FOR i := 256 TO 279 DO l [ i ] := 7;
  1076. FOR i := 280 TO 287 DO l [ i ] := 8; {make a complete, but wrong code set}
  1077. bl := 7;
  1078. i := huft_build ( pword ( @l ), 288, 257, pushlist ( @cplens ), pushlist ( @cplext ), @tl, bl );
  1079. IF i <> huft_complete THEN BEGIN
  1080. inflate_fixed := i;
  1081. exit
  1082. END;
  1083. FOR i := 0 TO 29 DO l [ i ] := 5; {make an incomplete code set}
  1084. bd := 5;
  1085. i := huft_build ( pword ( @l ), 30, 0, pushlist ( @cpdist ), pushlist ( @cpdext ), @td, bd );
  1086. IF i > huft_incomplete THEN BEGIN
  1087. huft_free ( tl );
  1088. inflate_fixed := unzip_ZipFileErr;
  1089. exit
  1090. END;
  1091. inflate_fixed := inflate_codes ( tl, td, bl, bd );
  1092. huft_free ( tl );
  1093. huft_free ( td );
  1094. END;
  1095. {**************************** decompress dynamic block **************************}
  1096. FUNCTION inflate_dynamic : integer;
  1097. VAR i : integer; {temporary variables}
  1098. j,
  1099. l, {last length}
  1100. m, {mask for bit length table}
  1101. n : word; {number of lengths to get}
  1102. tl, {literal/length code table}
  1103. td : phuftlist; {distance code table}
  1104. bl, bd : integer; {lookup bits for tl/bd}
  1105. nb, nl, nd : word; {number of bit length/literal length/distance codes}
  1106. ll : ARRAY [ 0..288 + 32 -1 ] of word; {literal/length and distance code lengths}
  1107. BEGIN
  1108. {read in table lengths}
  1109. NEEDBITS ( 5 );
  1110. nl := 257 + word ( b ) AND $1f;
  1111. DUMPBITS ( 5 );
  1112. NEEDBITS ( 5 );
  1113. nd := 1 + word ( b ) AND $1f;
  1114. DUMPBITS ( 5 );
  1115. NEEDBITS ( 4 );
  1116. nb := 4 + word ( b ) AND $f;
  1117. DUMPBITS ( 4 );
  1118. IF ( nl > 288 ) OR ( nd > 32 ) THEN BEGIN
  1119. inflate_dynamic := 1;
  1120. exit
  1121. END;
  1122. fillchar ( ll, sizeof ( ll ), #0 );
  1123. {read in bit-length-code lengths}
  1124. FOR j := 0 TO nb -1 DO BEGIN
  1125. NEEDBITS ( 3 );
  1126. ll [ border [ j ] ] := b AND 7;
  1127. DUMPBITS ( 3 );
  1128. END;
  1129. FOR j := nb TO 18 DO ll [ border [ j ] ] := 0;
  1130. {build decoding table for trees--single level, 7 bit lookup}
  1131. bl := 7;
  1132. i := huft_build ( pword ( @ll ), 19, 19, NIL, NIL, @tl, bl );
  1133. IF i <> huft_complete THEN BEGIN
  1134. IF i = huft_incomplete THEN huft_free ( tl ); {other errors: already freed}
  1135. inflate_dynamic := unzip_ZipFileErr;
  1136. exit
  1137. END;
  1138. {read in literal and distance code lengths}
  1139. n := nl + nd;
  1140. m := mask_bits [ bl ];
  1141. i := 0; l := 0;
  1142. WHILE word ( i ) < n DO BEGIN
  1143. NEEDBITS ( bl );
  1144. td := @tl^ [ b AND m ];
  1145. j := phuft ( td ) ^.b;
  1146. DUMPBITS ( j );
  1147. j := phuft ( td ) ^.v_n;
  1148. IF j < 16 THEN BEGIN {length of code in bits (0..15)}
  1149. l := j; {ave last length in l}
  1150. ll [ i ] := l;
  1151. inc ( i )
  1152. END ELSE IF j = 16 THEN BEGIN {repeat last length 3 to 6 times}
  1153. NEEDBITS ( 2 );
  1154. j := 3 + b AND 3;
  1155. DUMPBITS ( 2 );
  1156. IF i + j > n THEN BEGIN
  1157. inflate_dynamic := 1;
  1158. exit
  1159. END;
  1160. WHILE j > 0 DO BEGIN
  1161. ll [ i ] := l;
  1162. dec ( j );
  1163. inc ( i );
  1164. END;
  1165. END ELSE IF j = 17 THEN BEGIN {3 to 10 zero length codes}
  1166. NEEDBITS ( 3 );
  1167. j := 3 + b AND 7;
  1168. DUMPBITS ( 3 );
  1169. IF i + j > n THEN BEGIN
  1170. inflate_dynamic := 1;
  1171. exit
  1172. END;
  1173. WHILE j > 0 DO BEGIN
  1174. ll [ i ] := 0;
  1175. inc ( i );
  1176. dec ( j );
  1177. END;
  1178. l := 0;
  1179. END ELSE BEGIN {j == 18: 11 to 138 zero length codes}
  1180. NEEDBITS ( 7 );
  1181. j := 11 + b AND $7f;
  1182. DUMPBITS ( 7 );
  1183. IF i + j > n THEN BEGIN
  1184. inflate_dynamic := unzip_zipfileErr;
  1185. exit
  1186. END;
  1187. WHILE j > 0 DO BEGIN
  1188. ll [ i ] := 0;
  1189. dec ( j );
  1190. inc ( i );
  1191. END;
  1192. l := 0;
  1193. END;
  1194. END;
  1195. huft_free ( tl ); {free decoding table for trees}
  1196. {build the decoding tables for literal/length and distance codes}
  1197. bl := lbits;
  1198. i := huft_build ( pword ( @ll ), nl, 257, pushlist ( @cplens ), pushlist ( @cplext ), @tl, bl );
  1199. IF i <> huft_complete THEN BEGIN
  1200. IF i = huft_incomplete THEN huft_free ( tl );
  1201. inflate_dynamic := unzip_ZipFileErr;
  1202. exit
  1203. END;
  1204. bd := dbits;
  1205. i := huft_build ( pword ( @ll [ nl ] ), nd, 0, pushlist ( @cpdist ), pushlist ( @cpdext ), @td, bd );
  1206. IF i > huft_incomplete THEN BEGIN {pkzip bug workaround}
  1207. IF i = huft_incomplete THEN huft_free ( td );
  1208. huft_free ( tl );
  1209. inflate_dynamic := unzip_ZipFileErr;
  1210. exit
  1211. END;
  1212. {decompress until an end-of-block code}
  1213. inflate_dynamic := inflate_codes ( tl, td, bl, bd );
  1214. huft_free ( tl );
  1215. huft_free ( td );
  1216. END;
  1217. {**************************** decompress a block ******************************}
  1218. FUNCTION inflate_block ( VAR e : integer ) : integer;
  1219. VAR t : word; {block type}
  1220. BEGIN
  1221. NEEDBITS ( 1 );
  1222. e := b AND 1;
  1223. DUMPBITS ( 1 );
  1224. NEEDBITS ( 2 );
  1225. t := b AND 3;
  1226. DUMPBITS ( 2 );
  1227. CASE t of
  1228. 2 : inflate_block := inflate_dynamic;
  1229. 0 : inflate_block := inflate_stored;
  1230. 1 : inflate_block := inflate_fixed;
  1231. ELSE
  1232. inflate_block := unzip_ZipFileErr; {bad block type}
  1233. END;
  1234. END;
  1235. {**************************** decompress an inflated entry **************************}
  1236. FUNCTION inflate : integer;
  1237. VAR e, {last block flag}
  1238. r : integer; {result code}
  1239. BEGIN
  1240. inpos := 0; {Input buffer position}
  1241. readpos := -1; {Nothing read}
  1242. {initialize window, bit buffer}
  1243. w := 0;
  1244. k := 0;
  1245. b := 0;
  1246. {decompress until the last block}
  1247. REPEAT
  1248. r := inflate_block ( e );
  1249. IF r <> 0 THEN BEGIN
  1250. inflate := r;
  1251. exit
  1252. END;
  1253. UNTIL e <> 0;
  1254. {flush out slide}
  1255. IF NOT flush ( w ) THEN inflate := unzip_WriteErr
  1256. ELSE inflate := unzip_Ok;
  1257. END;
  1258. (***************************************************************************)
  1259. {.$I z_copyst.pas} {Copy stored file}
  1260. {include for unzip.pas: Copy stored file}
  1261. {C code by info-zip group, translated to Pascal by Christian Ghisler}
  1262. {based on unz51g.zip}
  1263. {************************* copy stored file ************************************}
  1264. FUNCTION copystored : integer;
  1265. VAR readin : longint;
  1266. outcnt : nword;
  1267. BEGIN
  1268. WHILE ( reachedsize < compsize ) AND NOT totalabort DO BEGIN
  1269. readin := compsize -reachedsize;
  1270. IF readin > wsize THEN readin := wsize;
  1271. {$I-}
  1272. blockread ( infile, slide [ 0 ], readin, outcnt ); {Use slide as buffer}
  1273. {$I+}
  1274. IF ( outcnt <> readin ) OR ( ioresult <> 0 ) THEN BEGIN
  1275. copystored := unzip_ReadErr;
  1276. exit
  1277. END;
  1278. IF NOT flush ( outcnt ) THEN BEGIN {Flushoutput takes care of CRC too}
  1279. copystored := unzip_WriteErr;
  1280. exit
  1281. END;
  1282. inc ( reachedsize, outcnt );
  1283. {$ifdef windows}
  1284. messageloop; {Other programs, or in DOS: keypressed?}
  1285. showpercent;
  1286. {$endif}
  1287. END;
  1288. IF NOT totalabort THEN
  1289. copystored := unzip_Ok
  1290. ELSE
  1291. copystored := unzip_Userabort;
  1292. END;
  1293. (***************************************************************************)
  1294. {.$I z_explod.pas} {Explode imploded file}
  1295. {include for unzip.pas: Explode imploded file}
  1296. {C code by info-zip group, translated to Pascal by Christian Ghisler}
  1297. {based on unz51g.zip}
  1298. {************************************* explode ********************************}
  1299. {*********************************** read in tree *****************************}
  1300. FUNCTION get_tree ( l : pword;n : word ) : integer;
  1301. VAR i, k, j, b : word;
  1302. bytebuf : byte;
  1303. BEGIN
  1304. READBYTE ( bytebuf );
  1305. i := bytebuf;
  1306. inc ( i );
  1307. k := 0;
  1308. REPEAT
  1309. READBYTE ( bytebuf );
  1310. j := bytebuf;
  1311. b := ( j AND $F ) + 1;
  1312. j := ( ( j AND $F0 ) SHR 4 ) + 1;
  1313. IF ( k + j ) > n THEN BEGIN
  1314. get_tree := 4;
  1315. exit
  1316. END;
  1317. REPEAT
  1318. l^ := b;
  1319. inc ( ptrint ( l ), sizeof ( word ) );
  1320. inc ( k );
  1321. dec ( j );
  1322. UNTIL j = 0;
  1323. dec ( i );
  1324. UNTIL i = 0;
  1325. IF k <> n THEN get_tree := 4 ELSE get_tree := 0;
  1326. END;
  1327. {******************exploding, method: 8k slide, 3 trees ***********************}
  1328. FUNCTION explode_lit8 ( tb, tl, td : phuftlist;bb, bl, bd : integer ) : integer;
  1329. VAR s : longint;
  1330. e : word;
  1331. n, d : word;
  1332. w : word;
  1333. t : phuft;
  1334. mb, ml, md : word;
  1335. u : word;
  1336. BEGIN
  1337. b := 0; k := 0; w := 0;
  1338. u := 1;
  1339. mb := mask_bits [ bb ];
  1340. ml := mask_bits [ bl ];
  1341. md := mask_bits [ bd ];
  1342. s := uncompsize;
  1343. WHILE ( s > 0 ) AND NOT ( totalabort OR zipeof ) DO BEGIN
  1344. NEEDBITS ( 1 );
  1345. IF ( b AND 1 ) <> 0 THEN BEGIN {Litteral}
  1346. DUMPBITS ( 1 );
  1347. dec ( s );
  1348. NEEDBITS ( bb );
  1349. t := @tb^ [ ( NOT b ) AND mb ];
  1350. e := t^.e;
  1351. IF e > 16 THEN REPEAT
  1352. IF e = 99 THEN BEGIN
  1353. explode_lit8 := unzip_ZipFileErr;
  1354. exit
  1355. END;
  1356. DUMPBITS ( t^.b );
  1357. dec ( e, 16 );
  1358. NEEDBITS ( e );
  1359. t := @t^.v_t^ [ ( NOT b ) AND mask_bits [ e ] ];
  1360. e := t^.e;
  1361. UNTIL e <= 16;
  1362. DUMPBITS ( t^.b );
  1363. slide [ w ] := char ( t^.v_n );
  1364. inc ( w );
  1365. IF w = WSIZE THEN BEGIN
  1366. IF NOT flush ( w ) THEN BEGIN
  1367. explode_lit8 := unzip_WriteErr;
  1368. exit
  1369. END;
  1370. w := 0; u := 0;
  1371. END;
  1372. END ELSE BEGIN
  1373. DUMPBITS ( 1 );
  1374. NEEDBITS ( 7 );
  1375. d := b AND $7F;
  1376. DUMPBITS ( 7 );
  1377. NEEDBITS ( bd );
  1378. t := @td^ [ ( NOT b ) AND md ];
  1379. e := t^.e;
  1380. IF e > 16 THEN REPEAT
  1381. IF e = 99 THEN BEGIN
  1382. explode_lit8 := unzip_ZipFileErr;
  1383. exit
  1384. END;
  1385. DUMPBITS ( t^.b );
  1386. dec ( e, 16 );
  1387. NEEDBITS ( e );
  1388. t := @t^.v_t^ [ ( NOT b ) AND mask_bits [ e ] ];
  1389. e := t^.e;
  1390. UNTIL e <= 16;
  1391. DUMPBITS ( t^.b );
  1392. d := w -d -t^.v_n;
  1393. NEEDBITS ( bl );
  1394. t := @tl^ [ ( NOT b ) AND ml ];
  1395. e := t^.e;
  1396. IF e > 16 THEN REPEAT
  1397. IF e = 99 THEN BEGIN
  1398. explode_lit8 := unzip_ZipFileErr;
  1399. exit
  1400. END;
  1401. DUMPBITS ( t^.b );
  1402. dec ( e, 16 );
  1403. NEEDBITS ( e );
  1404. t := @t^.v_t^ [ ( NOT b ) AND mask_bits [ e ] ];
  1405. e := t^.e;
  1406. UNTIL e <= 16;
  1407. DUMPBITS ( t^.b );
  1408. n := t^.v_n;
  1409. IF e <> 0 THEN BEGIN
  1410. NEEDBITS ( 8 );
  1411. inc ( n, byte ( b ) AND $ff );
  1412. DUMPBITS ( 8 );
  1413. END;
  1414. dec ( s, n );
  1415. REPEAT
  1416. d := d AND pred ( WSIZE );
  1417. IF d > w THEN e := WSIZE -d ELSE e := WSIZE -w;
  1418. IF e > n THEN e := n;
  1419. dec ( n, e );
  1420. IF ( u <> 0 ) AND ( w <= d ) THEN BEGIN
  1421. fillchar ( slide [ w ], e, #0 );
  1422. inc ( w, e );
  1423. inc ( d, e );
  1424. END ELSE IF ( w -d >= e ) THEN BEGIN
  1425. move ( slide [ d ], slide [ w ], e );
  1426. inc ( w, e );
  1427. inc ( d, e );
  1428. END ELSE REPEAT
  1429. slide [ w ] := slide [ d ];
  1430. inc ( w );
  1431. inc ( d );
  1432. dec ( e );
  1433. UNTIL e = 0;
  1434. IF w = WSIZE THEN BEGIN
  1435. IF NOT flush ( w ) THEN BEGIN
  1436. explode_lit8 := unzip_WriteErr;
  1437. exit
  1438. END;
  1439. w := 0; u := 0;
  1440. END;
  1441. UNTIL n = 0;
  1442. END;
  1443. END;
  1444. IF totalabort THEN explode_lit8 := unzip_userabort
  1445. ELSE
  1446. IF NOT flush ( w ) THEN explode_lit8 := unzip_WriteErr
  1447. ELSE
  1448. IF zipeof THEN explode_lit8 := unzip_readErr
  1449. ELSE
  1450. explode_lit8 := unzip_Ok;
  1451. END;
  1452. {******************exploding, method: 4k slide, 3 trees ***********************}
  1453. FUNCTION explode_lit4 ( tb, tl, td : phuftlist;bb, bl, bd : integer ) : integer;
  1454. VAR s : longint;
  1455. e : word;
  1456. n, d : word;
  1457. w : word;
  1458. t : phuft;
  1459. mb, ml, md : word;
  1460. u : word;
  1461. BEGIN
  1462. b := 0; k := 0; w := 0;
  1463. u := 1;
  1464. mb := mask_bits [ bb ];
  1465. ml := mask_bits [ bl ];
  1466. md := mask_bits [ bd ];
  1467. s := uncompsize;
  1468. WHILE ( s > 0 ) AND NOT ( totalabort OR zipeof ) DO BEGIN
  1469. NEEDBITS ( 1 );
  1470. IF ( b AND 1 ) <> 0 THEN BEGIN {Litteral}
  1471. DUMPBITS ( 1 );
  1472. dec ( s );
  1473. NEEDBITS ( bb );
  1474. t := @tb^ [ ( NOT b ) AND mb ];
  1475. e := t^.e;
  1476. IF e > 16 THEN REPEAT
  1477. IF e = 99 THEN BEGIN
  1478. explode_lit4 := unzip_ZipFileErr;
  1479. exit
  1480. END;
  1481. DUMPBITS ( t^.b );
  1482. dec ( e, 16 );
  1483. NEEDBITS ( e );
  1484. t := @t^.v_t^ [ ( NOT b ) AND mask_bits [ e ] ];
  1485. e := t^.e;
  1486. UNTIL e <= 16;
  1487. DUMPBITS ( t^.b );
  1488. slide [ w ] := char ( t^.v_n );
  1489. inc ( w );
  1490. IF w = WSIZE THEN BEGIN
  1491. IF NOT flush ( w ) THEN BEGIN
  1492. explode_lit4 := unzip_WriteErr;
  1493. exit
  1494. END;
  1495. w := 0; u := 0;
  1496. END;
  1497. END ELSE BEGIN
  1498. DUMPBITS ( 1 );
  1499. NEEDBITS ( 6 );
  1500. d := b AND $3F;
  1501. DUMPBITS ( 6 );
  1502. NEEDBITS ( bd );
  1503. t := @td^ [ ( NOT b ) AND md ];
  1504. e := t^.e;
  1505. IF e > 16 THEN REPEAT
  1506. IF e = 99 THEN BEGIN
  1507. explode_lit4 := unzip_ZipFileErr;
  1508. exit
  1509. END;
  1510. DUMPBITS ( t^.b );
  1511. dec ( e, 16 );
  1512. NEEDBITS ( e );
  1513. t := @t^.v_t^ [ ( NOT b ) AND mask_bits [ e ] ];
  1514. e := t^.e;
  1515. UNTIL e <= 16;
  1516. DUMPBITS ( t^.b );
  1517. d := w -d -t^.v_n;
  1518. NEEDBITS ( bl );
  1519. t := @tl^ [ ( NOT b ) AND ml ];
  1520. e := t^.e;
  1521. IF e > 16 THEN REPEAT
  1522. IF e = 99 THEN BEGIN
  1523. explode_lit4 := unzip_ZipFileErr;
  1524. exit
  1525. END;
  1526. DUMPBITS ( t^.b );
  1527. dec ( e, 16 );
  1528. NEEDBITS ( e );
  1529. t := @t^.v_t^ [ ( NOT b ) AND mask_bits [ e ] ];
  1530. e := t^.e;
  1531. UNTIL e <= 16;
  1532. DUMPBITS ( t^.b );
  1533. n := t^.v_n;
  1534. IF e <> 0 THEN BEGIN
  1535. NEEDBITS ( 8 );
  1536. inc ( n, b AND $ff );
  1537. DUMPBITS ( 8 );
  1538. END;
  1539. dec ( s, n );
  1540. REPEAT
  1541. d := d AND pred ( WSIZE );
  1542. IF d > w THEN e := WSIZE -d ELSE e := WSIZE -w;
  1543. IF e > n THEN e := n;
  1544. dec ( n, e );
  1545. IF ( u <> 0 ) AND ( w <= d ) THEN BEGIN
  1546. fillchar ( slide [ w ], e, #0 );
  1547. inc ( w, e );
  1548. inc ( d, e );
  1549. END ELSE IF ( w -d >= e ) THEN BEGIN
  1550. move ( slide [ d ], slide [ w ], e );
  1551. inc ( w, e );
  1552. inc ( d, e );
  1553. END ELSE REPEAT
  1554. slide [ w ] := slide [ d ];
  1555. inc ( w );
  1556. inc ( d );
  1557. dec ( e );
  1558. UNTIL e = 0;
  1559. IF w = WSIZE THEN BEGIN
  1560. IF NOT flush ( w ) THEN BEGIN
  1561. explode_lit4 := unzip_WriteErr;
  1562. exit
  1563. END;
  1564. w := 0; u := 0;
  1565. END;
  1566. UNTIL n = 0;
  1567. END;
  1568. END;
  1569. IF totalabort THEN explode_lit4 := unzip_userabort
  1570. ELSE
  1571. IF NOT flush ( w ) THEN explode_lit4 := unzip_WriteErr
  1572. ELSE
  1573. IF zipeof THEN explode_lit4 := unzip_readErr
  1574. ELSE explode_lit4 := unzip_Ok;
  1575. END;
  1576. {******************exploding, method: 8k slide, 2 trees ***********************}
  1577. FUNCTION explode_nolit8 ( tl, td : phuftlist;bl, bd : integer ) : integer;
  1578. VAR s : longint;
  1579. e : word;
  1580. n, d : word;
  1581. w : word;
  1582. t : phuft;
  1583. ml, md : word;
  1584. u : word;
  1585. BEGIN
  1586. b := 0; k := 0; w := 0;
  1587. u := 1;
  1588. ml := mask_bits [ bl ];
  1589. md := mask_bits [ bd ];
  1590. s := uncompsize;
  1591. WHILE ( s > 0 ) AND NOT ( totalabort OR zipeof ) DO BEGIN
  1592. NEEDBITS ( 1 );
  1593. IF ( b AND 1 ) <> 0 THEN BEGIN {Litteral}
  1594. DUMPBITS ( 1 );
  1595. dec ( s );
  1596. NEEDBITS ( 8 );
  1597. slide [ w ] := char ( b );
  1598. inc ( w );
  1599. IF w = WSIZE THEN BEGIN
  1600. IF NOT flush ( w ) THEN BEGIN
  1601. explode_nolit8 := unzip_WriteErr;
  1602. exit
  1603. END;
  1604. w := 0; u := 0;
  1605. END;
  1606. DUMPBITS ( 8 );
  1607. END ELSE BEGIN
  1608. DUMPBITS ( 1 );
  1609. NEEDBITS ( 7 );
  1610. d := b AND $7F;
  1611. DUMPBITS ( 7 );
  1612. NEEDBITS ( bd );
  1613. t := @td^ [ ( NOT b ) AND md ];
  1614. e := t^.e;
  1615. IF e > 16 THEN REPEAT
  1616. IF e = 99 THEN BEGIN
  1617. explode_nolit8 := unzip_ZipFileErr;
  1618. exit
  1619. END;
  1620. DUMPBITS ( t^.b );
  1621. dec ( e, 16 );
  1622. NEEDBITS ( e );
  1623. t := @t^.v_t^ [ ( NOT b ) AND mask_bits [ e ] ];
  1624. e := t^.e;
  1625. UNTIL e <= 16;
  1626. DUMPBITS ( t^.b );
  1627. d := w -d -t^.v_n;
  1628. NEEDBITS ( bl );
  1629. t := @tl^ [ ( NOT b ) AND ml ];
  1630. e := t^.e;
  1631. IF e > 16 THEN REPEAT
  1632. IF e = 99 THEN BEGIN
  1633. explode_nolit8 := unzip_ZipFileErr;
  1634. exit
  1635. END;
  1636. DUMPBITS ( t^.b );
  1637. dec ( e, 16 );
  1638. NEEDBITS ( e );
  1639. t := @t^.v_t^ [ ( NOT b ) AND mask_bits [ e ] ];
  1640. e := t^.e;
  1641. UNTIL e <= 16;
  1642. DUMPBITS ( t^.b );
  1643. n := t^.v_n;
  1644. IF e <> 0 THEN BEGIN
  1645. NEEDBITS ( 8 );
  1646. inc ( n, b AND $ff );
  1647. DUMPBITS ( 8 );
  1648. END;
  1649. dec ( s, n );
  1650. REPEAT
  1651. d := d AND pred ( WSIZE );
  1652. IF d > w THEN e := WSIZE -d ELSE e := WSIZE -w;
  1653. IF e > n THEN e := n;
  1654. dec ( n, e );
  1655. IF ( u <> 0 ) AND ( w <= d ) THEN BEGIN
  1656. fillchar ( slide [ w ], e, #0 );
  1657. inc ( w, e );
  1658. inc ( d, e );
  1659. END ELSE IF ( w -d >= e ) THEN BEGIN
  1660. move ( slide [ d ], slide [ w ], e );
  1661. inc ( w, e );
  1662. inc ( d, e );
  1663. END ELSE REPEAT
  1664. slide [ w ] := slide [ d ];
  1665. inc ( w );
  1666. inc ( d );
  1667. dec ( e );
  1668. UNTIL e = 0;
  1669. IF w = WSIZE THEN BEGIN
  1670. IF NOT flush ( w ) THEN BEGIN
  1671. explode_nolit8 := unzip_WriteErr;
  1672. exit
  1673. END;
  1674. w := 0; u := 0;
  1675. END;
  1676. UNTIL n = 0;
  1677. END;
  1678. END;
  1679. IF totalabort THEN explode_nolit8 := unzip_userabort
  1680. ELSE
  1681. IF NOT flush ( w ) THEN explode_nolit8 := unzip_WriteErr
  1682. ELSE
  1683. IF zipeof THEN explode_nolit8 := unzip_readErr
  1684. ELSE explode_nolit8 := unzip_Ok;
  1685. END;
  1686. {******************exploding, method: 4k slide, 2 trees ***********************}
  1687. FUNCTION explode_nolit4 ( tl, td : phuftlist;bl, bd : integer ) : integer;
  1688. VAR s : longint;
  1689. e : word;
  1690. n, d : word;
  1691. w : word;
  1692. t : phuft;
  1693. ml, md : word;
  1694. u : word;
  1695. BEGIN
  1696. b := 0; k := 0; w := 0;
  1697. u := 1;
  1698. ml := mask_bits [ bl ];
  1699. md := mask_bits [ bd ];
  1700. s := uncompsize;
  1701. WHILE ( s > 0 ) AND NOT ( totalabort OR zipeof ) DO BEGIN
  1702. NEEDBITS ( 1 );
  1703. IF ( b AND 1 ) <> 0 THEN BEGIN {Litteral}
  1704. DUMPBITS ( 1 );
  1705. dec ( s );
  1706. NEEDBITS ( 8 );
  1707. slide [ w ] := char ( b );
  1708. inc ( w );
  1709. IF w = WSIZE THEN BEGIN
  1710. IF NOT flush ( w ) THEN BEGIN
  1711. explode_nolit4 := unzip_WriteErr;
  1712. exit
  1713. END;
  1714. w := 0; u := 0;
  1715. END;
  1716. DUMPBITS ( 8 );
  1717. END ELSE BEGIN
  1718. DUMPBITS ( 1 );
  1719. NEEDBITS ( 6 );
  1720. d := b AND $3F;
  1721. DUMPBITS ( 6 );
  1722. NEEDBITS ( bd );
  1723. t := @td^ [ ( NOT b ) AND md ];
  1724. e := t^.e;
  1725. IF e > 16 THEN REPEAT
  1726. IF e = 99 THEN BEGIN
  1727. explode_nolit4 := unzip_ZipFileErr;
  1728. exit
  1729. END;
  1730. DUMPBITS ( t^.b );
  1731. dec ( e, 16 );
  1732. NEEDBITS ( e );
  1733. t := @t^.v_t^ [ ( NOT b ) AND mask_bits [ e ] ];
  1734. e := t^.e;
  1735. UNTIL e <= 16;
  1736. DUMPBITS ( t^.b );
  1737. d := w -d -t^.v_n;
  1738. NEEDBITS ( bl );
  1739. t := @tl^ [ ( NOT b ) AND ml ];
  1740. e := t^.e;
  1741. IF e > 16 THEN REPEAT
  1742. IF e = 99 THEN BEGIN
  1743. explode_nolit4 := unzip_ZipFileErr;
  1744. exit
  1745. END;
  1746. DUMPBITS ( t^.b );
  1747. dec ( e, 16 );
  1748. NEEDBITS ( e );
  1749. t := @t^.v_t^ [ ( NOT b ) AND mask_bits [ e ] ];
  1750. e := t^.e;
  1751. UNTIL e <= 16;
  1752. DUMPBITS ( t^.b );
  1753. n := t^.v_n;
  1754. IF e <> 0 THEN BEGIN
  1755. NEEDBITS ( 8 );
  1756. inc ( n, b AND $ff );
  1757. DUMPBITS ( 8 );
  1758. END;
  1759. dec ( s, n );
  1760. REPEAT
  1761. d := d AND pred ( WSIZE );
  1762. IF d > w THEN e := WSIZE -d ELSE e := WSIZE -w;
  1763. IF e > n THEN e := n;
  1764. dec ( n, e );
  1765. IF ( u <> 0 ) AND ( w <= d ) THEN BEGIN
  1766. fillchar ( slide [ w ], e, #0 );
  1767. inc ( w, e );
  1768. inc ( d, e );
  1769. END ELSE IF ( w -d >= e ) THEN BEGIN
  1770. move ( slide [ d ], slide [ w ], e );
  1771. inc ( w, e );
  1772. inc ( d, e );
  1773. END ELSE REPEAT
  1774. slide [ w ] := slide [ d ];
  1775. inc ( w );
  1776. inc ( d );
  1777. dec ( e );
  1778. UNTIL e = 0;
  1779. IF w = WSIZE THEN BEGIN
  1780. IF NOT flush ( w ) THEN BEGIN
  1781. explode_nolit4 := unzip_WriteErr;
  1782. exit
  1783. END;
  1784. w := 0; u := 0;
  1785. END;
  1786. UNTIL n = 0;
  1787. END;
  1788. END;
  1789. IF totalabort THEN explode_nolit4 := unzip_userabort
  1790. ELSE
  1791. IF NOT flush ( w ) THEN explode_nolit4 := unzip_WriteErr
  1792. ELSE
  1793. IF zipeof THEN explode_nolit4 := unzip_readErr
  1794. ELSE explode_nolit4 := unzip_Ok;
  1795. END;
  1796. {****************************** explode *********************************}
  1797. FUNCTION explode : integer;
  1798. VAR r : integer;
  1799. tb, tl, td : phuftlist;
  1800. bb, bl, bd : integer;
  1801. l : ARRAY [ 0..255 ] of word;
  1802. BEGIN
  1803. inpos := 0;
  1804. readpos := -1; {Nothing read in}
  1805. bl := 7;
  1806. IF compsize > 200000 THEN bd := 8 ELSE bd := 7;
  1807. IF hufttype AND 4 <> 0 THEN BEGIN
  1808. bb := 9;
  1809. r := get_tree ( @l [ 0 ], 256 );
  1810. IF r <> 0 THEN BEGIN
  1811. explode := unzip_ZipFileErr;
  1812. exit
  1813. END;
  1814. r := huft_build ( @l, 256, 256, NIL, NIL, @tb, bb );
  1815. IF r <> 0 THEN BEGIN
  1816. IF r = huft_incomplete THEN huft_free ( tb );
  1817. explode := unzip_ZipFileErr;
  1818. exit
  1819. END;
  1820. r := get_tree ( @l [ 0 ], 64 );
  1821. IF r <> 0 THEN BEGIN
  1822. huft_free ( tb );
  1823. explode := unzip_ZipFileErr;
  1824. exit
  1825. END;
  1826. r := huft_build ( @l, 64, 0, pushlist ( @cplen3 ), pushlist ( @extra ), @tl, bl );
  1827. IF r <> 0 THEN BEGIN
  1828. IF r = huft_incomplete THEN huft_free ( tl );
  1829. huft_free ( tb );
  1830. explode := unzip_ZipFileErr;
  1831. exit
  1832. END;
  1833. r := get_tree ( @l [ 0 ], 64 );
  1834. IF r <> 0 THEN BEGIN
  1835. huft_free ( tb );
  1836. huft_free ( tl );
  1837. explode := unzip_ZipFileErr;
  1838. exit
  1839. END;
  1840. IF hufttype AND 2 <> 0 THEN BEGIN {8k}
  1841. r := huft_build ( @l, 64, 0, pushlist ( @cpdist8 ), pushlist ( @extra ), @td, bd );
  1842. IF r <> 0 THEN BEGIN
  1843. IF r = huft_incomplete THEN huft_free ( td );
  1844. huft_free ( tb );
  1845. huft_free ( tl );
  1846. explode := unzip_ZipFileErr;
  1847. exit
  1848. END;
  1849. r := explode_lit8 ( tb, tl, td, bb, bl, bd );
  1850. END ELSE BEGIN
  1851. r := huft_build ( @l, 64, 0, pushlist ( @cpdist4 ), pushlist ( @extra ), @td, bd );
  1852. IF r <> 0 THEN BEGIN
  1853. IF r = huft_incomplete THEN huft_free ( td );
  1854. huft_free ( tb );
  1855. huft_free ( tl );
  1856. explode := unzip_ZipFileErr;
  1857. exit
  1858. END;
  1859. r := explode_lit4 ( tb, tl, td, bb, bl, bd );
  1860. END;
  1861. huft_free ( td );
  1862. huft_free ( tl );
  1863. huft_free ( tb );
  1864. END ELSE BEGIN {No literal tree}
  1865. r := get_tree ( @l [ 0 ], 64 );
  1866. IF r <> 0 THEN BEGIN
  1867. explode := unzip_ZipFileErr;
  1868. exit
  1869. END;
  1870. r := huft_build ( @l, 64, 0, pushlist ( @cplen2 ), pushlist ( @extra ), @tl, bl );
  1871. IF r <> 0 THEN BEGIN
  1872. IF r = huft_incomplete THEN huft_free ( tl );
  1873. explode := unzip_ZipFileErr;
  1874. exit
  1875. END;
  1876. r := get_tree ( @l [ 0 ], 64 );
  1877. IF r <> 0 THEN BEGIN
  1878. huft_free ( tl );
  1879. explode := unzip_ZipFileErr;
  1880. exit
  1881. END;
  1882. IF hufttype AND 2 <> 0 THEN BEGIN {8k}
  1883. r := huft_build ( @l, 64, 0, pushlist ( @cpdist8 ), pushlist ( @extra ), @td, bd );
  1884. IF r <> 0 THEN BEGIN
  1885. IF r = huft_incomplete THEN huft_free ( td );
  1886. huft_free ( tl );
  1887. explode := unzip_ZipFileErr;
  1888. exit
  1889. END;
  1890. r := explode_nolit8 ( tl, td, bl, bd );
  1891. END ELSE BEGIN
  1892. r := huft_build ( @l, 64, 0, pushlist ( @cpdist4 ), pushlist ( @extra ), @td, bd );
  1893. IF r <> 0 THEN BEGIN
  1894. IF r = huft_incomplete THEN huft_free ( td );
  1895. huft_free ( tl );
  1896. explode := unzip_ZipFileErr;
  1897. exit
  1898. END;
  1899. r := explode_nolit4 ( tl, td, bl, bd );
  1900. END;
  1901. huft_free ( td );
  1902. huft_free ( tl );
  1903. END;
  1904. explode := r;
  1905. END;
  1906. (***************************************************************************)
  1907. {.$I z_shrunk.pas} {Unshrink function}
  1908. {*************************** unshrink **********************************}
  1909. {Written and NOT copyrighted by Christian Ghisler.
  1910. I have rewritten unshrink because the original
  1911. function was copyrighted by Mr. Smith of Info-zip
  1912. This funtion here is now completely FREE!!!!
  1913. The only right I claim on this code is that
  1914. noone else claims a copyright on it!}
  1915. CONST max_code = 8192;
  1916. max_stack = 8192;
  1917. initial_code_size = 9;
  1918. final_code_size = 13;
  1919. write_max = wsize -3 * ( max_code -256 ) -max_stack -2; {Rest of slide=write buffer}
  1920. {=766 bytes}
  1921. TYPE prev = ARRAY [ 257..max_code ] of integer;
  1922. pprev = ^prev;
  1923. cds = ARRAY [ 257..max_code ] of char;
  1924. pcds = ^cds;
  1925. stacktype = ARRAY [ 0..max_stack ] of char;
  1926. pstacktype = ^stacktype;
  1927. writebuftype = ARRAY [ 0..write_max ] of char; {write buffer}
  1928. pwritebuftype = ^writebuftype;
  1929. VAR previous_code : pprev; {previous code trie}
  1930. actual_code : pcds; {actual code trie}
  1931. stack : pstacktype; {Stack for output}
  1932. writebuf : pwritebuftype; {Write buffer}
  1933. next_free, {Next free code in trie}
  1934. write_ptr : integer; {Pointer to output buffer}
  1935. FUNCTION unshrink_flush : boolean;
  1936. VAR
  1937. n : nword;
  1938. b : boolean;
  1939. BEGIN
  1940. {$I-}
  1941. blockwrite ( outfile, writebuf^ [ 0 ], write_ptr, n );
  1942. {$I+}
  1943. b := ( n = write_ptr ) AND ( ioresult = 0 ); {True-> alles ok}
  1944. UpdateCRC ( iobuf ( pointer ( @writebuf^ [ 0 ] ) ^ ), write_ptr );
  1945. {--}
  1946. {$IFDEF FPC}
  1947. IF ( b = TRUE ) AND Assigned(ZipReport) {callback report for high level functions}
  1948. {$ELSE}
  1949. IF ( b = TRUE ) AND ( @ZipReport <> NIL ) {callback report for high level functions}
  1950. {$ENDIF}
  1951. THEN BEGIN
  1952. WITH ZipRec DO BEGIN
  1953. Status := file_unzipping;
  1954. ZipReport ( n, @ZipRec ); {report the actual bytes written}
  1955. END;
  1956. END; {report}
  1957. unshrink_flush := b;
  1958. END;
  1959. FUNCTION write_char ( c : char ) : boolean;
  1960. BEGIN
  1961. writebuf^ [ write_ptr ] := c;
  1962. inc ( write_ptr );
  1963. IF write_ptr > write_max THEN BEGIN
  1964. write_char := unshrink_flush;
  1965. write_ptr := 0;
  1966. END ELSE write_char := TRUE;
  1967. END;
  1968. PROCEDURE ClearLeafNodes;
  1969. VAR pc, {previous code}
  1970. i, {index}
  1971. act_max_code : integer; {max code to be searched for leaf nodes}
  1972. previous : pprev; {previous code trie}
  1973. BEGIN
  1974. previous := previous_code;
  1975. act_max_code := next_free -1;
  1976. FOR i := 257 TO act_max_code DO
  1977. previous^ [ i ] := previous^ [ i ] OR $8000;
  1978. FOR i := 257 TO act_max_code DO BEGIN
  1979. pc := previous^ [ i ] AND NOT $8000;
  1980. IF pc > 256 THEN
  1981. previous^ [ pc ] := previous^ [ pc ] AND ( NOT $8000 );
  1982. END;
  1983. {Build new free list}
  1984. pc := -1;
  1985. next_free := -1;
  1986. FOR i := 257 TO act_max_code DO
  1987. IF previous^ [ i ] AND $C000 <> 0 THEN BEGIN {Either free before or marked now}
  1988. IF pc <> -1 THEN previous^ [ pc ] := -i {Link last item to this item}
  1989. ELSE next_free := i;
  1990. pc := i;
  1991. END;
  1992. IF pc <> -1 THEN
  1993. previous^ [ pc ] := -act_max_code -1;
  1994. END;
  1995. FUNCTION unshrink : integer;
  1996. VAR incode : integer; {code read in}
  1997. lastincode : integer; {last code read in}
  1998. lastoutcode : char; {last code emitted}
  1999. code_size : byte; {Actual code size}
  2000. stack_ptr, {Stackpointer}
  2001. new_code, {Save new code read}
  2002. code_mask, {mask for coding}
  2003. i : integer; {Index}
  2004. bits_to_read : longint;
  2005. BEGIN
  2006. IF compsize = maxlongint THEN BEGIN {Compressed Size was not in header!}
  2007. unshrink := unzip_NotSupported;
  2008. exit
  2009. END;
  2010. inpos := 0; {Input buffer position}
  2011. readpos := -1; {Nothing read}
  2012. {initialize window, bit buffer}
  2013. w := 0;
  2014. k := 0;
  2015. b := 0;
  2016. {Initialize pointers for various buffers}
  2017. previous_code := @slide [ 0 ];
  2018. actual_code := @slide [ sizeof ( prev ) ];
  2019. stack := @slide [ sizeof ( prev ) + sizeof ( cds ) ];
  2020. writebuf := @slide [ sizeof ( prev ) + sizeof ( cds ) + sizeof ( stacktype ) ];
  2021. fillchar ( slide^, wsize, #0 );
  2022. {initialize free codes list}
  2023. FOR i := 257 TO max_code DO
  2024. previous_code^ [ i ] := - ( i + 1 );
  2025. next_free := 257;
  2026. stack_ptr := max_stack;
  2027. write_ptr := 0;
  2028. code_size := initial_code_size;
  2029. code_mask := mask_bits [ code_size ];
  2030. NEEDBITS ( code_size );
  2031. incode := b AND code_mask;
  2032. DUMPBITS ( code_size );
  2033. lastincode := incode;
  2034. lastoutcode := char ( incode );
  2035. IF NOT write_char ( lastoutcode ) THEN BEGIN
  2036. unshrink := unzip_writeErr;
  2037. exit
  2038. END;
  2039. bits_to_read := 8 * compsize -code_size; {Bits to be read}
  2040. WHILE NOT totalabort AND ( bits_to_read >= code_size ) DO BEGIN
  2041. NEEDBITS ( code_size );
  2042. incode := b AND code_mask;
  2043. DUMPBITS ( code_size );
  2044. dec ( bits_to_read, code_size );
  2045. IF incode = 256 THEN BEGIN {Special code}
  2046. NEEDBITS ( code_size );
  2047. incode := b AND code_mask;
  2048. DUMPBITS ( code_size );
  2049. dec ( bits_to_read, code_size );
  2050. CASE incode of
  2051. 1 : BEGIN
  2052. inc ( code_size );
  2053. IF code_size > final_code_size THEN BEGIN
  2054. unshrink := unzip_ZipFileErr;
  2055. exit
  2056. END;
  2057. code_mask := mask_bits [ code_size ];
  2058. END;
  2059. 2 : BEGIN
  2060. ClearLeafNodes;
  2061. END;
  2062. ELSE
  2063. unshrink := unzip_ZipFileErr;
  2064. exit
  2065. END;
  2066. END ELSE BEGIN
  2067. new_code := incode;
  2068. IF incode < 256 THEN BEGIN {Simple char}
  2069. lastoutcode := char ( incode );
  2070. IF NOT write_char ( lastoutcode ) THEN BEGIN
  2071. unshrink := unzip_writeErr;
  2072. exit
  2073. END;
  2074. END ELSE BEGIN
  2075. IF previous_code^ [ incode ] < 0 THEN BEGIN
  2076. stack^ [ stack_ptr ] := lastoutcode;
  2077. dec ( stack_ptr );
  2078. incode := lastincode;
  2079. END;
  2080. WHILE incode > 256 DO BEGIN
  2081. stack^ [ stack_ptr ] := actual_code^ [ incode ];
  2082. dec ( stack_ptr );
  2083. incode := previous_code^ [ incode ];
  2084. END;
  2085. lastoutcode := char ( incode );
  2086. IF NOT write_char ( lastoutcode ) THEN BEGIN
  2087. unshrink := unzip_writeErr;
  2088. exit
  2089. END;
  2090. FOR i := stack_ptr + 1 TO max_stack DO
  2091. IF NOT write_char ( stack^ [ i ] ) THEN BEGIN
  2092. unshrink := unzip_writeErr;
  2093. exit
  2094. END;
  2095. stack_ptr := max_stack;
  2096. END;
  2097. incode := next_free;
  2098. IF incode <= max_code THEN BEGIN
  2099. next_free := -previous_code^ [ incode ]; {Next node in free list}
  2100. previous_code^ [ incode ] := lastincode;
  2101. actual_code^ [ incode ] := lastoutcode;
  2102. END;
  2103. lastincode := new_code;
  2104. END;
  2105. END;
  2106. IF totalabort THEN
  2107. unshrink := unzip_UserAbort
  2108. ELSE IF unshrink_flush THEN
  2109. unshrink := unzip_ok
  2110. ELSE
  2111. unshrink := unzip_WriteErr;
  2112. END;
  2113. (***************************************************************************)
  2114. {***************************************************************************}
  2115. FUNCTION GetSupportedMethods : longint;
  2116. BEGIN
  2117. GetSupportedMethods := 1 + ( 1 SHL 1 ) + ( 1 SHL 6 ) + ( 1 SHL 8 );
  2118. {stored, shrunk, imploded and deflated}
  2119. END;
  2120. {******************** main low level function: unzipfile ********************}
  2121. {written and not copyrighted by Christian Ghisler}
  2122. FUNCTION unzipfile ( in_name : pchar;out_name : pchar;offset : longint;
  2123. hFileAction : word;cm_index : integer ) : integer;
  2124. VAR err : integer;
  2125. header : plocalheader;
  2126. buf : ARRAY [ 0..80 ] of char;
  2127. {$ifndef unix}
  2128. buf0 : ARRAY [ 0..3 ] of char;
  2129. {$endif}
  2130. storefilemode,
  2131. timedate : longint;
  2132. originalcrc : cardinal; {crc from zip-header}
  2133. ziptype, aResult : integer;
  2134. p, p1 : pchar;
  2135. isadir : boolean;
  2136. oldcurdir : string [ 80 ];
  2137. BEGIN
  2138. {$ifdef windows}
  2139. IF inuse THEN BEGIN
  2140. {take care of crashed applications!}
  2141. IF ( lastusedtime <> 0 ) AND
  2142. ( abs ( gettickcount -lastusedtime ) > 30000 ) THEN BEGIN {1/2 minute timeout!!!}
  2143. {do not close files or free slide, they were already freed when application crashed!}
  2144. inuse := FALSE;
  2145. {memory for huffman trees is lost}
  2146. END ELSE BEGIN
  2147. unzipfile := unzip_inuse;
  2148. exit
  2149. END;
  2150. END;{inuse}
  2151. inuse := TRUE;
  2152. {$endif}
  2153. getmem ( slide, wsize );
  2154. fillchar ( slide [ 0 ], wsize, #0 );
  2155. assign ( infile, in_name );
  2156. storefilemode := filemode;
  2157. filemode := 0;
  2158. {$I-}
  2159. reset ( infile, 1 );
  2160. {$I+}
  2161. filemode := storefilemode;
  2162. IF ioresult <> 0 THEN BEGIN
  2163. freemem ( slide, wsize );
  2164. unzipfile := unzip_ReadErr;
  2165. inuse := FALSE;
  2166. exit
  2167. END;
  2168. {$I-}
  2169. seek ( infile, offset ); {seek to header position}
  2170. {$I+}
  2171. IF ioresult <> 0 THEN BEGIN
  2172. freemem ( slide, wsize );
  2173. close ( infile );
  2174. unzipfile := unzip_ZipFileErr;
  2175. inuse := FALSE;
  2176. exit
  2177. END;
  2178. header := @inbuf;
  2179. {$I-}
  2180. blockread ( infile, header^, sizeof ( header^ ) ); {read in local header}
  2181. {$I+}
  2182. IF ioresult <> 0 THEN BEGIN
  2183. freemem ( slide, wsize );
  2184. close ( infile );
  2185. unzipfile := unzip_ZipFileErr;
  2186. inuse := FALSE;
  2187. exit
  2188. END;
  2189. IF strlcomp ( header^.signature, 'PK'#3#4, 4 ) <> 0 THEN BEGIN
  2190. freemem ( slide, wsize );
  2191. close ( infile );
  2192. unzipfile := unzip_ZipFileErr;
  2193. inuse := FALSE;
  2194. exit
  2195. END;
  2196. {calculate offset of data}
  2197. offset := offset + header^.filename_len + header^.extra_field_len + sizeof ( tlocalheader );
  2198. timedate := header^.file_timedate;
  2199. IF ( hufttype AND 8 ) = 0 THEN BEGIN {Size and crc at the beginning}
  2200. compsize := header^.compress_size;
  2201. uncompsize := header^.uncompress_size;
  2202. originalcrc := header^.crc_32;
  2203. END ELSE BEGIN
  2204. compsize := maxlongint; {Don't get a sudden zipeof!}
  2205. uncompsize := maxlongint;
  2206. originalcrc := 0
  2207. END;
  2208. ziptype := header^.zip_type; {0=stored, 6=imploded, 8=deflated}
  2209. IF ( 1 SHL ziptype ) AND GetSupportedMethods = 0 THEN BEGIN {Not Supported!!!}
  2210. freemem ( slide, wsize );
  2211. close ( infile );
  2212. unzipfile := unzip_NotSupported;
  2213. inuse := FALSE;
  2214. exit;
  2215. END;
  2216. hufttype := header^.bit_flag;
  2217. IF ( hufttype AND 1 ) <> 0 THEN BEGIN {encrypted}
  2218. freemem ( slide, wsize );
  2219. close ( infile );
  2220. unzipfile := unzip_Encrypted;
  2221. inuse := FALSE;
  2222. exit;
  2223. END;
  2224. reachedsize := 0;
  2225. seek ( infile, offset );
  2226. assign ( outfile, out_name );
  2227. {$I-}
  2228. rewrite ( outfile, 1 );
  2229. {$I+}
  2230. err := ioresult;
  2231. {create directories not yet in path}
  2232. isadir := ( out_name [ strlen ( out_name ) -1 ] in ['/','\'] );
  2233. IF ( err = 3 ) OR isadir THEN BEGIN {path not found}
  2234. {$I-}
  2235. getdir ( 0, oldcurdir );
  2236. {$I+}
  2237. err := ioresult;
  2238. strcopy ( buf, out_name );
  2239. p1 := strrscan ( buf, DirSep );
  2240. IF p1 <> NIL THEN inc ( p1 ); {pointer to filename}
  2241. p := strtok ( buf, DirSep );
  2242. {$ifndef unix}
  2243. IF ( p <> NIL ) AND ( p [ 1 ] = ':' ) THEN BEGIN
  2244. strcopy ( buf0, 'c:\' ); {set drive}
  2245. buf0 [ 0 ] := p [ 0 ];
  2246. {$ifdef windows}
  2247. setcurdir ( buf0 );
  2248. {$else}
  2249. {$I-}
  2250. chdir ( buf0 );
  2251. {$I+}
  2252. err := ioresult;
  2253. {$endif}
  2254. p := strtok ( NIL, '\' );
  2255. END;
  2256. {$endif}
  2257. WHILE ( p <> NIL ) AND ( p <> p1 ) DO BEGIN
  2258. {$ifdef windows}
  2259. {$ifdef Delphi}
  2260. {$I-}
  2261. chdir ( strpas ( p ) );
  2262. {$I+}
  2263. err := ioresult;
  2264. {$else Delphi}
  2265. setcurdir ( p );
  2266. err := doserror;
  2267. {$endif Delphi}
  2268. {$else Windows}
  2269. {$I-}
  2270. chdir ( strpas ( p ) );
  2271. {$I+}
  2272. err := ioresult;
  2273. {$endif}
  2274. IF err <> 0 THEN BEGIN
  2275. {$ifdef windows}
  2276. createdir ( p );
  2277. err := doserror;
  2278. {$else}
  2279. {$I-}
  2280. mkdir ( strpas ( p ) );
  2281. {$I+}
  2282. err := ioresult;
  2283. {$endif}
  2284. IF err = 0 THEN
  2285. {$I-}
  2286. chdir ( strpas ( p ) );
  2287. {$I+}
  2288. err := ioresult;
  2289. END;
  2290. IF err = 0 THEN
  2291. p := strtok ( NIL, DirSep )
  2292. ELSE
  2293. p := NIL;
  2294. END;
  2295. {$I-}
  2296. chdir ( oldcurdir );
  2297. {$I+}
  2298. err := ioresult;
  2299. IF isadir THEN BEGIN
  2300. freemem ( slide, wsize );
  2301. unzipfile := unzip_Ok; {A directory -> ok}
  2302. close ( infile );
  2303. inuse := FALSE;
  2304. exit;
  2305. END;
  2306. {$I-}
  2307. rewrite ( outfile, 1 );
  2308. {$I+}
  2309. err := ioresult;
  2310. END;
  2311. IF err <> 0 THEN BEGIN
  2312. freemem ( slide, wsize );
  2313. unzipfile := unzip_WriteErr;
  2314. close ( infile );
  2315. inuse := FALSE;
  2316. exit
  2317. END;
  2318. totalabort := FALSE;
  2319. zipeof := FALSE;
  2320. {$ifdef windows}
  2321. dlghandle := hFileAction;
  2322. dlgnotify := cm_index;
  2323. messageloop;
  2324. oldpercent := 0;
  2325. {$endif}
  2326. crc32val := $FFFFFFFF;
  2327. {Unzip correct type}
  2328. CASE ziptype of
  2329. 0 : aResult := copystored;
  2330. 1 : aResult := unshrink;
  2331. 6 : aResult := explode;
  2332. 8 : aResult := inflate;
  2333. ELSE
  2334. aResult := unzip_NotSupported;
  2335. END;
  2336. unzipfile := aResult;
  2337. IF ( aResult = unzip_ok ) AND ( ( hufttype AND 8 ) <> 0 ) THEN BEGIN {CRC at the end}
  2338. dumpbits ( k AND 7 );
  2339. needbits ( 16 );
  2340. originalcrc := b AND $FFFF;
  2341. dumpbits ( 16 );
  2342. needbits ( 16 );
  2343. originalcrc := ( b AND $FFFF ) SHL 16;
  2344. dumpbits ( 16 );
  2345. END;
  2346. close ( infile );
  2347. close ( outfile );
  2348. crc32val := NOT ( crc32val ); {one's complement}
  2349. IF aResult <> 0 THEN BEGIN
  2350. erase ( outfile );
  2351. END ELSE IF ( originalcrc <> crc32val ) THEN BEGIN
  2352. unzipfile := unzip_CRCErr;
  2353. erase ( outfile );
  2354. END ELSE BEGIN
  2355. {$ifdef windows}
  2356. oldpercent := 100; {100 percent}
  2357. IF dlghandle <> 0 THEN
  2358. sendmessage ( dlghandle, wm_command, dlgnotify, longint ( @oldpercent ) );
  2359. {$endif}
  2360. filemode := 2;
  2361. reset ( outfile );
  2362. filemode := storefilemode;
  2363. setftime ( outfile, timedate ); {set zipped time and date of oufile}
  2364. close ( outfile );
  2365. END;
  2366. freemem ( slide, wsize );
  2367. inuse := FALSE;
  2368. END;
  2369. {***************************************************************************}
  2370. {***************************************************************************}
  2371. {***************************************************************************}
  2372. { other functions; zipread.pas }
  2373. CONST mainheader : pchar = 'PK'#5#6;
  2374. maxbufsize = 64000; {Can be as low as 500 Bytes; however, }
  2375. {this would lead to extensive disk reading!}
  2376. {If one entry (including Extra field) is bigger}
  2377. {than maxbufsize, you cannot read it :-( }
  2378. TYPE
  2379. pheader = ^theader;
  2380. pmainheader = ^tmainheader;
  2381. tmainheader = PACKED RECORD
  2382. signature : ARRAY [ 0..3 ] of char; {'PK'#5#6}
  2383. thisdisk,
  2384. centralstartdisk,
  2385. entries_this_disk,
  2386. entries_central_dir : word;
  2387. headsize,
  2388. headstart : longint;
  2389. comment_len : longint;
  2390. unknown : word;
  2391. END;
  2392. theader = PACKED RECORD
  2393. signature : ARRAY [ 0..3 ] of char; {'PK'#1#2}
  2394. OSversion, {Operating system version}
  2395. OSmadeby : byte; {MSDOS (FAT): 0}
  2396. extract_ver,
  2397. bit_flag,
  2398. zip_type : word;
  2399. file_timedate : longint;
  2400. crc_32,
  2401. compress_size,
  2402. uncompress_size : longint;
  2403. filename_len,
  2404. extra_field_len,
  2405. file_comment_len,
  2406. disk_number_start,
  2407. internal_attr : word;
  2408. external_attr : ARRAY [ 0..3 ] of byte;
  2409. offset_local_header : longint;
  2410. END;
  2411. {*********** Fill out tZipRec structure with next entry *************}
  2412. FUNCTION filloutRec ( VAR zprec : tZipRec ) : integer;
  2413. VAR p : pchar;
  2414. incr : longint;
  2415. header : pheader;
  2416. offs : word;
  2417. old : char;
  2418. f : file;
  2419. extra, err : nword;
  2420. BEGIN
  2421. WITH zprec DO BEGIN
  2422. header := pheader ( @buf^ [ localstart ] );
  2423. IF ( bufsize = maxbufsize ) THEN BEGIN {Caution: header bigger than 64k!}
  2424. extra := sizeof ( file );
  2425. IF ( ( localstart + sizeof ( theader ) ) > bufsize ) OR
  2426. ( localstart + header^.filename_len + header^.extra_field_len +
  2427. header^.file_comment_len + sizeof ( theader ) > bufsize )
  2428. THEN BEGIN {Read over end of header}
  2429. move ( buf^ [ bufsize + 1 ], f, extra ); {Restore file}
  2430. move ( buf^ [ localstart ], buf^ [ 0 ], bufsize -localstart ); {Move end to beginning in buffer}
  2431. {$I-}
  2432. blockread ( f, buf^ [ bufsize -localstart ], localstart, err ); {Read in full central dir, up to maxbufsize Bytes}
  2433. {$I+}
  2434. IF ( ioresult <> 0 ) OR ( err + localstart < sizeof ( theader ) ) THEN BEGIN
  2435. filloutrec := unzip_nomoreitems;
  2436. exit
  2437. END;
  2438. move ( f, buf^ [ bufsize + 1 ], extra ); {Save changed file info!}
  2439. localstart := 0;
  2440. header := pheader ( @buf^ [ localstart ] );
  2441. END;
  2442. END;
  2443. IF ( localstart + 4 <= bufsize ) AND {Here is the ONLY correct finish!}
  2444. ( strlcomp ( header^.signature, mainheader, 4 ) = 0 ) THEN BEGIN {Main header}
  2445. filloutrec := unzip_nomoreitems;
  2446. exit
  2447. END;
  2448. IF ( localstart + sizeof ( header ) > bufsize ) OR
  2449. ( localstart + header^.filename_len + header^.extra_field_len +
  2450. header^.file_comment_len + sizeof ( theader ) > bufsize ) OR
  2451. ( strlcomp ( header^.signature, 'PK'#1#2, 4 ) <> 0 ) THEN BEGIN
  2452. filloutrec := unzip_nomoreitems;
  2453. exit
  2454. END;
  2455. size := header^.uncompress_size;
  2456. compressSize := header^.compress_size;
  2457. IF header^.osmadeby = 0 THEN
  2458. attr := header^.external_attr [ 0 ]
  2459. ELSE
  2460. attr := 0;
  2461. time := header^.file_timedate;
  2462. headeroffset := header^.offset_local_header; {Other header size}
  2463. Packmethod := header^.zip_type;
  2464. offs := localstart + header^.filename_len + sizeof ( header^ );
  2465. old := buf^ [ offs ];
  2466. buf^ [ offs ] := #0; {Repair signature of next block!}
  2467. strlcopy ( filename, pchar ( @buf^ [ localstart + sizeof ( header^ ) ] ), sizeof ( filename ) -1 );
  2468. buf^ [ offs ] := old;
  2469. {$ifndef unix}
  2470. REPEAT {Convert slash to backslash!}
  2471. p := strscan ( filename, '/' );
  2472. IF p <> NIL THEN p [ 0 ] := '\';
  2473. UNTIL p = NIL;
  2474. {$else}
  2475. REPEAT {Convert backslash to slash!}
  2476. p := strscan ( filename, '\' );
  2477. IF p <> NIL THEN p [ 0 ] := '/';
  2478. UNTIL p = NIL;
  2479. {$endif}
  2480. incr := header^.filename_len + header^.extra_field_len +
  2481. header^.file_comment_len + sizeof ( header^ );
  2482. IF incr <= 0 THEN BEGIN
  2483. filloutrec := unzip_InternalError;
  2484. exit
  2485. END;
  2486. localstart := localstart + incr;
  2487. filloutrec := unzip_ok;
  2488. END;
  2489. END;
  2490. {**************** Get first entry from ZIP file ********************}
  2491. FUNCTION GetFirstInZip ( zipfilename : pchar;VAR zprec : tZipRec ) : integer;
  2492. VAR bufstart, headerstart, start : longint;
  2493. err, i : integer;
  2494. mainh : pmainheader;
  2495. f : file;
  2496. extra : word; {Extra bytes for saving File!}
  2497. BEGIN
  2498. WITH zprec DO BEGIN
  2499. assign ( f, zipfilename );
  2500. filemode := 0; {Others may read or write};
  2501. {$I-}
  2502. reset ( f, 1 );
  2503. {$I+}
  2504. IF ioresult <> 0 THEN BEGIN
  2505. GetFirstInZip := unzip_FileError;
  2506. exit
  2507. END;
  2508. size := filesize ( f );
  2509. IF size = 0 THEN BEGIN
  2510. GetFirstInZip := unzip_FileError;
  2511. {$I-}
  2512. close ( f );
  2513. {$I+}
  2514. exit
  2515. END;
  2516. bufsize := 4096; {in 4k-blocks}
  2517. IF size > bufsize THEN BEGIN
  2518. bufstart := size -bufsize;
  2519. END ELSE BEGIN
  2520. bufstart := 0;
  2521. bufsize := size;
  2522. END;
  2523. getmem ( buf, bufsize + 1 ); {#0 at the end of filemname}
  2524. {Search from back of file to central directory start}
  2525. start := -1; {Nothing found}
  2526. REPEAT
  2527. {$I-}
  2528. seek ( f, bufstart );
  2529. {$I+}
  2530. IF ioresult <> 0 THEN BEGIN
  2531. GetFirstInZip := unzip_FileError;
  2532. freeMem ( buf, bufsize + 1 );
  2533. buf := NIL;
  2534. {$I-}
  2535. close ( f );
  2536. {$I+}
  2537. exit
  2538. END;
  2539. {$I-}
  2540. blockread ( f, buf^, bufsize, err );
  2541. {$I+}
  2542. IF ( ioresult <> 0 ) OR ( err <> bufsize ) THEN BEGIN
  2543. GetFirstInZip := unzip_FileError;
  2544. freeMem ( buf, bufsize + 1 );
  2545. buf := NIL;
  2546. {$I-}
  2547. close ( f );
  2548. {$I+}
  2549. exit
  2550. END;
  2551. IF bufstart = 0 THEN start := maxlongint;{Break}
  2552. FOR i := bufsize -22 DOWNTO 0 DO BEGIN {Search buffer backwards}
  2553. IF ( buf^ [ i ] = 'P' ) AND ( buf^ [ i + 1 ] = 'K' ) AND ( buf^ [ i + 2 ] = #5 ) AND ( buf^ [ i + 3 ] = #6 )
  2554. THEN BEGIN {Header found!!!}
  2555. start := bufstart + i;
  2556. break;
  2557. END;
  2558. END;
  2559. IF start = -1 THEN BEGIN {Nothing found yet}
  2560. dec ( bufstart, bufsize -22 ); {Full header in buffer!}
  2561. IF bufstart < 0 THEN bufstart := 0;
  2562. END;
  2563. UNTIL start >= 0;
  2564. IF ( start = maxlongint ) THEN BEGIN {Nothing found}
  2565. GetFirstInZip := unzip_FileError;
  2566. freeMem ( buf, bufsize + 1 );
  2567. buf := NIL;
  2568. {$I-}
  2569. close ( f );
  2570. {$I+}
  2571. exit
  2572. END;
  2573. mainh := pmainheader ( @buf^ [ start -bufstart ] );
  2574. headerstart := mainh^.headstart;
  2575. localstart := 0;
  2576. freeMem ( buf, bufsize + 1 );
  2577. IF ( localstart + sizeof ( theader ) > start ) THEN BEGIN
  2578. buf := NIL;
  2579. GetFirstInZip := unzip_InternalError;
  2580. {$I-}
  2581. close ( f );
  2582. {$I+}
  2583. exit
  2584. END;
  2585. bufstart := headerstart;
  2586. start := start -headerstart + 4; {size for central dir,Including main header signature}
  2587. IF start >= maxbufsize THEN BEGIN
  2588. bufsize := maxbufsize; {Max buffer size, limit of around 1000 items!}
  2589. extra := sizeof ( file ) {Save file information for later reading!}
  2590. END ELSE BEGIN
  2591. bufsize := start;
  2592. extra := 0
  2593. END;
  2594. getmem ( buf, bufsize + 1 + extra );
  2595. {$I-}
  2596. seek ( f, bufstart );
  2597. {$I+}
  2598. IF ioresult <> 0 THEN BEGIN
  2599. GetFirstInZip := unzip_FileError;
  2600. freeMem ( buf, bufsize + 1 + extra );
  2601. buf := NIL;
  2602. {$I-}
  2603. close ( f );
  2604. {$I+}
  2605. exit
  2606. END;
  2607. {$I-}
  2608. blockread ( f, buf^, bufsize, err ); {Read in full central dir, up to maxbufsize Bytes}
  2609. {$I+}
  2610. IF ioresult <> 0 THEN BEGIN
  2611. GetFirstInZip := unzip_FileError;
  2612. freeMem ( buf, bufsize + 1 + extra );
  2613. buf := NIL;
  2614. {$I-}
  2615. close ( f );
  2616. {$I+}
  2617. exit
  2618. END;
  2619. IF extra = 0 THEN
  2620. {$I-} close ( f ) {$I+}
  2621. ELSE move ( f, buf^ [ bufsize + 1 ], extra ); {Save file info!}
  2622. err := filloutRec ( zprec );
  2623. IF err <> unzip_ok THEN BEGIN
  2624. CloseZipFile ( zprec );
  2625. GetFirstInZip := err;
  2626. exit
  2627. END;
  2628. GetFirstInZip := err;
  2629. END;
  2630. END;
  2631. {**************** Get next entry from ZIP file ********************}
  2632. FUNCTION GetNextInZip ( VAR Zprec : tZiprec ) : integer;
  2633. VAR err : integer;
  2634. BEGIN
  2635. WITH zprec DO BEGIN
  2636. IF ( buf <> NIL ) THEN BEGIN {Main Header at the end}
  2637. err := filloutRec ( zprec );
  2638. IF err <> unzip_ok THEN BEGIN
  2639. CloseZipFile ( ZPRec );
  2640. END;
  2641. GetNextInZip := err;
  2642. END ELSE GetNextInZip := unzip_NoMoreItems;
  2643. END
  2644. END;
  2645. {**************** VERY simple test for zip file ********************}
  2646. FUNCTION isZip ( filename : pchar ) : boolean;
  2647. VAR
  2648. myname : tdirtype;
  2649. l, err : integer;
  2650. f : file;
  2651. buf : ARRAY [ 0..4 ] of char;
  2652. oldcurdir : string{$ifndef BIT32} [ 80 ]{$endif};
  2653. BEGIN
  2654. filemode := 0;
  2655. {$I-}
  2656. getdir ( 0, oldcurdir );
  2657. {$I+}
  2658. err := ioresult;
  2659. isZip := FALSE;
  2660. IF ( strscan ( filename, '.' ) <> NIL )
  2661. AND ( strpos ( filename, '.exe' ) = NIL ) THEN BEGIN
  2662. strcopy ( myname, filename );
  2663. l := strlen ( myname );
  2664. IF myname [ l -1 ] = DirSep THEN myname [ l -1 ] := #0;
  2665. {$I-}
  2666. chdir ( Strpas ( myname ) );
  2667. {$I+}
  2668. IF ioresult <> 0 THEN BEGIN
  2669. assign ( f, Strpas ( myname ) );
  2670. filemode := 0; {Others may read or write};
  2671. {$I-}
  2672. reset ( f, 1 );
  2673. {$I+}
  2674. IF ioresult = 0 THEN BEGIN
  2675. {$I-}
  2676. blockread ( f, buf, 4, err );
  2677. {$I+}
  2678. IF ( ioresult = 0 ) THEN BEGIN
  2679. IF ( err = 4 ) AND ( buf [ 0 ] = 'P' ) AND ( buf [ 1 ] = 'K' )
  2680. AND ( buf [ 2 ] = #3 ) AND ( buf [ 3 ] = #4 ) THEN isZip := TRUE
  2681. END;
  2682. {$I-}
  2683. close ( f );
  2684. {$I+}
  2685. err := ioresult; {only clears ioresult variable}
  2686. END;
  2687. END;
  2688. END;
  2689. {$I-}
  2690. chdir ( oldcurdir );
  2691. {$I+}
  2692. err := ioresult;
  2693. END;
  2694. {**************** free ZIP buffers ********************}
  2695. PROCEDURE CloseZipFile ( VAR Zprec : tZiprec ); {Only free buffer, file only open in Getfirstinzip}
  2696. VAR
  2697. f : file;
  2698. extra : word;
  2699. BEGIN
  2700. WITH zprec DO BEGIN
  2701. IF buf <> NIL THEN BEGIN
  2702. IF ( bufsize = maxbufsize ) THEN BEGIN {Caution: header bigger than 64k!}
  2703. extra := sizeof ( file );
  2704. move ( buf^ [ bufsize + 1 ], f, extra ); {Restore file}
  2705. {$I-}
  2706. close ( f );
  2707. {$I+}
  2708. IF ioresult <> 0 THEN ;
  2709. END ELSE extra := 0;
  2710. freemem ( buf, bufsize + 1 + extra );
  2711. buf := NIL
  2712. END;
  2713. END
  2714. END;
  2715. {***************************************************************************}
  2716. {***************************************************************************}
  2717. {********** routines by the African Chief **********************************}
  2718. {***************************************************************************}
  2719. {***************************************************************************}
  2720. {$ifndef Delphi}
  2721. FUNCTION FileExists ( CONST fname : string ) : boolean; {simple fileexist function}
  2722. VAR
  2723. f : file;
  2724. i : byte;
  2725. BEGIN
  2726. i := filemode;
  2727. filemode := 0;
  2728. assign ( f, fname );
  2729. {$i-}
  2730. Reset ( f, 1 );
  2731. filemode := i;
  2732. FileExists := ioresult = 0;
  2733. Close ( f ); IF ioresult <> 0 THEN;
  2734. {$i+}
  2735. END;
  2736. {$endif Delphi}
  2737. PROCEDURE DummyReport ( Retcode : longint;Rec : pReportRec );
  2738. {$ifdef Windows}{$ifdef win32}STDCALL;{$else}EXPORT;{$endif}{$endif}
  2739. {dummy report procedure}
  2740. BEGIN
  2741. END;
  2742. FUNCTION DummyQuestion( Rec : pReportRec ) : Boolean;
  2743. {$ifdef Windows}{$ifdef win32}STDCALL;{$else}EXPORT;{$endif}{$endif}
  2744. {dummy question procedure}
  2745. begin
  2746. DummyQuestion:=true;
  2747. end;
  2748. FUNCTION Matches ( s : String;CONST main : string ) : Boolean;
  2749. {rudimentary matching function;
  2750. accepts only '', '*.*', 'XXX.*' or '*.XXX'
  2751. }
  2752. FUNCTION extensiononly ( CONST s : string ) : string;{return just the extension}
  2753. VAR i : integer;
  2754. BEGIN
  2755. extensiononly := '';
  2756. i := pos ( '.', s );
  2757. IF i = 0 THEN exit;
  2758. extensiononly := copy ( s, succ ( i ), length ( s ) );
  2759. END;
  2760. FUNCTION nameonly ( CONST s : string ) : string;{return just the name}
  2761. VAR i : integer;
  2762. BEGIN
  2763. nameonly := s;
  2764. i := pos ( '.', s );
  2765. IF i = 0 THEN exit;
  2766. nameonly := copy ( s, 1, pred ( i ) );
  2767. END;
  2768. {!!!!!}
  2769. VAR
  2770. b : boolean;
  2771. i : integer;
  2772. BEGIN
  2773. Matches := TRUE;
  2774. IF ( s = '' ) OR ( s = AllFiles ) THEN exit; {'' or '*.*' = all files match}
  2775. s := upper ( s );
  2776. b := copy ( s, 1, 2 ) = '*.'; {e.g., *.PAS}
  2777. IF b THEN BEGIN
  2778. delete ( s, 1, 2 );
  2779. Matches := s = extensiononly ( upper ( main ) );
  2780. END ELSE BEGIN
  2781. i := length ( s );
  2782. b := s [ i ] = '*'; {e.g. TEST.*}
  2783. IF b THEN BEGIN
  2784. IF s [ pred ( i ) ] = '.' THEN delete ( s, pred ( i ), 2 );
  2785. i := length ( s );
  2786. IF s [ i ] in [ '*', '?' ] THEN dec ( i );{e.g. TEST*.*}
  2787. Matches := Copy ( s, 1, i ) = Copy ( nameonly ( upper ( main ) ), 1, i );
  2788. END ELSE Matches := s = upper ( main );
  2789. END;
  2790. END; { Matches }
  2791. {****************************************************}
  2792. FUNCTION FileUnzip ( SourceZipFile, TargetDirectory, FileSpecs : pChar;
  2793. Report : UnzipReportProc;Question : UnzipQuestionProc ) : integer;
  2794. VAR
  2795. rc : integer;
  2796. r : tziprec;
  2797. buf,
  2798. thename,
  2799. target : ARRAY [ 0..tFSize ] of char;
  2800. Count : integer;
  2801. rSize, cSize : longint;
  2802. s : string [ 255 ];
  2803. BEGIN
  2804. {$IFDEF FPC}
  2805. IF not assigned(Report) THEN
  2806. Report := @DummyReport;
  2807. IF not assigned(Question) THEN
  2808. Question := @DummyQuestion;
  2809. {$ELSE}
  2810. IF @Report = nil THEN
  2811. Report := DummyReport;
  2812. IF @Question = nil THEN
  2813. Question := DummyQuestion;
  2814. {$ENDIF}
  2815. Count := 0;
  2816. rSize := 0;
  2817. cSize := 0;
  2818. FileUnzip := unzip_MissingParameter;
  2819. IF ( StrPas ( SourceZipFile ) = '' ) OR ( StrPas ( TargetDirectory ) = '' ) THEN Exit;
  2820. Strcopy ( thename, SourceZipFile );
  2821. Strcopy ( target, TargetDirectory );
  2822. IF ( target [ 0 ] <> #0 ) AND ( target [ strlen ( target ) -1 ] <> DirSep )
  2823. THEN strcat ( target, DirSep );
  2824. FileUnzip := unzip_NotZipFile;
  2825. IF NOT iszip ( thename ) THEN exit;
  2826. FillChar ( ZipRec, Sizeof ( ZipRec ), #0 );
  2827. WITH ZipRec DO BEGIN
  2828. IsaDir := FALSE;
  2829. strcopy ( FileName, thename );
  2830. Size := UnZipSize ( SourceZipFile, CompressSize );
  2831. IF Size = 0 THEN ratio := 0 ELSE
  2832. Ratio := 100 -Round ( ( CompressSize / Size ) * 100 );
  2833. Status := unzip_starting;
  2834. Report ( Status, @ZipRec );
  2835. END; {start of ZIP file}
  2836. ZipReport := Report;
  2837. rc := getfirstinzip ( thename, r );
  2838. WHILE ( rc = unzip_ok )
  2839. DO BEGIN
  2840. IF ( Matches ( StrPas ( FileSpecs ), Strpas ( R.FileName ) ) )
  2841. THEN BEGIN
  2842. Inc ( rSize, r.Size );
  2843. Inc ( cSize, r.CompressSize );
  2844. strcopy ( buf, target );
  2845. IF NoRecurseDirs { no recursion }
  2846. THEN BEGIN
  2847. s := StripPath ( Strpas ( r.filename ) ) + #0;
  2848. Strcat ( buf, @s [ 1 ] );
  2849. END ELSE strcat ( buf, r.filename );
  2850. WITH ZipRec DO BEGIN { report start of file }
  2851. s := StrPas ( Buf );
  2852. IsaDir := s [ length ( s ) ] = DirSep;
  2853. Time := r.Time;
  2854. Size := r.Size;
  2855. CompressSize := r.CompressSize;
  2856. strcopy ( FileName, buf );
  2857. PackMethod := r.PackMethod;
  2858. Attr := r.Attr;
  2859. IF Size = 0 THEN ratio := 0 ELSE
  2860. Ratio := 100 -Round ( ( CompressSize /Size ) * 100 );
  2861. Status := file_starting;
  2862. IF ( IsaDir ) AND ( NoRecurseDirs )
  2863. THEN {} ELSE
  2864. ZipReport ( Status, @ZipRec );
  2865. END; { start of file }
  2866. IF ( FileExists ( StrPas ( buf ) ) )
  2867. AND ( Question ( @ZipRec ) = FALSE )
  2868. THEN BEGIN
  2869. rc := unzip_ok; { we are okay }
  2870. WITH ZipRec DO BEGIN
  2871. Status := file_unzipping;
  2872. PackMethod := 9; { skipped }
  2873. ZipReport ( Size, @ZipRec ); { report uncompressed size }
  2874. END;
  2875. END ELSE BEGIN
  2876. rc := unzipfile ( thename, buf, r.headeroffset, 0,
  2877. {$ifdef windows}vk_escape{$else}27{$endif} ); {Escape interrupts}
  2878. END;
  2879. IF rc = unzip_ok
  2880. THEN BEGIN
  2881. Inc ( Count );
  2882. WITH ZipRec DO BEGIN { report end of file }
  2883. Status := file_completed;
  2884. IF ( IsaDir ) AND ( NoRecurseDirs )
  2885. THEN {} ELSE
  2886. ZipReport ( Status, @ZipRec );
  2887. END; { end of file }
  2888. END ELSE BEGIN
  2889. ZipRec.Status := file_failure; {error}
  2890. CASE rc of
  2891. unzip_CRCErr,
  2892. unzip_WriteErr,
  2893. unzip_Encrypted,
  2894. unzip_NotSupported : ZipReport ( rc, @ZipRec );
  2895. unzip_ReadErr, unzip_Userabort,
  2896. unzip_FileError, unzip_InternalError,
  2897. unzip_InUse, unzip_ZipFileErr :
  2898. BEGIN
  2899. ZipRec.Status := unzip_SeriousError;
  2900. FileUnzip := unzip_SeriousError; {Serious error, force abort}
  2901. ZipReport ( unzip_SeriousError, @ZipRec );
  2902. closezipfile ( r );
  2903. ZipReport := NIL;
  2904. ZipQuestion := NIL;
  2905. exit;
  2906. END;
  2907. END; {case rc}
  2908. Continue;
  2909. {rc:=getnextinzip(r);}
  2910. END; {else}
  2911. END; { if Matches }
  2912. rc := getnextinzip ( r );
  2913. END; {while }
  2914. closezipfile ( r ); {Free memory used for central directory info}
  2915. WITH ZipRec DO BEGIN { report end of ZIP file }
  2916. Time := -1;
  2917. Attr := -1;
  2918. PackMethod := 0;
  2919. Size := rSize;
  2920. CompressSize := cSize;
  2921. strcopy ( FileName, thename );
  2922. IF Size = 0 THEN ratio := 0 ELSE
  2923. Ratio := 100 -Round ( ( CompressSize /Size ) * 100 );
  2924. Status := unzip_completed;
  2925. ZipReport ( Status, @ZipRec );
  2926. END; { end of ZIP file }
  2927. ZipReport := NIL;
  2928. ZipQuestion := NIL;
  2929. FileUnzip := Count;
  2930. END; { FileUnzip }
  2931. {***************************************************************************}
  2932. FUNCTION FileUnzipEx ( SourceZipFile, TargetDirectory, FileSpecs : pChar ) : integer;
  2933. BEGIN
  2934. FileUnzipEx :=
  2935. FileUnzip ( SourceZipFile, TargetDirectory, FileSpecs, ZipReport, ZipQuestion );
  2936. END; { FileUnzipEx }
  2937. {***************************************************************************}
  2938. FUNCTION Viewzip ( SourceZipFile, FileSpecs : pChar; Report : UnzipReportProc ) : integer;
  2939. VAR
  2940. rc : integer;
  2941. r : tziprec;
  2942. thename : ARRAY [ 0..tFSize ] of char;
  2943. Count : integer;
  2944. rSize, cSize : longint;
  2945. BEGIN
  2946. Count := 0;
  2947. rSize := 0;
  2948. cSize := 0;
  2949. Viewzip := unzip_MissingParameter;
  2950. {$IFDEF FPC}
  2951. IF ( StrPas ( SourceZipFile ) = '' ) or
  2952. not assigned(Report) THEN
  2953. exit;
  2954. {$ELSE}
  2955. IF ( StrPas ( SourceZipFile ) = '' ) OR ( @Report = NIL ) THEN Exit;
  2956. {$ENDIF}
  2957. Strcopy ( thename, SourceZipFile );
  2958. ViewZip := unzip_NotZipFile;
  2959. IF NOT iszip ( thename ) THEN exit;
  2960. FillChar ( ZipRec, Sizeof ( ZipRec ), #0 );
  2961. rc := getfirstinzip ( thename, r );
  2962. WHILE ( rc = unzip_ok )
  2963. DO BEGIN
  2964. IF ( Matches ( StrPas ( FileSpecs ), Strpas ( R.FileName ) ) ) THEN BEGIN
  2965. Inc ( rSize, r.Size );
  2966. Inc ( cSize, r.CompressSize );
  2967. WITH ZipRec DO BEGIN
  2968. Time := r.Time;
  2969. Size := r.Size;
  2970. CompressSize := r.CompressSize;
  2971. strcopy ( FileName, r.Filename );
  2972. PackMethod := r.PackMethod;
  2973. Attr := r.Attr;
  2974. IF Size = 0 THEN ratio := 0 ELSE
  2975. Ratio := 100 -Round ( ( CompressSize /Size ) * 100 );
  2976. END;
  2977. Inc ( Count );
  2978. Report ( rc, @ZipRec );
  2979. END; {matches}
  2980. rc := getnextinzip ( r );
  2981. END; {while }
  2982. closezipfile ( r );
  2983. WITH ZipRec DO BEGIN
  2984. Time := -1;
  2985. Attr := -1;
  2986. PackMethod := 0;
  2987. Size := rSize;
  2988. CompressSize := cSize;
  2989. strcopy ( FileName, thename );
  2990. IF Size = 0 THEN ratio := 0 ELSE
  2991. Ratio := 100 -Round ( ( CompressSize /Size ) * 100 );
  2992. END;
  2993. Report ( Count, @ZipRec );
  2994. ViewZip := Count;
  2995. END; { ViewZip }
  2996. {***************************************************************************}
  2997. FUNCTION UnZipSize ( SourceZipFile : pChar;VAR Compressed : Longint ) : longint;
  2998. VAR
  2999. rc : integer;
  3000. r : tziprec;
  3001. thename : ARRAY [ 0..tFSize ] of char;
  3002. Count : longint;
  3003. f : file;
  3004. BEGIN
  3005. Compressed := 0;
  3006. UnZipSize := 0;
  3007. IF ( StrPas ( SourceZipFile ) = '' ) THEN Exit;
  3008. System.Assign ( f, StrPas ( SourceZipFile ) );
  3009. count := filemode;
  3010. filemode := 0;
  3011. {$i-}
  3012. Reset ( f, 1 );
  3013. filemode := count;
  3014. IF ioresult <> 0 THEN exit;
  3015. Count := filesize ( f );
  3016. close ( f );
  3017. UnZipSize := count;
  3018. Compressed := count;
  3019. Strcopy ( thename, SourceZipFile );
  3020. IF NOT iszip ( thename ) THEN exit;
  3021. Count := 0;
  3022. Compressed := 0;
  3023. rc := getfirstinzip ( thename, r );
  3024. WHILE ( rc = unzip_ok )
  3025. DO BEGIN
  3026. Inc ( Count, r.Size );
  3027. Inc ( Compressed, r.CompressSize );
  3028. rc := getnextinzip ( r );
  3029. END; {while }
  3030. closezipfile ( r );
  3031. UnZipSize := Count;
  3032. END; { UnZipSize }
  3033. {***************************************************************************}
  3034. FUNCTION SetUnZipReportProc ( aProc : UnzipReportProc ) : Pointer;
  3035. BEGIN
  3036. {$IFDEF FPC}
  3037. SetUnZipReportProc := ZipReport; {save and return original}
  3038. {$ELSE}
  3039. SetUnZipReportProc := @ZipReport; {save and return original}
  3040. {$ENDIF}
  3041. ZipReport := aProc;
  3042. END; { SetUnZipReportProc }
  3043. {***************************************************************************}
  3044. FUNCTION SetUnZipQuestionProc ( aProc : UnzipQuestionProc ) : Pointer;
  3045. BEGIN
  3046. {$IFDEF FPC}
  3047. SetUnZipQuestionProc := ZipQuestion; {save and return original}
  3048. {$ELSE}
  3049. SetUnZipQuestionProc := @ZipQuestion; {save and return original}
  3050. {$ENDIF}
  3051. ZipQuestion := aProc;
  3052. END; { SetUnZipQuestionProc }
  3053. {***************************************************************************}
  3054. FUNCTION SetNoRecurseDirs ( DontRecurse : Boolean ) : Boolean;
  3055. BEGIN
  3056. SetNoRecurseDirs := NoRecurseDirs;
  3057. NoRecurseDirs := DontRecurse;
  3058. END; { SetNoRecurseDirs }
  3059. {***************************************************************************}
  3060. {***************************************************************************}
  3061. PROCEDURE ChfUnzip_Init;
  3062. BEGIN
  3063. slide := NIL; {unused}
  3064. {$ifdef windows}
  3065. inuse := FALSE; {Not yet in use!}
  3066. lastusedtime := 0; {Not yet used}
  3067. {$endif}
  3068. if inuse then; { to remove warning }
  3069. SetUnZipReportProc ( NIL );
  3070. SetUnZipQuestionProc ( NIL );
  3071. SetNoRecurseDirs ( FALSE );
  3072. END;
  3073. {***************************************************************************}
  3074. {***************************************************************************}
  3075. {***************************************************************************}
  3076. BEGIN
  3077. ChfUnzip_Init;
  3078. END.