unzip.pp 97 KB

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