mod_gzip.c 275 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843
  1. /* ====================================================================
  2. * Copyright (c) 1995-2000 The Apache Group. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. *
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in
  13. * the documentation and/or other materials provided with the
  14. * distribution.
  15. *
  16. * 3. All advertising materials mentioning features or use of this
  17. * software must display the following acknowledgment:
  18. * "This product includes software developed by the Apache Group
  19. * for use in the Apache HTTP server project (http://www.apache.org/)."
  20. *
  21. * 4. The names "Apache Server" and "Apache Group" must not be used to
  22. * endorse or promote products derived from this software without
  23. * prior written permission. For written permission, please contact
  24. * apache@apache.org.
  25. *
  26. * 5. Products derived from this software may not be called "Apache"
  27. * nor may "Apache" appear in their names without prior written
  28. * permission of the Apache Group.
  29. *
  30. * 6. Redistributions of any form whatsoever must retain the following
  31. * acknowledgment:
  32. * "This product includes software developed by the Apache Group
  33. * for use in the Apache HTTP server project (http://www.apache.org/)."
  34. *
  35. * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
  36. * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  37. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  38. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
  39. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  41. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  42. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  43. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  44. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  45. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  46. * OF THE POSSIBILITY OF SUCH DAMAGE.
  47. * ====================================================================
  48. *
  49. * This software consists of voluntary contributions made by many
  50. * individuals on behalf of the Apache Group and was originally based
  51. * on public domain software written at the National Center for
  52. * Supercomputing Applications, University of Illinois, Urbana-Champaign.
  53. * For more information on the Apache Group and the Apache HTTP server
  54. * project, please see <http://www.apache.org/>.
  55. *
  56. */
  57. /*
  58. * mod_gzip.c
  59. *
  60. * Apache gzip compression module.
  61. *
  62. * This module adds 'on the fly' compression of HTTP content to
  63. * any Apache Web Server. It uses the IETF Content-encoding standard(s).
  64. *
  65. * It will compress both static files and the output of any CGI
  66. * program inclding shell scripts, perl scripts, executables,
  67. * PHP used as CGI, etc.
  68. *
  69. * There is NO client-side software required for using this module
  70. * other than any fully HTTP 1.1 compliant user agent.
  71. *
  72. * Any fully HTTP 1.1 compliant user agent will be able to receive and
  73. * automatically decode the compressed content.
  74. *
  75. * All fully HTTP 1.1 compliant user agents that are capable of receiving
  76. * gzip encoded data will indicate their ability to do so by adding the
  77. * standard "Accept-Encoding: gzip" field to the inbound request header.
  78. *
  79. * This module may be compiled as a stand-alone external 'plug-in'
  80. * or be compiled into the Apache core server as a 'built-in' module.
  81. *
  82. * Sponsor: Remote Communications, Inc. http://www.RemoteCommunications.com/
  83. * Authors: Konstantin Balashov, Alex Kosobrukhov and Kevin Kiley.
  84. * Contact: info@RemoteCommunications.com
  85. *
  86. * Initial public release date: 13-Oct-2000
  87. *
  88. * Miscellaneous release notes:
  89. *
  90. * THIS IS A COMPLETELY SELF-CONTAINED MODULE. MOD_GZIP.C IS THE
  91. * ONY SOURCE CODE FILE THERE IS AND THERE ARE NO MODULE SPECIFIC
  92. * HEADER FILES OR THE NEED FOR ANY 3RD PARTY COMPRESSION LIBRARIES.
  93. * ALL OF THE COMPRESSION CODE NEEDED BY THIS MODULE IS CONTAINED
  94. * WITHIN THIS SINGLE SOURCE FILE.
  95. *
  96. * Many standard compression libraries are not designed or optimized
  97. * for use as real-time compression codecs nor are they guaranteed
  98. * to be 'thread-safe'. The internal compression code used by mod_gzip
  99. * is all of those things. It is a highly-optimized and thread-safe
  100. * implementation of the standard LZ77 + Huffman compression
  101. * technique that has come to be known as GZIP.
  102. *
  103. * MOD_GZIP LOG FORMATS...
  104. *
  105. * mod_gzip makes a number of statistical items for each transaction
  106. * available through the use of Apache's 'LogFormat' directives which
  107. * can be specified in the httpd.conf Apache config file
  108. *
  109. * mod_gzip uses the standard Apache NOTES interface to allow compression
  110. * information to be added to the Apache Web Server log files.
  111. *
  112. * Standard NOTES may be added to Apache logs using the following syntax
  113. * in any LogFormat directive...
  114. * * %...{Foobar}n: The contents of note "Foobar" from another module.
  115. *
  116. * Additional notes about logging compression information...
  117. *
  118. * The Apache LogFormat directive is unable to actually display
  119. * the 'percent' symbol since it is used exclusively as a 'pickup'
  120. * character in the formatting string and cannot be 'escaped' so
  121. * all logging of compression ratios cannot use the PERCENT symbol.
  122. * Use ASCII 'pct.' designation instead for all PERCENTAGE values.
  123. *
  124. * Example: This will display the compression ratio percentage along
  125. * with the standard CLF ( Common Log Format ) information...
  126. *
  127. * Available 'mod_gzip' compression information 'notes'...
  128. *
  129. * %{mod_gzip_result}n - A short 'result' message. Could be OK or DECLINED, etc.
  130. * %{mod_gzip_input_size}n - The size ( in bytes ) of the requested object.
  131. * %{mod_gzip_output_size}n - The size ( in bytes ) of the compressed version.
  132. * %{mod_gzip_compression_ration}n - The compression rate achieved.
  133. *
  134. * LogFormat "%h %l %u %t \"%r\" %>s %b mod_gzip: %{mod_gzip_compression_ratio}npct." common_with_mod_gzip_info1
  135. * LogFormat "%h %l %u %t \"%r\" %>s %b mod_gzip: %{mod_gzip_result}n In:%{mod_gzip_input_size}n Out:%{mod_gzip_output_size}n:%{mod_gzip_compression_ratio}npct." common_with_mod_gzip_info2
  136. *
  137. * If you create your own custom 'LogFormat' lines don't forget that
  138. * the entire LogFormat line must be encased in quote marks or you
  139. * won't get the right results. The visible effect of there not being
  140. * and end-quote on a LogFormat line is that the NAME you are choosing
  141. * for the LogFormat line is the only thing that will appear in the
  142. * log file that tries to use the unbalanced line.
  143. *
  144. * Also... when using the %{mod_gzip_xxxxx}n note references in your
  145. * LogFormat line don't forget to add the lowercase letter 'n' after
  146. * the closing bracket to indicate that this is a module 'note' value.
  147. *
  148. * Once a LogFormat directive has been added to your httpd.conf file
  149. * which displays whatever level of compression information desired
  150. * simply use the 'name' associated with that LogFormat line in
  151. * the 'CustomLog' directive for 'access.log'.
  152. *
  153. * Example: The line below simply changes the default access.log format
  154. * for Apache to the special mog_gzip information record defined above...
  155. * CustomLog logs/access.log common
  156. *
  157. * CustomLog logs/access.log common_with_mod_gzip_info2
  158. *
  159. * Using the 'common_with_mod_gzip_info1' LogFormat line for Apache's
  160. * normal access.log file produces the following results in the access.log
  161. * file when a gigantic 679,188 byte online CD music collection HTML
  162. * document called 'music.htm' is requested and the Server delivers the
  163. * file via mod_gzip compressed 93 percent down to only 48,951 bytes...
  164. *
  165. * 216.20.10.1 [12/Oct...] "GET /music.htm HTTP/1.1" 200 48951 mod_gzip: 93pct.
  166. *
  167. * The line below shows what will appear in the Apache access.log file
  168. * if the more detailed 'common_with_mod_gzip_info2' LogFormat line is used.
  169. * The line has been intentionally 'wrapped' for better display below
  170. * but would normally appear as a single line entry in access.log.
  171. *
  172. * 216.20.10.1 [12/Oct...] "GET /music.htm HTTP/1.1" 200 48951
  173. * mod_gzip: OK In:679188 Out:48951:93pct.
  174. *
  175. * The 'OK' result string shows that the compression was successful.
  176. * The 'In:' value is the size (in bytes) of the requested file and
  177. * the 'Out:' value is the size (in bytes) after compression followed
  178. * by a colon and a number showing that the document was compressed
  179. * 93 percent before being returned to the user.
  180. *
  181. * Please NOTE that if you add any ASCII strings to your LogFormat
  182. * string then they will appear in your log file regardless of
  183. * whether this module was actually 'called' to process the
  184. * transaction or not. If the module was not called to handle the
  185. * transaction then the places where the statistical information
  186. * associated with the 'NOTES' references would normally appear
  187. * will be filled in with 'dashes' to denote 'no value available'.
  188. *
  189. * MOD_GZIP RUNTIME DEBUG...
  190. *
  191. * If you set your default Apache logging level to 'LogLevel debug'
  192. * in your httpd.conf file then this module will add certain
  193. * diagnostic debug messages to your error log for each and every
  194. * transaction that is actually passed to the module.
  195. *
  196. * If Apache does not 'call' this module to handle a particular
  197. * transaction then no special log information will appear in
  198. * your error log(s) for that transaction.
  199. *
  200. * MOD_GZIP CONFIGURATION DIRECTIVES...
  201. *
  202. * The section that follows is a sample mod_gzip configuration
  203. * section that will provide basic compression of all static
  204. * TEXT and HTML files as well as dynamic compression of most
  205. * standard CGI including Shell scripts, Perl, PHP, etc.
  206. *
  207. * The configuration directives themselves are documented in more
  208. * detail in the README and INSTALL files that accompany this module.
  209. *
  210. * You should be able to simply 'cut and paste' the follwing section
  211. * directly into the BOTTOM of your current httpd.conf Apache
  212. * configuration file and be able to start using mod_gzip immediately.
  213. *
  214. #
  215. # MOD_GZIP Configuration Directives
  216. #
  217. # All you should have to do to get up and running using
  218. # mod_gzip with some basic STATIC and DYNAMIC compression
  219. # capabilites is copy the mod_gzip dynamic library to your
  220. # ../modules directory and then add this entire example
  221. # configuration section to the BOTTOM of your httpd.conf file.
  222. #
  223. # Add this entire section including all lines down to where
  224. # it says '# End of MOD_GZIP Configuration Directives'.
  225. #
  226. # The LoadModule command is included here for clarity
  227. # but you may want to move it the the BOTTOM of your
  228. # current LoadModule list in httpd.conf.
  229. #
  230. # Change the 'mod_gzip_temp_dir' to the name of a directory
  231. # on your machine where temporary workfiles can be created
  232. # and destroyed. This directory MUST be readable/writable
  233. # by the Server itself while it is running. If the directory
  234. # does not exist you must create it yourself with the right
  235. # permissions before running the Server.
  236. #
  237. # If no 'mod_gzip_temp_dir' is specified then the default location
  238. # for temporary workfiles will be 'ServerRoot' directory.
  239. #
  240. # The special mod_gzip log formats are, of course, optional.
  241. #
  242. # You must, of course, load the right module name for your OS
  243. # so make sure the correct 'LoadModule' command is uncommented
  244. # directly below...
  245. # Load Win32 module...
  246. LoadModule gzip_module modules/ApacheModuleGzip.dll
  247. # Load UNIX module...
  248. # LoadModule gzip_module modules/mod_gzip.so
  249. LogFormat "%h %l %u %t \"%r\" %>s %b mod_gzip: %{mod_gzip_compression_ratio}npct." common_with_mod_gzip_info1
  250. LogFormat "%h %l %u %t \"%r\" %>s %b mod_gzip: %{mod_gzip_result}n In:%{mod_gzip_input_size}n Out:%{mod_gzip_output_size}n:%{mod_gzip_compression_ratio}npct." common_with_mod_gzip_info2
  251. # NOTE: This 'CustomLog' directive shows how to set your access.log file
  252. # to use the mod_gzip format but please remember that for every 'CustomLog'
  253. # directive that Apache finds in httpd.conf there will be corresponding
  254. # line of output in the access.log file. If you only want ONE line of
  255. # results in access.log for each transaction then be sure to comment out
  256. # any other 'CustomLog' directives so that this is the only one.
  257. CustomLog logs/access.log common_with_mod_gzip_info2
  258. # Runtime control directives...
  259. mod_gzip_on Yes
  260. mod_gzip_do_cgi Yes
  261. mod_gzip_do_static_files Yes
  262. mod_gzip_minimum_file_size 300
  263. mod_gzip_maximum_inmem_size 60000
  264. mod_gzip_keep_workfiles No
  265. mod_gzip_temp_dir "C:/Program Files/Apache Group/Apache/temp"
  266. # Item lists...
  267. #
  268. # Item names can be any one of the following...
  269. #
  270. # cgi-script - A valid 'handler' name
  271. # text/* - A valid MIME type name ( '*' wildcard allowed )
  272. # .phtml - A valid file type extension
  273. # Dynamic items...
  274. #
  275. # NOTE: FOR NOW ALL DYNAMIC ITEMS SHOULD BE
  276. # DECLARED BEFORE ANY STATIC ITEMS TO PREVENT
  277. # PICKUP CONFLICTS. IF YOU USE !cgi-script
  278. # BE SURE IT IS DECLARED BEFORE ANY text/*
  279. # MIME TYPE ENTRIES.
  280. #
  281. # The items listed here are the types of dynamic
  282. # output that will be compressed...
  283. #
  284. # Dynamic items MUST have the "!" BANG character
  285. # on the front of the item name.
  286. #
  287. mod_gzip_item_include !cgi-script
  288. mod_gzip_item_include !.php
  289. mod_gzip_item_include !.php3
  290. mod_gzip_item_include !.phtml
  291. # Static items...
  292. #
  293. # The items listed here are the types of static
  294. # files that will be compressed...
  295. #
  296. # NOTE: FOR NOW ALL STATIC INCLUDES MUST
  297. # COME AFTER DYNAMIC INCLUDES TO PREVENT
  298. # PICKUP CONFLICTS
  299. #
  300. mod_gzip_item_include text/*
  301. # Uncomment this line to compress graphics
  302. # when graphics compression is allowed...
  303. #mod_gzip_item_include image/*
  304. # Exclusions... MIME types and FILE types...
  305. #
  306. # The items listed here will be EXCLUDED from
  307. # any attempt to apply compression...
  308. #
  309. mod_gzip_item_exclude .js
  310. mod_gzip_item_exclude .css
  311. # Exclusions... HTTP support levels...
  312. #
  313. # By specifying a certain minimum level of HTTP support
  314. # certain older user agents ( browsers ) can be
  315. # automatically excluded from receiving compressed data.
  316. #
  317. # The item value should be in the same HTTP numeric format
  318. # that Apache uses to designate HTTP version levels.
  319. #
  320. # 1001 = HTTP/1.1
  321. #
  322. # So 'mod_gzip_min_http 1001' means that a requesting
  323. # user agent ( browser ) must report a minimum HTTP support
  324. # level of 1.1 or it will not receive any compressed data.
  325. #
  326. mod_gzip_min_http 1001
  327. # Debugging...
  328. #
  329. # If your Apache 'LogLevel' is set to 'debug' then
  330. # mod_gzip will add some diagnostic and compression
  331. # information to your error.log file for each request
  332. # that is processed by mod_gzip.
  333. #
  334. # LogLevel debug
  335. # End of MOD_GZIP Configuration Directives
  336. * End of inline comments
  337. */
  338. #include <stdlib.h>
  339. /*
  340. * Apache headers...
  341. */
  342. #define CORE_PRIVATE
  343. #include "httpd.h"
  344. #include "http_config.h"
  345. #include "http_core.h"
  346. #include "http_log.h"
  347. #include "http_main.h"
  348. #include "http_protocol.h"
  349. #include "util_script.h"
  350. /*
  351. * Add this header for ap_server_root[ MAX_STRING_LEN ] global...
  352. *
  353. * #include "http_conf_globals.h"
  354. *
  355. * ...or just include what we need from http_conf_globals.h
  356. * since that is, in fact, only 1 item at this time.
  357. */
  358. extern API_VAR_EXPORT char ap_server_root[ MAX_STRING_LEN ];
  359. /*
  360. * Add this header to get 'ap_update_mtime()' prototype...
  361. *
  362. * #include "http_request.h"
  363. *
  364. * ...or just include what we need from http_request.h since
  365. * that is, in fact, only 1 item at this time.
  366. */
  367. extern API_EXPORT(time_t)
  368. ap_update_mtime(request_rec *r, time_t dependency_mtime);
  369. /*
  370. * Version information...
  371. *
  372. * Since this product is 'married' to the ASF Apache Web Server
  373. * the version numbers should always 'match' the changing
  374. * version numbers of Apache itself so users can be sure
  375. * they have the 'right' module. This allows us to move the
  376. * version numbers either backwards or forwards in case issues
  377. * arise which require specific versions of mod_gzip for
  378. * specific versions of Apache.
  379. *
  380. * The original code was first tested against the Apache 1.3.14
  381. * release but should be compatible with the entire 1.3.x series.
  382. * If earlier 1.3.x versions of Apache required special versions
  383. * then the mod_gzip version number will still match the Apache
  384. * version number ( As in... mod_gzip v1.3.12.1, if needed ).
  385. *
  386. * If a special version is required for Apache 2.0 then the
  387. * version number(s) will change to match release numbers in
  388. * that series. ( As in... mod_gzip v 2.0.1.1, etc. ).
  389. *
  390. * The first 3 numbers of the version are always the equivalent
  391. * Apache release numbers. The fourth number is always the actual
  392. * mod_gzip 'build' number for that version of Apache.
  393. */
  394. char mod_gzip_version[] = "1.3.14.5"; /* Global version string */
  395. /*
  396. * Declare the NAME by which this module will be known.
  397. * This is the NAME that will be used in LoadModule command(s).
  398. */
  399. extern module MODULE_VAR_EXPORT gzip_module;
  400. /*
  401. * Allow this module to 'read' config information from
  402. * ( and interact with ) the 'real' mod_cgi module...
  403. */
  404. extern module cgi_module;
  405. /*
  406. * Some compile-time code inclusion switches...
  407. */
  408. /*
  409. * Turn MOD_GZIP_ALLOWS_INTERNAL_COMMANDS switch ON to allow
  410. * information requests to be sent via any standard browser.
  411. */
  412. #define MOD_GZIP_ALLOWS_INTERNAL_COMMANDS
  413. /*
  414. * Turn MOD_GZIP_USES_APACHE_LOGS switch ON to include the
  415. * code that can update Apache logs with compression information.
  416. */
  417. #define MOD_GZIP_USES_APACHE_LOGS
  418. /*
  419. * Turn MOD_GZIP_USES_AP_SEND_MMAP switch ON to use the
  420. * ap_send_mmap() method for transmitting data. If this
  421. * switch is OFF then the default is to use ap_rwrite().
  422. * This might need to be platform specific at some point.
  423. */
  424. #define MOD_GZIP_USES_AP_SEND_MMAP
  425. /*
  426. * Turn MOD_GZIP_DEBUG1 switch ON for verbose diags.
  427. * This is normally OFF by default and should only be
  428. * used for diagnosing problems. The log output is
  429. * VERY detailed and the log files will be HUGE.
  430. */
  431. /*
  432. #define MOD_GZIP_DEBUG1
  433. */
  434. /*
  435. * Some useful instance globals...
  436. */
  437. #ifndef MOD_GZIP_MAX_PATH_LEN
  438. #define MOD_GZIP_MAX_PATH_LEN 512
  439. #endif
  440. char mod_gzip_temp_dir[ MOD_GZIP_MAX_PATH_LEN + 2 ];
  441. long mod_gzip_iusn = 0; /* Instance Unique Sequence Number */
  442. long mod_gzip_maximum_inmem_size = 60000L;
  443. long mod_gzip_minimum_file_size = 300L;
  444. #ifdef WIN32
  445. char mod_gzip_dirsep[]="\\"; /* Dir separator is a backslash for Windows */
  446. #else /* !WIN32 */
  447. char mod_gzip_dirsep[]="/"; /* Dir separator is a forward slash for UNIX */
  448. #endif /* WIN32 */
  449. /*
  450. * The Compressed Object Cache control structure...
  451. */
  452. #define MOD_GZIP_SEC_ONE_DAY 86400 /* Total seconds in one day */
  453. #define MOD_GZIP_SEC_ONE_HR 3600 /* Total seconds in one hour */
  454. #define MOD_GZIP_DEFAULT_CACHE_SPACE 5
  455. #define MOD_GZIP_DEFAULT_CACHE_MAXEXPIRE MOD_GZIP_SEC_ONE_DAY
  456. #define MOD_GZIP_DEFAULT_CACHE_EXPIRE MOD_GZIP_SEC_ONE_HR
  457. #define MOD_GZIP_DEFAULT_CACHE_LMFACTOR (0.1)
  458. #define MOD_GZIP_DEFAULT_CACHE_COMPLETION (0.9)
  459. struct mod_gzip_cache_conf {
  460. const char *root; /* The location of the cache directory */
  461. off_t space; /* Maximum cache size (in 1024 bytes) */
  462. char space_set;
  463. time_t maxexpire; /* Maximum time to keep cached files (secs) */
  464. char maxexpire_set;
  465. time_t defaultexpire; /* Default time to keep cached file (secs) */
  466. char defaultexpire_set;
  467. double lmfactor; /* Factor for estimating expires date */
  468. char lmfactor_set;
  469. time_t gcinterval; /* Garbage collection interval (secs) */
  470. char gcinterval_set;
  471. int dirlevels; /* Number of levels of subdirectories */
  472. char dirlevels_set;
  473. int dirlength; /* Length of subdirectory names */
  474. char dirlength_set;
  475. };
  476. /*
  477. * The Inclusion/Exclusion map item structure...
  478. */
  479. #define MOD_GZIP_IMAP_MAXNAMES 256
  480. #define MOD_GZIP_IMAP_MAXNAMELEN 90
  481. #define MOD_GZIP_IMAP_ISMIME 1
  482. #define MOD_GZIP_IMAP_ISEXT 2
  483. #define MOD_GZIP_IMAP_ISHANDLER 3
  484. #define MOD_GZIP_IMAP_STATIC1 9001
  485. #define MOD_GZIP_IMAP_DYNAMIC1 9002
  486. #define MOD_GZIP_IMAP_DECLINED1 9003
  487. typedef struct {
  488. int include; /* 1=Include 0=Exclude */
  489. int type; /* _ISMIME, _ISEXT, _ISHANDLER, etc. */
  490. int action; /* _STATIC1, _DYNAMIC1, etc. */
  491. char name[ MOD_GZIP_IMAP_MAXNAMELEN + 2 ];
  492. } mod_gzip_imap;
  493. /*
  494. * The primary module configuration record...
  495. */
  496. typedef struct {
  497. struct mod_gzip_cache_conf cache; /* Compressed Object Cache control */
  498. int req; /* 1=mod_gzip handles requests 0=No */
  499. char req_set; /* Mirrors the 'req' flag */
  500. int do_static_files; /* 1=Yes 0=No */
  501. int do_cgi; /* 1=Yes 0=No */
  502. int keep_workfiles; /* 1=Keep workfiles 0=No */
  503. int min_http; /* Minimum HTTP level ( 1001=HTTP/1.1 ) */
  504. long minimum_file_size; /* Minimum size in bytes for compression attempt */
  505. long maximum_inmem_size; /* Maximum size in bytes for im-memory compress */
  506. /* Inclusion/Exclusion list(s)... */
  507. int imap_total_entries;
  508. mod_gzip_imap imap[ MOD_GZIP_IMAP_MAXNAMES + 1 ];
  509. } mod_gzip_conf;
  510. /*
  511. * The GZP request control structure...
  512. */
  513. #define GZIP_FORMAT (0)
  514. #define DEFLATE_FORMAT (1)
  515. typedef struct _GZP_CONTROL {
  516. int decompress; /* 0=Compress 1=Decompress */
  517. int compression_format; /* GZIP_FORMAT or DEFLATE_FORMAT */
  518. /* Input control... */
  519. int input_ismem; /* Input source is memory buffer, not file */
  520. char *input_ismem_ibuf; /* Pointer to input memory buffer */
  521. long input_ismem_ibuflen; /* Total length of input data */
  522. char input_filename[ MOD_GZIP_MAX_PATH_LEN + 2 ]; /* Input file name */
  523. /* Output control... */
  524. int output_ismem; /* Output source is memory buffer, not file */
  525. char *output_ismem_obuf; /* Pointer to output memory buffer */
  526. long output_ismem_obuflen; /* Maximum length of output data buffer */
  527. char output_filename[ MOD_GZIP_MAX_PATH_LEN + 2 ]; /* Output file name */
  528. /* Results... */
  529. int result_code; /* Result code */
  530. long bytes_out; /* Total number of compressed output bytes */
  531. } GZP_CONTROL;
  532. /*
  533. * Forward prototypes for internal routines...
  534. */
  535. int gzp_main( GZP_CONTROL *gzp ); /* Primary GZP API entry point */
  536. int mod_gzip_request_handler( request_rec *r );
  537. int mod_gzip_cgi_handler( request_rec *r );
  538. int mod_gzip_static_file_handler( request_rec *r );
  539. int mod_gzip_prepare_for_dynamic_call( request_rec *r );
  540. int mod_gzip_imap_show_items( mod_gzip_conf *mgc );
  541. int mod_gzip_get_action_flag( request_rec *r, mod_gzip_conf *conf );
  542. int mod_gzip_ismatch( char *s1, char *s2, int len1, int haswilds );
  543. FILE *mod_gzip_open_output_file(
  544. request_rec *r,
  545. char *output_filename,
  546. int *rc
  547. );
  548. int mod_gzip_create_unique_filename(
  549. mod_gzip_conf *mgc,
  550. char *target,
  551. int targetmaxlen
  552. );
  553. int mod_gzip_encode_and_transmit(
  554. request_rec *r,
  555. char *source,
  556. int source_is_a_file,
  557. long input_size,
  558. int nodecline
  559. );
  560. #ifdef MOD_GZIP_ALLOWS_INTERNAL_COMMANDS
  561. int mod_gzip_send_html_command_response(
  562. request_rec *r, /* Request record */
  563. char *tmp, /* Response to send */
  564. char *ctype /* Content type string */
  565. );
  566. #endif /* MOD_GZIP_ALLOWS_INTERNAL_COMMANDS */
  567. /*
  568. * Module routines...
  569. */
  570. #ifdef MOD_GZIP_DEBUG1
  571. void mod_gzip_printf( const char *fmt, ... )
  572. {
  573. int l;
  574. FILE *log;
  575. va_list ap;
  576. char logname[256];
  577. char log_line[4096];
  578. /* Start... */
  579. /* If UNIX then mod_gzip_dirsep = '/' Backward slash */
  580. /* If WIN32 then mod_gzip_dirsep = '\' Forward slash */
  581. #ifdef FUTURE_USE
  582. /*
  583. For now we need both startup and runtime diags in the same
  584. log so it all goes to ServerRoot. 'mod_gzip_temp_dir' name
  585. isn't even valid until late in the startup process so we
  586. have to write to ServerRoot anyway until temp dir is known.
  587. */
  588. if ( strlen(mod_gzip_temp_dir) ) /* Use temp directory ( if specified )... */
  589. {
  590. sprintf( logname, "%s%smod_gzip.log", mod_gzip_temp_dir, mod_gzip_dirsep );
  591. }
  592. else /* Just use 'ap_server_root' Apache ServerRoot directory... */
  593. {
  594. sprintf( logname, "%s%smod_gzip.log", ap_server_root, mod_gzip_dirsep );
  595. }
  596. #endif /* FUTURE_USE */
  597. /* Just use ServerRoot for now... */
  598. sprintf( logname, "%s%smod_gzip.log", ap_server_root, mod_gzip_dirsep );
  599. log = fopen( logname,"a" );
  600. if ( !log ) /* Log file did not open... */
  601. {
  602. /* Just turn and burn... */
  603. return; /* Void return */
  604. }
  605. /* Get the variable parameter list... */
  606. va_start( ap, fmt );
  607. l = vsprintf(log_line, fmt, ap);
  608. /* See if we need to add LF... */
  609. if ( l > 0 )
  610. {
  611. if ( log_line[l-1] != '\n' )
  612. {
  613. log_line[l]='\n';
  614. l++;
  615. }
  616. log_line[l+1] = 0;
  617. }
  618. fprintf( log, "%s", log_line );
  619. fclose( log );
  620. va_end(ap); /* End session */
  621. return; /* Void return */
  622. }/* End of log_d() */
  623. void mod_gzip_hexdump( char *buffer, int buflen )
  624. {
  625. int i,o1,o2,o3;
  626. int len1;
  627. int len2;
  628. char ch1;
  629. char ch2;
  630. char s[40];
  631. char l1[129];
  632. char l2[129];
  633. char l3[300];
  634. long offset1=0L;
  635. /* Start... */
  636. o1=0;
  637. o2=0;
  638. o3=0;
  639. l1[0] = 0;
  640. l2[0] = 0;
  641. l3[0] = 0;
  642. offset1 = 0;
  643. for ( i=0; i<buflen; i++ )
  644. {
  645. ch1 = (char) *buffer++;
  646. /*------------------------------------------------------------*/
  647. /* WARNING: UNIX hates anything non-printable. It can mess */
  648. /* up the terminal output by trying to use SLASH */
  649. /* ESCAPE substitutions... */
  650. /*------------------------------------------------------------*/
  651. /* DOUBLE WARNING!: We MUST mask the per-cent char (37 dec) */
  652. /* and the 'backslash' char ( 92 decimal ) or the UNIX */
  653. /* STDIO calls could CRASH. They are just brain-dead enough */
  654. /* to actually try to respond to these chars in the output */
  655. /* stream and convert them to HEX equivalents which could */
  656. /* lengthen the output string(s) and CRASH the output buffer. */
  657. /*------------------------------------------------------------*/
  658. /* ASTERISK = ASC 42 */
  659. /* LEFT APOSTROPHE = ASC 96 */
  660. /* RIGHT APOSTROPHE = ASC 39 */
  661. /* PERIOD = ASC 46 */
  662. /* CR DUMP SYMBOL = ASC 67 ( The letter C ) */
  663. /* LF DUMP SYMBOL = ASC 76 ( The letter L ) */
  664. #define DUMPIT_ASTERISK 42
  665. #define DUMPIT_LAPOSTROPHE 96
  666. #define DUMPIT_RAPOSTROPHE 39
  667. #define DUMPIT_PERIOD 46
  668. #define DUMPIT_CR 67
  669. #define DUMPIT_LF 76
  670. #ifdef MASK_ONLY_CERTAIN_CHARS
  671. if ( ch1 == 0 ) ch2 = DUMPIT_PERIOD;
  672. else if ( ch1 == 13 ) ch2 = DUMPIT_CR;
  673. else if ( ch1 == 10 ) ch2 = DUMPIT_LF;
  674. else if ( ch1 == 9 ) ch2 = DUMPIT_LAPOSTROPHE;
  675. else ch2 = ch1;
  676. #endif
  677. #define MASK_ALL_NON_PRINTABLE_CHARS
  678. #ifdef MASK_ALL_NON_PRINTABLE_CHARS
  679. /* Mask all control chars and high ends chars for UNIX or */
  680. /* TTY console screws up... */
  681. if ( ch1 == 13 ) ch2 = DUMPIT_CR;
  682. else if ( ch1 == 10 ) ch2 = DUMPIT_LF;
  683. else if ( ch1 < 32 ) ch2 = DUMPIT_PERIOD;
  684. else if ( ch1 > 126) ch2 = DUMPIT_LAPOSTROPHE;
  685. else if ( ch1 == 37 ) ch2 = DUMPIT_ASTERISK; /* Mask PERCENT for UNIX */
  686. else if ( ch1 == 92 ) ch2 = DUMPIT_ASTERISK; /* Mask BACKSLASH for UNIX */
  687. else ch2 = ch1;
  688. /* ENDIF on MASK_ALL_NON_PRINTABLE_CHARS */
  689. #endif
  690. l2[o2++] = ch2;
  691. sprintf( s, "%02X", ch1 );
  692. if ( strlen(s) > 2 ) s[2]=0; /* Prevent overflow */
  693. len1 = strlen(s);
  694. len2 = strlen(l1);
  695. if ( strlen(l1) < (sizeof(l1) - (len1+1)) )
  696. {
  697. strcat( l1, s );
  698. strcat( l1, " " );
  699. }
  700. if ( o2 >= 16 )
  701. {
  702. l2[o2]=0;
  703. mod_gzip_printf( "%6lu| %-49.49s| %-16.16s |\n", offset1, l1, l2 );
  704. offset1 += o2;
  705. o1=0;
  706. o2=0;
  707. o3=0;
  708. l1[0] = 0;
  709. l2[0] = 0;
  710. l3[0] = 0;
  711. }
  712. }/* End 'for( i=0; i<buflen; i++ )' loop... */
  713. /* Print remainder ( if anything ) */
  714. if ( o2 > 0 )
  715. {
  716. l2[o2]=0;
  717. mod_gzip_printf( "%6lu| %-49.49s| %-16.16s |\n", offset1, l1, l2 );
  718. offset1 += o2;
  719. o1 = o2 = o3 = 0;
  720. l1[0] = 0;
  721. l2[0] = 0;
  722. l3[0] = 0;
  723. }
  724. }/* End of mod_gzip_hexdump() */
  725. #endif /* MOD_GZIP_DEBUG1 */
  726. static void mod_gzip_init( server_rec *server, pool *p )
  727. {
  728. /*
  729. * The module initialization procedure...
  730. */
  731. FILE *fh1;
  732. char filename[ 512 ];
  733. #ifdef MOD_GZIP_DEBUG1
  734. char cn[]="mod_gzip_init()";
  735. #endif
  736. mod_gzip_conf *mgc;
  737. /* Start... */
  738. #ifdef MOD_GZIP_DEBUG1
  739. mod_gzip_printf( "%s: Entry...\n", cn );
  740. #endif
  741. /*
  742. * Set some instance specific globals...
  743. *
  744. * The default 'temp' dir, lacking an httpd.conf config file
  745. * override, is the Apache 'ServerRoot'. Don't assume that /logs
  746. * dir exists because some Apache installations just use syslog
  747. * or stderr as their log output target.
  748. *
  749. * On most Apache installations 'ServerRoot' is automatically
  750. * readable/writable by the Server while it is running.
  751. *
  752. * On systems where it is not there MUST be an override
  753. * in the httpd.conf file.
  754. *
  755. * See the comments regarding the 'mod_gzip_temp_dir' directive
  756. * in the httpd.conf configuration file.
  757. */
  758. mgc = ( mod_gzip_conf * )
  759. ap_get_module_config(server->module_config, &gzip_module);
  760. /* Make sure we can read/write the temp directory... */
  761. sprintf( filename, "%s%smod_gzip.id", mgc->cache.root, mod_gzip_dirsep );
  762. fh1 = fopen( filename, "wb" );
  763. if ( !fh1 ) /* Write an ERROR to console and to log(s)... */
  764. {
  765. fprintf( stderr, "mod_gzip: Cannot read/write dir/file [%s]\n",filename);
  766. fprintf( stderr, "mod_gzip: Make sure the directory exists and that the Server\n");
  767. fprintf( stderr, "mod_gzip: has read/write permission(s) for the directory.\n");
  768. fprintf( stderr, "mod_gzip: See the 'mod_gzip_temp_dir' configuration notes.\n");
  769. /* This is a startup ERROR and has to be fixed... */
  770. ap_log_error( "",0,APLOG_NOERRNO|APLOG_ERR, server,
  771. "mod_gzip: Cannot read/write dir/file [%s]", filename);
  772. ap_log_error( "",0,APLOG_NOERRNO|APLOG_ERR, server,
  773. "mod_gzip: Make sure the directory exists and that the Server");
  774. ap_log_error( "",0,APLOG_NOERRNO|APLOG_ERR, server,
  775. "mod_gzip: has read/write permission(s) for the directory.");
  776. ap_log_error( "",0,APLOG_NOERRNO|APLOG_ERR, server,
  777. "mod_gzip: See the 'mod_gzip_temp_dir' configuration notes.");
  778. }
  779. else /* File opened OK... just add some data and close it... */
  780. {
  781. /*
  782. * Since this is just a MARK file we could simply wipe
  783. * it out but might as well print the actual version
  784. * number into it and leave it there in case there is
  785. * any question about which version is actually running.
  786. */
  787. fprintf( fh1, "mod_gzip version %s\n", mod_gzip_version );
  788. fclose( fh1 );
  789. }
  790. #ifdef MOD_GZIP_DEBUG1
  791. mod_gzip_imap_show_items( (mod_gzip_conf *) mgc ); /* Show item list */
  792. mod_gzip_printf( "%s: Exit > return( void ) >\n", cn );
  793. mod_gzip_printf( "\n" ); /* Separator for log file */
  794. #endif
  795. }/* End of mod_gzip_init() */
  796. int mod_gzip_strnicmp( char *s1, char *s2, int len1 )
  797. {
  798. /* Behaves just like strnicmp() but IGNORES differences */
  799. /* between FORWARD or BACKWARD slashes in a STRING... */
  800. /* Also uses straight pointers and avoids stdlib calls. */
  801. int i;
  802. char ch1;
  803. char ch2;
  804. /* WARNING! We MUST have a check for 'NULL' on the pointer(s) */
  805. /* themselves or we might GP ( like NETSCAPE does ) */
  806. /* if a 'NULL' pointer is passed to this routine... */
  807. if ( ( s1 == 0 ) || ( s2 == 0 ) )
  808. {
  809. /* SAFETY! If pointer itself if NULL */
  810. /* don't enter LOOP or NETSCAPE will GP... */
  811. return( 1 ); /* Return '1' for NOMATCH... */
  812. }
  813. for ( i=0; i<len1; i++ )
  814. {
  815. if ( ( *s1 == 0 ) || ( *s2 == 0 ) ) return( 1 ); /* No match! */
  816. ch1 = *s1;
  817. ch2 = *s2;
  818. if ( ch1 > 96 ) ch1 -= 32;
  819. if ( ch2 > 96 ) ch2 -= 32;
  820. if ( ch1 == '/' ) ch1 = '\\';
  821. if ( ch2 == '/' ) ch2 = '\\';
  822. if ( ch1 != ch2 ) return( 1 ); /* No match! */
  823. s1++;
  824. s2++;
  825. }/* End 'i' loop */
  826. /* If we make it to here then everything MATCHED! */
  827. return( 0 ); /* MATCH! */
  828. }/* End mod_gzip_strnicmp() */
  829. extern API_VAR_EXPORT module *top_module;
  830. struct _table {
  831. array_header a;
  832. #ifdef MAKE_TABLE_PROFILE
  833. void *creator;
  834. #endif
  835. };
  836. typedef struct _table _table;
  837. const char *mod_gzip_isscript( request_rec *r, _table *t, const char *key)
  838. {
  839. /*
  840. * Get a 'handler' name for a MIME type right out of
  841. * the Apache 'Action' table(s)...
  842. *
  843. * Example:
  844. *
  845. * If "key" is "applications/x-httpd-php3"
  846. * then this search will return "/php3/php.exe"
  847. * or whatever the equivalent PHP executable
  848. * pathname is as specified by an 'Action' statement
  849. * in the httpd.conf configuration file.
  850. *
  851. * This pathname might still have 'aliases' in it
  852. * so we will have to consult with mod_alias
  853. * following this call and get any aliases converted.
  854. */
  855. table_entry *elts =
  856. (table_entry *) t->a.elts;
  857. int i;
  858. char cn[]="mod_gzip_isscript()";
  859. /*
  860. * Start...
  861. */
  862. #ifdef MOD_GZIP_DEBUG1
  863. mod_gzip_printf( "%s: Entry...\n",cn);
  864. mod_gzip_printf( "%s: key=[%s]\n",cn,key );
  865. #endif
  866. if ( key == NULL )
  867. {
  868. #ifdef MOD_GZIP_DEBUG1
  869. mod_gzip_printf( "%s: 'key' has no length\n",cn);
  870. mod_gzip_printf( "%s: Exit > return( NULL ) >\n",cn);
  871. #endif
  872. if ( r->server->loglevel == APLOG_DEBUG )
  873. {
  874. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  875. "%s: Search key is NULL.",cn);
  876. }
  877. return NULL;
  878. }
  879. for (i = 0; i < t->a.nelts; ++i)
  880. {
  881. #ifdef MOD_GZIP_DEBUG1
  882. mod_gzip_printf(
  883. "%s: i=%4.4d Comparing [%s] with elts.key[%s].val[%s]\n",
  884. cn, i, key, elts[i].key, elts[i].val );
  885. #endif
  886. if ( r->server->loglevel == APLOG_DEBUG )
  887. {
  888. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  889. "%s: i=%4.4d Comparing [%s] with elts.key[%s].val[%s]",
  890. cn, i, key, elts[i].key, elts[i].val );
  891. }
  892. if (!strcasecmp(elts[i].key, key))
  893. {
  894. #ifdef MOD_GZIP_DEBUG1
  895. mod_gzip_printf( "%s: MATCH FOUND!",cn);
  896. mod_gzip_printf( "%s: Exit > return(%s) >\n",cn,elts[i].val);
  897. #endif
  898. if ( r->server->loglevel == APLOG_DEBUG )
  899. {
  900. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  901. "%s: MATCH FOUND...",cn);
  902. }
  903. return elts[i].val;
  904. }
  905. }/* End 'i' loop */
  906. if ( r->server->loglevel == APLOG_DEBUG )
  907. {
  908. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  909. "%s: NO MATCH FOUND...",cn);
  910. }
  911. #ifdef MOD_GZIP_DEBUG1
  912. mod_gzip_printf( "%s: NO MATCH FOUND!\n",cn);
  913. mod_gzip_printf( "%s: Exit > return( NULL ) >\n",cn);
  914. #endif
  915. return NULL;
  916. }/* End of 'mod_gzip_isscript()' */
  917. typedef struct {
  918. table *action_types; /* Added with Action... */
  919. char *scripted[METHODS]; /* Added with Script... */
  920. array_header *xmethods; /* Added with Script -- extension methods */
  921. } mod_actions_local_config;
  922. int mod_gzip_run_mod_action( request_rec *r )
  923. {
  924. module *modp;
  925. int count=0;
  926. int pass=0;
  927. mod_actions_local_config *mod_actions_conf;
  928. const char *t=0;
  929. const char *action=0;
  930. #ifdef MOD_GZIP_DEBUG1
  931. char cn[]="mod_gzip_run_mod_action()";
  932. #endif
  933. #ifdef MOD_GZIP_FUTURE_USE
  934. const handler_rec *handp;
  935. #endif
  936. /* Currently 9 possible 'event' handlers. */
  937. /* Actual content handler in a module is 'extra'. */
  938. #define MOD_GZIP_NMETHODS 9
  939. /*
  940. * Start...
  941. */
  942. #ifdef MOD_GZIP_DEBUG1
  943. mod_gzip_printf( "%s: Entry...\n",cn);
  944. mod_gzip_printf( "%s: *IN: r->uri =[%s]\n", cn, r->uri );
  945. mod_gzip_printf( "%s: *IN: r->unparsed_uri=[%s]\n", cn, r->unparsed_uri );
  946. mod_gzip_printf( "%s: *IN: r->filename =[%s]\n", cn, r->filename );
  947. mod_gzip_printf( "%s: r->content_type =[%s]\n", cn,r->content_type);
  948. mod_gzip_printf( "%s: r->handler =[%s]\n", cn,r->handler);
  949. #endif
  950. for ( modp = top_module; modp; modp = modp->next )
  951. {
  952. /* modp->name list will look like this... */
  953. /*--------------------*/
  954. /* 00 [mod_gzip.c] */
  955. /* 01 [mod_isapi.c] */
  956. /* 02 [mod_setenv.c] */
  957. /* 02 [mod_actions.c] */
  958. /* ............... */
  959. /* ............... */
  960. /* 18 [mod_so.c] */
  961. /* 19 [http_core.c] <- Always bottom of list (last one called) */
  962. /*--------------------*/
  963. #ifdef MOD_GZIP_DEBUG1
  964. mod_gzip_printf( "%s: count=%4.4d modp = %10.10ld modp->name=[%s]\n",
  965. cn,count,(long)modp, modp->name );
  966. #endif
  967. if ( mod_gzip_strnicmp( (char *) modp->name, "mod_actions.c", 13 ) == 0 )
  968. {
  969. /* Module information... */
  970. #ifdef MOD_GZIP_DEBUG1
  971. mod_gzip_printf( "%s: ++++++++++ MODULE FOUND!...\n",cn);
  972. mod_gzip_printf( "%s: ++++++++++ modp->module_index = %d\n",cn,(int)modp->module_index);
  973. #endif
  974. /* Get a pointer to the module configuration data... */
  975. mod_actions_conf = (mod_actions_local_config *)
  976. ap_get_module_config(r->per_dir_config, modp );
  977. /* Get script name... */
  978. /* Make 2 passes if necessary. If we don't find a */
  979. /* program name associated with MIME type first */
  980. /* then punt and look for a program name associated */
  981. /* with the r->handler name such as [php-script] */
  982. for ( pass = 0; pass < 2; pass++ )
  983. {
  984. if ( pass == 0 ) /* Check r->content_type first */
  985. {
  986. /* This is the first pass... */
  987. /* Set 'action' search key to 'r->content_type' */
  988. /* so we search for [application/x-httpd-php3] */
  989. action = r->content_type;
  990. }
  991. else if ( pass == 1 ) /* Try r->handler */
  992. {
  993. /* This is the second pass... */
  994. /* Set 'action' search key to 'r->handler' */
  995. /* so we search for [php-script] */
  996. action = r->handler;
  997. }
  998. #ifdef MOD_GZIP_DEBUG1
  999. mod_gzip_printf( "%s: ++++++++++ pass =%d\n", cn,pass);
  1000. mod_gzip_printf( "%s: ++++++++++ t =[%s]\n",cn,t);
  1001. mod_gzip_printf( "%s: ++++++++++ r->content_type =[%s]\n",cn,r->content_type);
  1002. mod_gzip_printf( "%s: ++++++++++ r->handler =[%s]\n",cn,r->handler);
  1003. mod_gzip_printf( "%s: ++++++++++ action =[%s]\n",cn,action);
  1004. mod_gzip_printf( "%s: ++++++++++ r->filename =[%s]\n",cn,r->filename);
  1005. mod_gzip_printf( "%s: ++++++++++ r->uri =[%s]\n",cn,r->uri);
  1006. mod_gzip_printf( "%s: ++++++++++ Call mod_gzip_isscript()...\n",cn);
  1007. #endif
  1008. t =
  1009. mod_gzip_isscript(
  1010. r,
  1011. (_table *) mod_actions_conf->action_types,
  1012. action ? action : ap_default_type(r)
  1013. );
  1014. #ifdef MOD_GZIP_DEBUG1
  1015. mod_gzip_printf( "%s: ++++++++++ Back mod_gzip_isscript()...\n",cn);
  1016. mod_gzip_printf( "%s: ++++++++++ t =[%s]\n",cn,t);
  1017. mod_gzip_printf( "%s: ++++++++++ action =[%s]\n",cn,action);
  1018. #endif
  1019. if ( t )
  1020. {
  1021. /*
  1022. * If a program name was found then make it r->filename
  1023. * and r->uri will become the input name for the program
  1024. */
  1025. r->filename = ap_pstrdup(r->pool,t);
  1026. break;
  1027. }
  1028. }/* End 'for( pass )' loop */
  1029. #ifdef MOD_GZIP_DEBUG1
  1030. mod_gzip_printf( "%s: ++++++++++ r->filename=[%s]\n",cn,r->filename);
  1031. mod_gzip_printf( "%s: ++++++++++ r->uri =[%s]\n",cn,r->uri);
  1032. #endif
  1033. /* If a handler was found we are DONE... */
  1034. if ( t )
  1035. {
  1036. #ifdef MOD_GZIP_DEBUG1
  1037. mod_gzip_printf( "%s: Handler was found...\n",cn);
  1038. mod_gzip_printf( "%s: Exit > return( OK ) >\n",cn);
  1039. #endif
  1040. return OK;
  1041. }
  1042. #ifdef MOD_GZIP_FUTURE_USE
  1043. #ifdef MOD_GZIP_DEBUG1
  1044. mod_gzip_printf( "%s: ++++++++++ METHODS\n",cn);
  1045. mod_gzip_printf( "%s: ++++++++++ modp->translate_handler = %ld\n",cn,(long)modp->translate_handler);
  1046. mod_gzip_printf( "%s: ++++++++++ modp->ap_check_user_id = %ld\n",cn,(long)modp->ap_check_user_id);
  1047. mod_gzip_printf( "%s: ++++++++++ modp->auth_checker = %ld\n",cn,(long)modp->auth_checker);
  1048. mod_gzip_printf( "%s: ++++++++++ modp->access_checker = %ld\n",cn,(long)modp->access_checker);
  1049. mod_gzip_printf( "%s: ++++++++++ modp->type_checker = %ld\n",cn,(long)modp->type_checker);
  1050. mod_gzip_printf( "%s: ++++++++++ modp->fixer_upper = %ld\n",cn,(long)modp->fixer_upper);
  1051. mod_gzip_printf( "%s: ++++++++++ modp->logger = %ld\n",cn,(long)modp->logger);
  1052. mod_gzip_printf( "%s: ++++++++++ modp->header_parser = %ld\n",cn,(long)modp->header_parser);
  1053. mod_gzip_printf( "%s: .......... CONTENT HANDLERS\n",cn);
  1054. #endif /* MOD_GZIP_DEBUG1 */
  1055. if ( !modp->handlers )
  1056. {
  1057. #ifdef MOD_GZIP_DEBUG1
  1058. mod_gzip_printf( "%s: .......... NO CONTENT HANDLERS!\n",cn);
  1059. #endif
  1060. }
  1061. else /* There are some handlers... */
  1062. {
  1063. for ( handp = modp->handlers; handp->content_type; ++handp )
  1064. {
  1065. #ifdef MOD_GZIP_DEBUG1
  1066. mod_gzip_printf( "%s: .......... handp->content_type = [%s]\n",
  1067. cn,handp->content_type);
  1068. mod_gzip_printf( "%s: .......... handp->handler = %ld\n",cn,(long)handp->handler);
  1069. #endif
  1070. }/* End 'handp' loop */
  1071. }/* End 'else' */
  1072. #endif /* MOD_GZIP_FUTURE_USE */
  1073. #ifdef MOD_GZIP_DEBUG1
  1074. mod_gzip_printf( "%s: No handler was found...\n",cn);
  1075. mod_gzip_printf( "%s: Exit > return( DECLINED ) >\n",cn);
  1076. #endif
  1077. return DECLINED;
  1078. }/* 'if ( mod_gzip_strnicmp( (char *) modp->name, "mod_actions.c", 13 ) == 0 )' */
  1079. count++;
  1080. }/* End 'modp' loop... */
  1081. #ifdef MOD_GZIP_DEBUG1
  1082. mod_gzip_printf( "%s: No handler found...\n",cn);
  1083. mod_gzip_printf( "%s: Exit > return( DECLINED ) > ERROR >\n",cn);
  1084. #endif
  1085. return DECLINED;
  1086. }/* End of mod_gzip_run_mod_action() */
  1087. int mod_gzip_run_mod_alias( request_rec *r )
  1088. {
  1089. /*
  1090. * This calls 'translate_alias_redir()' routine in mod_alias.c
  1091. * which will search/replace keywords in the URI with the correct
  1092. * 'ScriptAlias' value(s) from the httpd.conf configuration file.
  1093. *
  1094. * 'translate_alias_redir()' is the name of routine registered
  1095. * by mod_alias.c module as the 'translate' hook.
  1096. */
  1097. module *modp;
  1098. int count=0;
  1099. int rc;
  1100. #ifdef MOD_GZIP_DEBUG1
  1101. char cn[]="mod_gzip_run_mod_alias()";
  1102. #endif
  1103. const handler_rec *handp;
  1104. /* Currently 9 possible 'event' handlers. */
  1105. /* Actual content handler in a module is 'extra'. */
  1106. #define MOD_GZIP_NMETHODS 9
  1107. char *save_filename = 0;
  1108. char *save_uri = 0;
  1109. char nothing[256];
  1110. /*
  1111. * Start...
  1112. */
  1113. #ifdef MOD_GZIP_DEBUG1
  1114. mod_gzip_printf( "%s: Entry...\n",cn);
  1115. mod_gzip_printf( "%s: *IN: r->uri =[%s]\n", cn, r->uri );
  1116. mod_gzip_printf( "%s: *IN: r->unparsed_uri=[%s]\n", cn, r->unparsed_uri );
  1117. mod_gzip_printf( "%s: *IN: r->filename =[%s]\n", cn, r->filename );
  1118. #endif
  1119. for ( modp = top_module; modp; modp = modp->next )
  1120. {
  1121. /* modp->name list will look like this... */
  1122. /*--------------------*/
  1123. /* 00 [mod_gzip.c] */
  1124. /* 01 [mod_isapi.c] */
  1125. /* 02 [mod_setenv.c] */
  1126. /* 02 [mod_actions.c] */
  1127. /* ............... */
  1128. /* ............... */
  1129. /* 18 [mod_so.c] */
  1130. /* 19 [http_core.c] <- Always bottom of list (last one called) */
  1131. /*--------------------*/
  1132. #ifdef MOD_GZIP_DEBUG1
  1133. mod_gzip_printf( "%s: count=%4.4d modp = %10.10ld modp->name=[%s]\n",
  1134. cn,count,(long)modp, modp->name );
  1135. #endif
  1136. /*
  1137. There are only 3 modules that normally have
  1138. 'translate' handlers registered...
  1139. mod_alias
  1140. mod_userdir
  1141. http_core
  1142. */
  1143. if ( ( mod_gzip_strnicmp( (char *) modp->name, "mod_alias.c", 11 ) == 0 ) ||
  1144. ( mod_gzip_strnicmp( (char *) modp->name, "mod_userdir.c", 13 ) == 0 ) ||
  1145. ( mod_gzip_strnicmp( (char *) modp->name, "http_core.c", 11 ) == 0 ) )
  1146. {
  1147. /* Module information... */
  1148. #ifdef MOD_GZIP_DEBUG1
  1149. mod_gzip_printf( "%s: ++++++++++ MODULE FOUND!...\n",cn);
  1150. mod_gzip_printf( "%s: ++++++++++ modp->module_index = %d\n",cn,(int)modp->module_index);
  1151. mod_gzip_printf( "%s: ++++++++++ METHODS\n",cn);
  1152. mod_gzip_printf( "%s: ++++++++++ modp->translate_handler = %ld\n",cn,(long)modp->translate_handler);
  1153. mod_gzip_printf( "%s: ++++++++++ modp->ap_check_user_id = %ld\n",cn,(long)modp->ap_check_user_id);
  1154. mod_gzip_printf( "%s: ++++++++++ modp->auth_checker = %ld\n",cn,(long)modp->auth_checker);
  1155. mod_gzip_printf( "%s: ++++++++++ modp->access_checker = %ld\n",cn,(long)modp->access_checker);
  1156. mod_gzip_printf( "%s: ++++++++++ modp->type_checker = %ld\n",cn,(long)modp->type_checker);
  1157. mod_gzip_printf( "%s: ++++++++++ modp->fixer_upper = %ld\n",cn,(long)modp->fixer_upper);
  1158. mod_gzip_printf( "%s: ++++++++++ modp->logger = %ld\n",cn,(long)modp->logger);
  1159. mod_gzip_printf( "%s: ++++++++++ modp->header_parser = %ld\n",cn,(long)modp->header_parser);
  1160. mod_gzip_printf( "%s: .......... CONTENT HANDLERS\n",cn);
  1161. #endif /* MOD_GZIP_DEBUG1 */
  1162. if ( !modp->handlers )
  1163. {
  1164. #ifdef MOD_GZIP_DEBUG1
  1165. mod_gzip_printf( "%s: .......... NO CONTENT HANDLERS!\n",cn);
  1166. #endif
  1167. }
  1168. else /* There are some handlers... */
  1169. {
  1170. for ( handp = modp->handlers; handp->content_type; ++handp )
  1171. {
  1172. #ifdef MOD_GZIP_DEBUG1
  1173. mod_gzip_printf( "%s: .......... handp->content_type = [%s]\n",
  1174. cn,handp->content_type);
  1175. mod_gzip_printf( "%s: .......... handp->handler = %ld\n",cn,(long)handp->handler);
  1176. #endif
  1177. }/* End 'handp' loop */
  1178. }/* End 'else' */
  1179. if ( modp->translate_handler )
  1180. {
  1181. #ifdef MOD_GZIP_DEBUG1
  1182. mod_gzip_printf( "%s: modp->translate_handler is VALID...\n",cn);
  1183. #endif
  1184. /*
  1185. There are only 3 modules that normally have
  1186. 'translate' handlers registered...
  1187. mod_alias <- Will translate /php3/xxx to c:/php3017/xx
  1188. mod_userdir
  1189. http_core
  1190. */
  1191. /*
  1192. * This calls 'translate_alias_redir()' routine in mod_alias.c
  1193. * which will search/replace keywords in the URI with the correct
  1194. * 'ScriptAlias' value(s) from the httpd.conf configuration file.
  1195. *
  1196. * 'translate_alias_redir()' is the name of routine registered
  1197. * by mod_alias.c module as the 'translate' hook.
  1198. *
  1199. * The 'translate_alias_redir()' function in mod_alias.c
  1200. * is really simple. All it does is check to make sure
  1201. * that r->uri has some value and, if it does, it calls
  1202. * another routine in mod_alias.c named 'try_alias_list()'
  1203. * which replaces any 'ScriptAlias' phrases with their
  1204. * real values and copies the result to r->filename.
  1205. *
  1206. * We must make sure the phrase we want translated is
  1207. * in r->uri and check for results in r->filename.
  1208. */
  1209. /*
  1210. * Calling mod_alias.c translate handler will correctly
  1211. * translate 'ScriptAlias' phrases such as...
  1212. *
  1213. * URI value...
  1214. * /php3/php3.exe
  1215. * becomes...
  1216. * c:/php3017/php3.exe
  1217. */
  1218. save_filename = r->filename;
  1219. save_uri = r->uri;
  1220. nothing[0] = 0;
  1221. r->filename = nothing;
  1222. r->uri = save_filename; /* Phrase to translate */
  1223. #ifdef MOD_GZIP_DEBUG1
  1224. mod_gzip_printf( "%s: r->filename = [%s]\n",cn,r->filename);
  1225. mod_gzip_printf( "%s: r->uri = [%s]\n",cn,r->uri);
  1226. mod_gzip_printf( "%s: Call (modp->translate_handler)(r)...\n",cn);
  1227. #endif
  1228. /* Call the actual translate routine in mod_action module... */
  1229. rc = (modp->translate_handler)( (request_rec *) r );
  1230. #ifdef MOD_GZIP_DEBUG1
  1231. mod_gzip_printf( "%s: Back (modp->translate_handler)(r)...\n",cn);
  1232. mod_gzip_printf( "%s: r->filename = [%s]\n",cn,r->filename);
  1233. mod_gzip_printf( "%s: r->uri = [%s]\n",cn,r->uri);
  1234. #endif
  1235. /*
  1236. * If there was a successful translation then the return
  1237. * code will be OK and the translated URI will be sitting
  1238. * in r->filename. If there were no phrase replacements
  1239. * then the return code will be DECLINED.
  1240. */
  1241. #ifdef MOD_GZIP_DEBUG1
  1242. if ( rc == OK )
  1243. {
  1244. mod_gzip_printf( "%s: rc = %d = OK\n",cn, rc );
  1245. }
  1246. else if ( rc == DECLINED )
  1247. {
  1248. mod_gzip_printf( "%s: rc = %d = DECLINED\n",cn, rc );
  1249. }
  1250. else if ( rc == DONE ) /* -2 means 'totally done' */
  1251. {
  1252. mod_gzip_printf( "%s: rc = %d = DONE\n",cn, rc );
  1253. }
  1254. else /* Probably an HTTP ERROR value... */
  1255. {
  1256. mod_gzip_printf( "%s: rc = %d = HTTP_ERROR?\n",cn, rc );
  1257. }
  1258. #endif /* MOD_GZIP_DEBUG */
  1259. /*
  1260. * Evaluate the results...
  1261. */
  1262. if ( rc == OK ) /* There was a phrase translation... */
  1263. {
  1264. #ifdef MOD_GZIP_DEBUG1
  1265. mod_gzip_printf( "%s: There was a phrase translation...\n",cn );
  1266. mod_gzip_printf( "%s: Keeping new 'r->filename'\n",cn );
  1267. #endif
  1268. /* Do NOT restore 'r->filename' to original value... */
  1269. /* Just fall-through and continue... */
  1270. }
  1271. else /* No phrases were replaced... */
  1272. {
  1273. #ifdef MOD_GZIP_DEBUG1
  1274. mod_gzip_printf( "%s: There were NO phrases translated...\n",cn );
  1275. mod_gzip_printf( "%s: Restoring 'r->filename' to original value...\n",cn );
  1276. #endif
  1277. /* Restore 'r->filename' to original value... */
  1278. r->filename = save_filename;
  1279. }
  1280. /* Always 'restore' URI to original value... */
  1281. r->uri = save_uri;
  1282. /* Turn and burn... */
  1283. #ifdef MOD_GZIP_DEBUG1
  1284. mod_gzip_printf( "%s: Exit > return( rc=%d ) >\n",cn,rc);
  1285. #endif
  1286. return rc;
  1287. }
  1288. else /* modp->translate_handler is NULL... */
  1289. {
  1290. #ifdef MOD_GZIP_DEBUG1
  1291. mod_gzip_printf( "%s: modp->translate_handler is NOT VALID.\n",cn);
  1292. #endif
  1293. }
  1294. }/* 'if ( mod_gzip_strnicmp( (char *) modp->name, "mod_actions.c", 13 ) == 0 )' */
  1295. count++;
  1296. }/* End 'modp' loop... */
  1297. #ifdef MOD_GZIP_DEBUG1
  1298. mod_gzip_printf( "%s: No handler found...\n",cn);
  1299. mod_gzip_printf( "%s: Exit > return( DECLINED ) > ERROR >\n",cn);
  1300. #endif
  1301. return DECLINED;
  1302. }/* End of mod_gzip_run_mod_alias() */
  1303. static int mod_gzip_handler( request_rec *r )
  1304. {
  1305. /*
  1306. * The primary module request handler...
  1307. */
  1308. int rc=0;
  1309. char cn[]="mod_gzip_handler()";
  1310. int access_status=0;
  1311. int access_status2=0;
  1312. /*
  1313. * Start...
  1314. */
  1315. if ( r->server->loglevel == APLOG_DEBUG )
  1316. {
  1317. /*
  1318. * If the user has 'LogLevel debug' set in httpd.conf then
  1319. * it's ok to go ahead and strike some diagnostic information
  1320. * to the Apache log(s).
  1321. *
  1322. * APLOG_MARK is what supplies __FILE__ and __LINE__ info and
  1323. * it is actually defined in HTTP_LOG.H as...
  1324. *
  1325. * define APLOG_MARK __FILE__,__LINE__
  1326. *
  1327. * Sometimes the original __FILE__ name is very long and is
  1328. * fairly useless information cluttering up the logs when
  1329. * there is only 1 possible source file name so
  1330. * to NOT use it just supply 2 dummy parameters instead.
  1331. *
  1332. * The first parameter can be a custom message instead of
  1333. * the __FILE__ string that would normally be substituted.
  1334. */
  1335. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  1336. "%s: Entry point...",cn);
  1337. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  1338. "%s: r->the_request = [%s]",cn,r->the_request);
  1339. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  1340. "%s: r->protocol = [%s]",cn,r->protocol);
  1341. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  1342. "%s: r->proto_num = %d",cn,(int)r->proto_num);
  1343. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  1344. "%s: r->filename = [%s]",cn,r->filename);
  1345. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  1346. "%s: r->uri = [%s]",cn,r->uri);
  1347. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  1348. "%s: r->content_type = [%s]",cn,r->content_type);
  1349. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  1350. "%s: r->handler = [%s]",cn,r->handler);
  1351. }/* End 'if( r->server->loglevel == APLOG_DEBUG )' */
  1352. #ifdef MOD_GZIP_DEBUG1
  1353. mod_gzip_printf( "\n" );
  1354. mod_gzip_printf( "%s: ```` Entry...\n",cn);
  1355. mod_gzip_printf( "%s: -------------------------------------------------------------\n",cn);
  1356. mod_gzip_printf( "%s: *IN: r->uri =[%s]\n", cn, r->uri );
  1357. mod_gzip_printf( "%s: *IN: r->unparsed_uri =[%s]\n", cn, r->unparsed_uri );
  1358. mod_gzip_printf( "%s: *IN: r->filename =[%s]\n", cn, r->filename );
  1359. mod_gzip_printf( "%s: *IN: r->path_info =[%s]\n", cn, r->path_info );
  1360. mod_gzip_printf( "%s: *IN: r->args =[%s]\n", cn, r->args );
  1361. mod_gzip_printf( "%s: *IN: r->header_only =[%s]\n", cn, r->header_only );
  1362. mod_gzip_printf( "%s: *IN: r->protocol =[%s]\n", cn, r->protocol );
  1363. mod_gzip_printf( "%s: *IN: r->proto_num =%d\n", cn, r->proto_num );
  1364. mod_gzip_printf( "%s: *IN: r->hostname =[%s]\n", cn, r->hostname );
  1365. mod_gzip_printf( "%s: *IN: r->the_request =[%s]\n", cn, r->the_request );
  1366. mod_gzip_printf( "%s: *IN: r->assbackwards =%d\n", cn, r->assbackwards );
  1367. mod_gzip_printf( "%s: *IN: r->status_line =[%s]\n", cn, r->status_line );
  1368. mod_gzip_printf( "%s: *IN: r->status =%d\n", cn, r->status );
  1369. mod_gzip_printf( "%s: *IN: r->method =[%s]\n", cn, r->method );
  1370. mod_gzip_printf( "%s: *IN: r->method_number =%d\n", cn, r->method_number );
  1371. mod_gzip_printf( "%s: *IN: r->content_type =[%s]\n", cn, r->content_type );
  1372. mod_gzip_printf( "%s: *IN: r->handler =[%s]\n", cn, r->handler );
  1373. mod_gzip_printf( "%s: *IN: r->content_encoding =[%s]\n", cn, r->content_encoding );
  1374. mod_gzip_printf( "%s: *IN: r->content_language =[%s]\n", cn, r->content_language );
  1375. mod_gzip_printf( "%s: -------------------------------------------------------------\n",cn);
  1376. mod_gzip_printf( "%s: *IN: r->parsed_uri.scheme =[%s]\n", cn, r->parsed_uri.scheme );
  1377. mod_gzip_printf( "%s: *IN: r->parsed_uri.hostinfo =[%s]\n", cn, r->parsed_uri.hostinfo );
  1378. mod_gzip_printf( "%s: *IN: r->parsed_uri.user =[%s]\n", cn, r->parsed_uri.user );
  1379. mod_gzip_printf( "%s: *IN: r->parsed_uri.password =[%s]\n", cn, r->parsed_uri.password );
  1380. mod_gzip_printf( "%s: *IN: r->parsed_uri.hostname =[%s]\n", cn, r->parsed_uri.hostname );
  1381. mod_gzip_printf( "%s: *IN: r->parsed_uri.port_str =[%s]\n", cn, r->parsed_uri.port_str );
  1382. mod_gzip_printf( "%s: *IN: r->parsed_uri.port =%u\n", cn, r->parsed_uri.port );
  1383. mod_gzip_printf( "%s: *IN: r->parsed_uri.path =[%s]\n", cn, r->parsed_uri.path );
  1384. mod_gzip_printf( "%s: *IN: r->parsed_uri.query =[%s]\n", cn, r->parsed_uri.query );
  1385. mod_gzip_printf( "%s: *IN: r->parsed_uri.fragment =[%s]\n", cn, r->parsed_uri.fragment );
  1386. mod_gzip_printf( "%s: -------------------------------------------------------------\n",cn);
  1387. #endif /* MOD_GZIP_DEBUG1 */
  1388. /*
  1389. * Call the real transaction handler....
  1390. */
  1391. #ifdef MOD_GZIP_DEBUG1
  1392. mod_gzip_printf( "%s: Call mod_gzip_request_handler()...\n", cn );
  1393. #endif
  1394. rc = mod_gzip_request_handler( (request_rec *) r );
  1395. #ifdef MOD_GZIP_DEBUG1
  1396. mod_gzip_printf( "%s: Back mod_gzip_request_handler()... rc=%d\n",cn,rc);
  1397. #endif
  1398. if ( r->server->loglevel == APLOG_DEBUG )
  1399. {
  1400. /*
  1401. * If LogLevel is 'debug' then show the final return code
  1402. * value in the log(s)...
  1403. */
  1404. if ( rc == OK )
  1405. {
  1406. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  1407. "%s: Exit: return( rc = %d = OK )", cn, rc );
  1408. }
  1409. else if ( rc == DECLINED )
  1410. {
  1411. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  1412. "%s: Exit: return( rc = %d = DECLINED )", cn, rc );
  1413. }
  1414. else /* It's probably an HTTP error code... */
  1415. {
  1416. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  1417. "%s: Exit: return( rc = %d = HTTP ERROR CODE? )", cn, rc );
  1418. }
  1419. }/* End 'if( r->server->loglevel == APLOG_DEBUG )' */
  1420. #ifdef MOD_GZIP_DEBUG1
  1421. if ( rc == OK )
  1422. {
  1423. mod_gzip_printf( "%s: rc = %d OK\n", cn, (int) rc);
  1424. }
  1425. else if ( rc == DECLINED )
  1426. {
  1427. mod_gzip_printf( "%s: rc = %d DECLINED\n", cn, (int) rc );
  1428. }
  1429. else /* It's probably an HTTP error code... */
  1430. {
  1431. mod_gzip_printf( "%s: rc = %d ( HTTP ERROR CODE? )\n", cn, (int) rc );
  1432. }
  1433. mod_gzip_printf( "%s: Exit > return( rc = %d ) >\n",cn,rc );
  1434. #endif /* MOD_GZIP_DEBUG1 */
  1435. return rc;
  1436. }/* End of mod_gzip_handler() */
  1437. typedef struct {
  1438. table *action_types; /* Added with Action... */
  1439. char *scripted[METHODS]; /* Added with Script... */
  1440. array_header *xmethods; /* Added with Script -- extension methods */
  1441. } action_dir_config2;
  1442. extern module action_module;
  1443. int mod_gzip_request_handler( request_rec *r )
  1444. {
  1445. /*
  1446. * Process a new request...
  1447. */
  1448. int rc = 0;
  1449. int loglevel = 0;
  1450. int do_command = 0;
  1451. int process = 0;
  1452. int action_flag = 0;
  1453. long compression_ratio = 0;
  1454. const char* has_encoding = 0;
  1455. const char* accept_encoding = 0;
  1456. #ifdef MOD_GZIP_ALLOWS_INTERNAL_COMMANDS
  1457. char tmp[4096]; /* Scratch buffer for HTML output */
  1458. #endif
  1459. #ifdef MOD_GZIP_DEBUG1
  1460. char cn[]="mod_gzip_request_handler()";
  1461. const char* the_type = 0;
  1462. #endif
  1463. #ifdef MOD_GZIP_USES_APACHE_LOGS
  1464. char log_info[40]; /* Scratch buffer */
  1465. #endif
  1466. void *modconf = r->server->module_config;
  1467. mod_gzip_conf *conf = 0; /* Pointer to our own config data */
  1468. /*
  1469. * Start...
  1470. *
  1471. * Establish a local pointer to module configuration data...
  1472. */
  1473. conf = (mod_gzip_conf *)
  1474. ap_get_module_config(modconf, &gzip_module);
  1475. /*
  1476. * Get the current Apache log level...
  1477. */
  1478. loglevel = r->server->loglevel;
  1479. #ifdef MOD_GZIP_USES_APACHE_LOGS
  1480. /*
  1481. * If the MOD_GZIP_USES_APACHE_LOGS compile-time switch is ON
  1482. * then the Apache log module interface code is being included.
  1483. *
  1484. * Reset the module 'notes' that are used by mod_gzip to
  1485. * add entries to Apache standard log files...
  1486. *
  1487. * See the note farther below about how to add mod_gzip
  1488. * compression information to any standard Apache log file.
  1489. */
  1490. /* Default for 'mod_result' message is 'DECLINED:NOP'... */
  1491. ap_table_setn( r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:NOP"));
  1492. /* Default for in/out size is 'n/a'... 'Not available'...*/
  1493. sprintf( log_info, "n/a" );
  1494. ap_table_setn( r->notes,"mod_gzip_input_size",ap_pstrdup(r->pool,log_info));
  1495. ap_table_setn( r->notes,"mod_gzip_output_size",ap_pstrdup(r->pool,log_info));
  1496. /* Default for compression ratio is '0' percent... */
  1497. ap_table_setn( r->notes,"mod_gzip_compression_ratio",ap_pstrdup(r->pool,"0"));
  1498. #endif /* MOD_GZIP_USES_APACHE_LOGS */
  1499. #ifdef MOD_GZIP_DEBUG1
  1500. /* Request info... */
  1501. mod_gzip_printf( "%s: Entry...\n",cn);
  1502. mod_gzip_printf( "%s: mod_gzip_version =[%s]\n", cn, mod_gzip_version);
  1503. mod_gzip_printf( "%s: conf->req = %d\n", cn, (int) conf->req);
  1504. mod_gzip_printf( "%s: conf->cache.root =[%s]\n", cn, conf->cache.root);
  1505. mod_gzip_printf( "%s: *IN: r->uri =[%s]\n", cn, r->uri);
  1506. mod_gzip_printf( "%s: *IN: r->unparsed_uri=[%s]\n", cn, r->unparsed_uri);
  1507. mod_gzip_printf( "%s: *IN: r->filename =[%s]\n", cn, r->filename);
  1508. mod_gzip_printf( "%s: *IN: r->handler =[%s]\n", cn, r->handler);
  1509. mod_gzip_printf( "%s: r->finfo.st_size = %ld\n", cn, (long) r->finfo.st_size);
  1510. /* NOTE: The r->headers_out content type value has not normally */
  1511. /* been set at this point but grab a pointer to it and show */
  1512. /* it just to make sure. The r->content_type value, however, */
  1513. /* normally WILL have some value at this point. */
  1514. the_type = ap_table_get( r->headers_out,"Content-type" );
  1515. mod_gzip_printf( "%s: r->headers_out, Content-type = [%s]\n",cn,the_type);
  1516. mod_gzip_printf( "%s: r->content_type = [%s]\n",cn,r->content_type );
  1517. /* The r->handler ASCII name string is the all-important */
  1518. /* jump table name for the module that will handle the */
  1519. /* transaction. If this is a CGI jump then it will normally */
  1520. /* have a value of 'cgi-script' at this point. */
  1521. mod_gzip_printf( "%s: r->handler = [%s]\n",cn,r->handler );
  1522. /* Server info... */
  1523. mod_gzip_printf( "%s: r->server->path = [%s]\n",cn,r->server->path );
  1524. mod_gzip_printf( "%s: r->server->pathlen = %d\n", cn,r->server->pathlen);
  1525. mod_gzip_printf( "%s: r->server->server_admin = [%s]\n",cn,r->server->server_admin);
  1526. mod_gzip_printf( "%s: r->server->server_hostname = [%s]\n",cn,r->server->server_hostname);
  1527. mod_gzip_printf( "%s: r->server->error_fname = [%s]\n",cn,r->server->error_fname);
  1528. /* Environment info... */
  1529. mod_gzip_printf( "%s: DOCUMENT_ROOT = [%s]\n",cn,ap_document_root(r));
  1530. #endif /* MOD_GZIP_DEBUG1 */
  1531. /*
  1532. * Check the 'master' request control switch and see if mod_gzip
  1533. * is ON (ENABLED) or OFF (DISABLED)...
  1534. */
  1535. if ( conf->req != 1 )
  1536. {
  1537. /* mod_gzip is currently DISABLED so DECLINE the processing... */
  1538. #ifdef MOD_GZIP_DEBUG1
  1539. mod_gzip_printf( "%s: conf->req = %d = OFF\n",cn,conf->req);
  1540. mod_gzip_printf( "%s: The module is currently DISABLED\n",cn);
  1541. mod_gzip_printf( "%s: Exit > return( DECLINED ) >\n",cn);
  1542. #endif
  1543. #ifdef MOD_GZIP_USES_APACHE_LOGS
  1544. /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */
  1545. ap_table_setn(
  1546. r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:DISABLED"));
  1547. #endif /* MOD_GZIP_USES_APACHE_LOGS */
  1548. return DECLINED;
  1549. }/* End 'if( conf->req != 1 )' */
  1550. /*
  1551. * Check for a default HTTP support level ( if used ).
  1552. * If no value for conf->min_http was supplied in the
  1553. * httpd.conf file then the default value will be 0
  1554. * so that ALL levels of HTTP will be OK...
  1555. */
  1556. #ifdef MOD_GZIP_DEBUG1
  1557. mod_gzip_printf( "%s: *HTTP CHECK:conf->min_http = %d\n", cn, conf->min_http );
  1558. mod_gzip_printf( "%s: *HTTP CHECK:r->proto_num = %d\n", cn, r->proto_num );
  1559. mod_gzip_printf( "%s: *HTTP CHECK:r->protocol = [%s]\n", cn, r->protocol );
  1560. #endif
  1561. if ( r->proto_num < conf->min_http )
  1562. {
  1563. /* The HTTPx/x version number does not meet the minimum requirement */
  1564. #ifdef MOD_GZIP_DEBUG1
  1565. mod_gzip_printf( "%s: Request HTTP level does not meet minimum requirement\n",cn);
  1566. mod_gzip_printf( "%s: Exit > return( DECLINED ) >\n",cn);
  1567. #endif
  1568. #ifdef MOD_GZIP_USES_APACHE_LOGS
  1569. /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */
  1570. sprintf( log_info, "DECLINED:%s:%d", r->protocol, r->proto_num );
  1571. ap_table_setn(
  1572. r->notes,"mod_gzip_result",ap_pstrdup(r->pool,log_info));
  1573. #endif /* MOD_GZIP_USES_APACHE_LOGS */
  1574. return DECLINED;
  1575. }/* End 'if ( r->proto_num < conf->min_http )' */
  1576. else /* Protocol level is OK... */
  1577. {
  1578. #ifdef MOD_GZIP_DEBUG1
  1579. mod_gzip_printf( "%s: Request HTTP level is OK...\n",cn);
  1580. #endif
  1581. }
  1582. #ifdef MOD_GZIP_ALLOWS_INTERNAL_COMMANDS
  1583. /*
  1584. * Internal command pickups...
  1585. *
  1586. * If this module was compiled with the
  1587. * MOD_GZIP_ALLOWS_INTERNAL_COMMANDS switch ON
  1588. * then the first thing we do is check for valid
  1589. * URL-based internal commands.
  1590. *
  1591. * Rather than check for all possible commands each time
  1592. * just do 1 quick check for the command prefix and set
  1593. * a flag to indicate if there is any need to enter the
  1594. * actual command handler...
  1595. */
  1596. if ( strstr( r->filename, "mod_gzip_command_" ) )
  1597. {
  1598. do_command = 1; /* Process the command */
  1599. }
  1600. #ifdef MOD_GZIP_DEBUG1
  1601. mod_gzip_printf( "%s: do_command = %d\n",cn,do_command);
  1602. #endif
  1603. if ( do_command )
  1604. {
  1605. /* Determine the exact command and respond... */
  1606. if ( strstr( r->filename, "mod_gzip_command_version" ) )
  1607. {
  1608. /*------------------------------------------------------*/
  1609. /* Command: 'mod_gzip_command_version' */
  1610. /* Purpose: Return the current mod_gzip version number. */
  1611. /* Comment: Allows anyone to query any Apache Server at */
  1612. /* any URL with a browser and discover if */
  1613. /* mod_gzip is in use at that site. */
  1614. /*------------------------------------------------------*/
  1615. #ifdef MOD_GZIP_DEBUG1
  1616. mod_gzip_printf( "%s: 'mod_gzip_command_version' seen...\n",cn);
  1617. #endif
  1618. /* NOTE: mod_gzip command results are not sent compressed */
  1619. /* Build the response buffer... */
  1620. sprintf( tmp,
  1621. "<html><body><pre>"
  1622. "mod_gzip is available on this Server\r\n"
  1623. "mod_gzip version = %s\r\n"
  1624. "</pre></body></html>",
  1625. mod_gzip_version
  1626. );
  1627. /* For all mod_gzip commands that are intercepted we */
  1628. /* simply return OK. */
  1629. return( mod_gzip_send_html_command_response( r, tmp, "text/html" ));
  1630. }
  1631. else if ( strstr( r->filename, "mod_gzip_command_showstats" ) )
  1632. {
  1633. /*------------------------------------------------------*/
  1634. /* Command: 'mod_gzip_command_showstats' */
  1635. /* Purpose: Display compression statistics. */
  1636. /* Comment: Allows anyone to query any Apache Server at */
  1637. /* any URL with a browser and get a report */
  1638. /* about compression results. */
  1639. /*------------------------------------------------------*/
  1640. #ifdef MOD_GZIP_DEBUG1
  1641. mod_gzip_printf( "%s: 'mod_gzip_command_showstats' seen...\n",cn);
  1642. #endif
  1643. /* NOTE: mod_gzip command results are not sent compressed */
  1644. /* Build the response buffer... */
  1645. /* NOTE: This command has been temporarily removed */
  1646. sprintf( tmp,
  1647. "<html><body><pre>"
  1648. "mod_gzip is available on this Server\r\n"
  1649. "mod_gzip version = %s\r\n\r\n"
  1650. "The 'mod_gzip_command_showstats' command has been temporarily removed.\r\n"
  1651. "</pre></body></html>",
  1652. mod_gzip_version
  1653. );
  1654. /* For all mod_gzip commands that are intercepted we */
  1655. /* simply return OK. */
  1656. return( mod_gzip_send_html_command_response( r, tmp, "text/html" ));
  1657. }
  1658. else if ( strstr( r->filename, "mod_gzip_command_resetstats" ) )
  1659. {
  1660. /*------------------------------------------------------*/
  1661. /* Command: 'mod_gzip_command_resetstats' */
  1662. /* Purpose: Resets the compression statistics. */
  1663. /* Comment: Allows the compression statistics to be */
  1664. /* reset using only a browser. */
  1665. /*------------------------------------------------------*/
  1666. #ifdef MOD_GZIP_DEBUG1
  1667. mod_gzip_printf( "%s: 'mod_gzip_command_resetstats' seen...\n",cn);
  1668. #endif
  1669. /* NOTE: mod_gzip command results are not sent compressed */
  1670. /* Build the response buffer... */
  1671. /* NOTE: This command has been temporarily removed */
  1672. sprintf( tmp,
  1673. "<html><body><pre>"
  1674. "mod_gzip is available on this Server\r\n"
  1675. "mod_gzip version = %s\r\n\r\n"
  1676. "The 'mod_gzip_command_resetstats' command has been temporarily removed.\r\n"
  1677. "</pre></body></html>",
  1678. mod_gzip_version
  1679. );
  1680. /* For all mod_gzip commands that are intercepted we */
  1681. /* simply return OK. */
  1682. return( mod_gzip_send_html_command_response( r, tmp, "text/html" ));
  1683. }
  1684. else /* Unrecognized command... */
  1685. {
  1686. /* The command prefix was 'seen' and the 'do_command' flag */
  1687. /* was TRUE but either the command was mis-typed or there */
  1688. /* is no such command available. This is not an ERROR and */
  1689. /* we should simply fall-through and assume that the URL */
  1690. /* is valid for the local Server. A 404 will be returned */
  1691. /* if there is no object that actually matches the name. */
  1692. }
  1693. }/* End 'if( do_command )' */
  1694. #endif /* MOD_GZIP_ALLOWS_INTERNAL_COMMANDS */
  1695. /*
  1696. * Sanity checks...
  1697. */
  1698. /*
  1699. * If the requested file already contains the .gz designation
  1700. * then we must assume it is pre-compressed and let the
  1701. * default logic take care of sending the file. This module
  1702. * doesn't really care if a .gz file was actually requested
  1703. * or if it is the source target because of a successful
  1704. * Server side 'negotiation'. Doesn't matter.
  1705. */
  1706. if ( ( r->filename ) && ( strstr( r->filename, ".gz" ) ) )
  1707. {
  1708. #ifdef MOD_GZIP_DEBUG1
  1709. mod_gzip_printf( "%s: r->filename already contains '.gz'.\n",cn);
  1710. mod_gzip_printf( "%s: Pre-compression is assumed.\n",cn);
  1711. mod_gzip_printf( "%s: Exit > return( DECLINED ) >\n",cn);
  1712. #endif
  1713. #ifdef MOD_GZIP_USES_APACHE_LOGS
  1714. /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */
  1715. ap_table_setn(
  1716. r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:HAS.GZ"));
  1717. if ( r->server->loglevel == APLOG_DEBUG )
  1718. {
  1719. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  1720. "mod_gzip: Files with .gz file extension are skipped.");
  1721. }
  1722. #endif /* MOD_GZIP_USES_APACHE_LOGS */
  1723. return DECLINED;
  1724. }
  1725. else /* r->filename doesn not contain '.gz' designator... */
  1726. {
  1727. #ifdef MOD_GZIP_DEBUG1
  1728. mod_gzip_printf( "%s: r->filename does NOT contain '.gz'.\n",cn);
  1729. mod_gzip_printf( "%s: Assuming OK to proceed...\n",cn);
  1730. #endif
  1731. }
  1732. /*
  1733. * For now just block all attempts to compress 'image/*' MIME
  1734. * type even if user is trying to do so. Too many issues with
  1735. * broken browsers when it comes to decoding compressed images.
  1736. *
  1737. * WARNING: Don't submit r->content_type to strstr() it if is
  1738. * NULL or the API call will GP fault. Go figure.
  1739. */
  1740. if ( ( r->content_type ) && ( strstr( r->content_type, "image/" ) ) )
  1741. {
  1742. #ifdef MOD_GZIP_DEBUG1
  1743. mod_gzip_printf( "%s: r->content_type contains 'image/'.\n",cn);
  1744. mod_gzip_printf( "%s: Image compression is temporaily BLOCKED\n",cn);
  1745. mod_gzip_printf( "%s: Exit > return( DECLINED ) >\n",cn);
  1746. #endif
  1747. #ifdef MOD_GZIP_USES_APACHE_LOGS
  1748. /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */
  1749. ap_table_setn(
  1750. r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:IMAGE"));
  1751. if ( r->server->loglevel == APLOG_DEBUG )
  1752. {
  1753. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  1754. "mod_gzip: Graphics image compression option is temporarily disabled.");
  1755. }
  1756. #endif /* MOD_GZIP_USES_APACHE_LOGS */
  1757. return DECLINED;
  1758. }
  1759. /*
  1760. * Safeguard against situations where some other module or
  1761. * filter has gotten to this request BEFORE us and has already
  1762. * added the 'Content-encoding: gzip' field to the output header.
  1763. * It must be assumed that whoever added the header prior to this
  1764. * point also took care of the compression itself.
  1765. *
  1766. * If the output header already contains "Content-encoding: gzip"
  1767. * then simply DECLINE the processing and let the default chain
  1768. * take care of it...
  1769. */
  1770. has_encoding = ap_table_get( r->headers_out, "Content-encoding" );
  1771. #ifdef MOD_GZIP_DEBUG1
  1772. mod_gzip_printf( "%s: has_encoding = [%s]\n",cn,has_encoding);
  1773. #endif
  1774. if ( has_encoding ) /* 'Content-encoding' field is present... */
  1775. {
  1776. #ifdef MOD_GZIP_DEBUG1
  1777. mod_gzip_printf( "%s: Output header already contains 'Content-encoding:' field\n",cn);
  1778. mod_gzip_printf( "%s: Checking for 'gzip' designator...\n",cn);
  1779. #endif
  1780. if ( strstr( has_encoding, "gzip" ) ||
  1781. strstr( has_encoding, "deflate" ) )
  1782. {
  1783. #ifdef MOD_GZIP_DEBUG1
  1784. mod_gzip_printf( "%s: 'Content-encoding:' field contains 'gzip' or 'deflate' designator...\n",cn);
  1785. mod_gzip_printf( "%s: Pre-compression is assumed.\n",cn);
  1786. mod_gzip_printf( "%s: Exit > return( DECLINED ) >\n",cn);
  1787. #endif
  1788. #ifdef MOD_GZIP_USES_APACHE_LOGS
  1789. /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */
  1790. ap_table_setn(
  1791. r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:HAS_CE:GZIP"));
  1792. if ( r->server->loglevel == APLOG_DEBUG )
  1793. {
  1794. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  1795. "mod_gzip: Header already has 'Content-encoding: gzip'");
  1796. }
  1797. #endif /* MOD_GZIP_USES_APACHE_LOGS */
  1798. return DECLINED;
  1799. }
  1800. else /* 'gzip' designator not found... */
  1801. {
  1802. #ifdef MOD_GZIP_DEBUG1
  1803. mod_gzip_printf( "%s: 'Content-encoding:' field does NOT contain 'gzip' or 'deflate' designator...\n",cn);
  1804. mod_gzip_printf( "%s: Assuming OK to proceed...\n",cn);
  1805. #endif
  1806. }
  1807. }/* End 'if( has_encoding )' */
  1808. else /* Output header does NOT contain 'Content-encoding:' field... */
  1809. {
  1810. #ifdef MOD_GZIP_DEBUG1
  1811. mod_gzip_printf( "%s: Output header does NOT contain 'Content-encoding:' field.\n",cn);
  1812. mod_gzip_printf( "%s: Assuming OK to proceed...\n",cn);
  1813. #endif
  1814. }
  1815. /*
  1816. * Basic sanity checks completed and we are still here.
  1817. *
  1818. * Now we must determine if the User-Agent is capable of receiving
  1819. * compressed data...
  1820. *
  1821. * There are, currently, many reasons why it is actually never
  1822. * enough to simply trust the 'Accept-encoding: foo, bar'
  1823. * request header field when it comes to actually determining
  1824. * if a User-agent is capable of receiving content or transfer
  1825. * encodings.
  1826. *
  1827. * Some of them are...
  1828. *
  1829. * 1. There have been several major releases of popular browsers
  1830. * that actually send the 'Accept-encoding:' request field but
  1831. * are, in reality, unable to perform the specified decoding(s).
  1832. * In some cases the result will be that the browser screen
  1833. * simply fills with garbage ( the binary compressed data
  1834. * itself ) but in some cases the browser will actually crash.
  1835. *
  1836. * 2. There have been other major releases of browsers that are
  1837. * specifying multiple 'Accept-encoding' techniques with no
  1838. * 'Q' values whatsoever and they are actually only able to
  1839. * handle one of the multiple types specified. There is no
  1840. * way to know which type is 'real' other than by using other
  1841. * empiricial data extracted from the 'User-agent' field
  1842. * or other inbound request headers.
  1843. *
  1844. * 3. Same as 1 and 2 but relates to SIZE. Some major browser
  1845. * releases can handle the encoded content but only up to
  1846. * a certain 'SIZE' limit and then they will fail. There
  1847. * is no way for a User-agent to specify this limitation
  1848. * via HTTP so empirical header analysis is the only option.
  1849. *
  1850. * 4. The HTTP specification has no way for a Server to distinguish
  1851. * from the 'Accept encoding: foo, bar' input request field
  1852. * whether the user agent can only support the specified encodings
  1853. * as either a Content-encoding OR a Transfer-encoding, but
  1854. * not both. There is also no way of knowing if the user
  1855. * agent is able to handle any of the specified types being
  1856. * used as both a Content-encoding AND a Transfer-encoding
  1857. * for the same message body. All the Server can do is assume
  1858. * that the encodings are valid in any/all combinations
  1859. * and that the user agent can 'Accept' them as either
  1860. * 'Content' encodings and/or 'Transfer' encodings under
  1861. * any and all circumstances. This blanket assumption will
  1862. * cause problems with some release versions of some browsers
  1863. * because the assumed 'do all' capability is simply not a
  1864. * reality.
  1865. *
  1866. * 5. Many browsers ( such as Netscape 4.75 for UNIX ) are unable
  1867. * to handle Content-encoding only for specific kinds of HTML
  1868. * transactions such as Style Sheets even though the browser
  1869. * says it is HTTP 1.1 compliant and is suppying the standard
  1870. * 'Accept-encoding: gzip' field. According to the IETF
  1871. * specifications any user-agent that says it can accept
  1872. * encodings should be able to do so for all types of HTML
  1873. * transactions but this is simply not the current reality.
  1874. * Some will, some won't... even if they say they can.
  1875. *
  1876. * This version of this module takes the 'What, me worry' approach
  1877. * and simply uses the accepted method of relying solely on the
  1878. * 'Accept-encoding: foo, bar' field and also assumes this means
  1879. * that the User-agent can accept the specified encodings as
  1880. * either Content-encodings (CE) and/or Transfer-encodings (TE)
  1881. * under all circumstances and in any combinations that the
  1882. * Server decides to send.
  1883. *
  1884. * It also assumes that the caller has no preference and should
  1885. * be able to decode any of the specified encodings equally well.
  1886. * Most user-agents sending the 'Accept-encoding:' field do NOT
  1887. * supply any 'Q' values to help with determining preferences.
  1888. */
  1889. accept_encoding = ap_table_get( r->headers_in, "Accept-Encoding" );
  1890. #ifdef MOD_GZIP_DEBUG1
  1891. if ( accept_encoding )
  1892. {
  1893. mod_gzip_printf( "%s: 'Accept Encoding:' field seen.\n",cn);
  1894. }
  1895. else
  1896. {
  1897. mod_gzip_printf( "%s: 'Accept Encoding' field NOT seen.\n",cn);
  1898. }
  1899. #endif /* MOD_GZIP_DEBUG1 */
  1900. /* If Accept-Encoding is applicable to this request...*/
  1901. if ( accept_encoding )
  1902. {
  1903. /* ...and if it has the right 'gzip' indicator... */
  1904. /* We record the compression format in a request note, so we
  1905. * can get it again later, and so it can potentially be logged.
  1906. */
  1907. if ( strstr( accept_encoding, "gzip" ) )
  1908. {
  1909. process = 1; /* ...set the 'process' flag TRUE */
  1910. ap_table_setn( r->notes,"mod_gzip_compression_format",
  1911. ap_pstrdup(r->pool,"gzip"));
  1912. }
  1913. else if ( strstr( accept_encoding, "deflate" ) )
  1914. {
  1915. process = 1; /* ...set the 'process' flag TRUE */
  1916. ap_table_setn( r->notes,"mod_gzip_compression_format",
  1917. ap_pstrdup(r->pool,"deflate"));
  1918. }
  1919. }/* End 'if( accept_encoding )' */
  1920. #ifdef MOD_GZIP_DEBUG1
  1921. mod_gzip_printf( "%s: 'process' flag = %d\n",cn,process);
  1922. #endif
  1923. if ( !process ) /* Request does not meet criteria for processing... */
  1924. {
  1925. #ifdef MOD_GZIP_DEBUG1
  1926. mod_gzip_printf( "%s: No 'gzip' capability specified by user-agent.\n",cn);
  1927. mod_gzip_printf( "%s: 'process' flag is FALSE.\n",cn);
  1928. mod_gzip_printf( "%s: This request will not be processed.\n",cn);
  1929. mod_gzip_printf( "%s: Exit > return( DECLINED ) >\n",cn);
  1930. #endif
  1931. #ifdef MOD_GZIP_USES_APACHE_LOGS
  1932. /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */
  1933. ap_table_setn(
  1934. r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:NO_GZIP"));
  1935. if ( r->server->loglevel == APLOG_DEBUG )
  1936. {
  1937. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  1938. "mod_gzip: The inbound request header does not have 'Accept-encoding: gzip'");
  1939. }
  1940. #endif /* MOD_GZIP_USES_APACHE_LOGS */
  1941. return DECLINED;
  1942. }
  1943. else /* 'gzip' designator was seen in 'Accept-Encoding:' field */
  1944. {
  1945. #ifdef MOD_GZIP_DEBUG1
  1946. mod_gzip_printf( "%s: 'gzip' or 'deflate' capability specified by user-agent.\n",cn);
  1947. mod_gzip_printf( "%s: Assuming OK to proceed...\n",cn);
  1948. #endif
  1949. }
  1950. /*
  1951. * Handle the transaction...
  1952. *
  1953. * At this point the inbound header analysis has been completed
  1954. * and we are assuming that the user agent is capable of accepting
  1955. * the content encodings we can provide.
  1956. *
  1957. * We must now 'do the right thing' based on what type of
  1958. * request it actually is...
  1959. */
  1960. #ifdef MOD_GZIP_DEBUG1
  1961. mod_gzip_printf( "%s: r->handler = [%s]\n",cn,r->handler);
  1962. mod_gzip_printf( "%s: r->content_type = [%s]\n",cn,r->content_type);
  1963. mod_gzip_printf( "%s: Call mod_gzip_get_action_flag()...\n",cn);
  1964. #endif
  1965. action_flag =
  1966. mod_gzip_get_action_flag(
  1967. (request_rec *) r,
  1968. (mod_gzip_conf *) conf
  1969. );
  1970. #ifdef MOD_GZIP_DEBUG1
  1971. mod_gzip_printf( "%s: Back mod_gzip_get_action_flag()...\n",cn);
  1972. mod_gzip_printf( "%s: action_flag = %d\n",cn,action_flag);
  1973. mod_gzip_printf( "%s: conf->do_static_files = %d\n",cn,(int)conf->do_static_files);
  1974. mod_gzip_printf( "%s: conf->do_cgi = %d\n",cn,(int)conf->do_cgi);
  1975. #endif
  1976. /*
  1977. * Perform the right 'action' for this transaction...
  1978. */
  1979. if ( action_flag == MOD_GZIP_IMAP_DECLINED1 )
  1980. {
  1981. /*
  1982. * If the transaction is to be DECLINED then just set the final
  1983. * return code to DECLINED, fall through, and return.
  1984. */
  1985. #ifdef MOD_GZIP_DEBUG1
  1986. mod_gzip_printf( "%s: action_flag = MOD_GZIP_IMAP_DECLINED1\n",cn);
  1987. #endif
  1988. if ( r->server->loglevel == APLOG_DEBUG )
  1989. {
  1990. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  1991. "mod_gzip: action_flag = MOD_GZIP_IMAP_DECLINED1 ");
  1992. }
  1993. rc = DECLINED;
  1994. }
  1995. else if ( action_flag == MOD_GZIP_IMAP_DYNAMIC1 )
  1996. {
  1997. #ifdef MOD_GZIP_DEBUG1
  1998. mod_gzip_printf( "%s: action_flag = MOD_GZIP_IMAP_DYNAMIC1\n",cn);
  1999. #endif
  2000. if ( r->server->loglevel == APLOG_DEBUG )
  2001. {
  2002. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  2003. "mod_gzip: action_flag = MOD_GZIP_IMAP_DYNAMIC1 ");
  2004. }
  2005. /*
  2006. * Check the flag that can control whether or not the
  2007. * CGI dynamic output handler is ever called...
  2008. */
  2009. if ( conf->do_cgi != 1 ) /* CGI handler is OFF for now... */
  2010. {
  2011. if ( r->server->loglevel == APLOG_DEBUG )
  2012. {
  2013. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  2014. "mod_gzip: Calls to CGI handler currently DISABLED ");
  2015. }
  2016. #ifdef MOD_GZIP_USES_APACHE_LOGS
  2017. /* Update the result string for Apache log(s)... */
  2018. ap_table_setn(
  2019. r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:CGI_OFF"));
  2020. #endif
  2021. rc = DECLINED; /* Just set final return code and fall through */
  2022. }/* End 'if( conf->do_cgi == 0 )' */
  2023. else /* It's OK to call the handler... */
  2024. {
  2025. if ( r->server->loglevel == APLOG_DEBUG )
  2026. {
  2027. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  2028. "mod_gzip: Calling cgi_handler for r->uri=[%s]",r->uri);
  2029. }
  2030. /* Take care of some business BEFORE calling the */
  2031. /* dynamic handler... */
  2032. mod_gzip_prepare_for_dynamic_call( r );
  2033. /* PHP NOTE */
  2034. /* r->path_info must be set before ap_add_cgi_vars() */
  2035. /* is called from within the upcoming hander or we */
  2036. /* won't get PATH_INFO or PATH_TRANSLATED environment */
  2037. /* variables set and PHP.EXE will return 'No input file' */
  2038. /* error message since it depends on both of these being */
  2039. /* set. r->path_info must be set to r->uri */
  2040. #ifdef MOD_GZIP_DEBUG1
  2041. mod_gzip_printf( "%s: 1 r->uri = [%s]\n", cn, r->uri );
  2042. mod_gzip_printf( "%s: 1 r->path_info = [%s]\n", cn, r->path_info );
  2043. mod_gzip_printf( "%s: Setting r->path_info to r->uri for CGI...\n", cn );
  2044. #endif
  2045. r->path_info = r->uri;
  2046. #ifdef MOD_GZIP_DEBUG1
  2047. mod_gzip_printf( "%s: 2 r->uri = [%s]\n", cn, r->uri );
  2048. mod_gzip_printf( "%s: 2 r->path_info = [%s]\n", cn, r->path_info );
  2049. #endif
  2050. /* Call the actual handler... */
  2051. #ifdef MOD_GZIP_DEBUG1
  2052. mod_gzip_printf( "%s: Call mod_gzip_cgi_handler()...\n",cn);
  2053. #endif
  2054. rc = mod_gzip_cgi_handler( (request_rec *) r );
  2055. #ifdef MOD_GZIP_DEBUG1
  2056. mod_gzip_printf( "%s: Back mod_gzip_cgi_handler()... rc=%d\n",cn,rc);
  2057. #endif
  2058. }/* End 'else' - OK to call handler */
  2059. }
  2060. else if ( action_flag == MOD_GZIP_IMAP_STATIC1 )
  2061. {
  2062. #ifdef MOD_GZIP_DEBUG1
  2063. mod_gzip_printf( "%s: action_flag = MOD_GZIP_IMAP_STATIC1\n",cn);
  2064. #endif
  2065. if ( r->server->loglevel == APLOG_DEBUG )
  2066. {
  2067. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  2068. "mod_gzip: action_flag = MOD_GZIP_IMAP_STATIC1 ");
  2069. }
  2070. /*
  2071. * Check the flag that can control whether or not the
  2072. * static handler is ever called...
  2073. */
  2074. if ( conf->do_static_files != 1 ) /* Static handler is OFF for now... */
  2075. {
  2076. if ( r->server->loglevel == APLOG_DEBUG )
  2077. {
  2078. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  2079. "mod_gzip: Calls to static handler currently DISABLED ");
  2080. }
  2081. #ifdef MOD_GZIP_USES_APACHE_LOGS
  2082. /* Update the result string for Apache log(s)... */
  2083. ap_table_setn(
  2084. r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:STATIC_OFF"));
  2085. #endif
  2086. rc = DECLINED; /* Just set final return code and fall through */
  2087. }/* End 'if( conf->do_static == 0 )' */
  2088. else /* It's OK to call the handler... */
  2089. {
  2090. if ( r->server->loglevel == APLOG_DEBUG )
  2091. {
  2092. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  2093. "mod_gzip: Calling static_handler for r->uri=[%s]",r->uri);
  2094. }
  2095. #ifdef MOD_GZIP_DEBUG1
  2096. mod_gzip_printf( "%s: Call mod_gzip_static_file_handler()...\n",cn);
  2097. #endif
  2098. rc = mod_gzip_static_file_handler( (request_rec *) r );
  2099. #ifdef MOD_GZIP_DEBUG1
  2100. mod_gzip_printf( "%s: Back mod_gzip_static_file_handler()... rc=%d\n",cn,rc);
  2101. #endif
  2102. }/* End 'else' - OK to call the handler */
  2103. }
  2104. else /* Safety catch... No pickup for the 'action' flag... */
  2105. {
  2106. if ( r->server->loglevel == APLOG_DEBUG )
  2107. {
  2108. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  2109. "mod_gzip: action_flag = MOD_GZIP_IMAP_????? Unknown value");
  2110. }
  2111. if ( r->server->loglevel == APLOG_DEBUG )
  2112. {
  2113. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  2114. "mod_gzip: No pickup for specified 'action' flag.");
  2115. }
  2116. #ifdef MOD_GZIP_DEBUG1
  2117. mod_gzip_printf( "%s: action_flag = MOD_GZIP_??? Unknown value\n",cn);
  2118. #endif
  2119. rc = DECLINED;
  2120. }
  2121. /*
  2122. * Record results to logs, if applicable, and return...
  2123. *
  2124. * The 'r->notes' values that can be used to disply result
  2125. * information in the standard Apache log files should have
  2126. * already been updated by the handler that was actually
  2127. * used to process the transaction.
  2128. */
  2129. #ifdef MOD_GZIP_DEBUG1
  2130. if ( rc == OK )
  2131. {
  2132. mod_gzip_printf( "%s: Exit > return( rc=%d OK ) >\n",cn,rc);
  2133. }
  2134. else if ( rc == DECLINED )
  2135. {
  2136. mod_gzip_printf( "%s: Exit > return( rc=%d DECLINED ) >\n",cn,rc);
  2137. }
  2138. else /* HTTP ERROR VALUE... */
  2139. {
  2140. mod_gzip_printf( "%s: Exit > return( rc=%d HTTP_ERROR ) >\n",cn,rc);
  2141. }
  2142. #endif /* MOD_GZIP_DEBUG1 */
  2143. return rc; /* Could be OK or DECLINED or HTTP_ERROR */
  2144. }/* End of mod_gzip_request_handler() */
  2145. int mod_gzip_prepare_for_dynamic_call( request_rec *r )
  2146. {
  2147. int rc;
  2148. #ifdef MOD_GZIP_DEBUG1
  2149. char cn[]="mod_gzip_prepare_for_dynamic_call()";
  2150. #endif
  2151. /*
  2152. * Start...
  2153. */
  2154. #ifdef MOD_GZIP_DEBUG1
  2155. mod_gzip_printf( "%s: Entry...\n",cn);
  2156. #endif
  2157. /*
  2158. * mod_gzip can run other modules directly...
  2159. */
  2160. /*
  2161. * First run mod_action and see it there's a SCRIPT
  2162. * for this mime type...
  2163. */
  2164. #ifdef MOD_GZIP_DEBUG1
  2165. mod_gzip_printf( "%s: 1 ***: r->uri =[%s]\n", cn, r->uri );
  2166. mod_gzip_printf( "%s: 1 ***: r->unparsed_uri=[%s]\n", cn, r->unparsed_uri );
  2167. mod_gzip_printf( "%s: 1 ***: r->filename =[%s]\n", cn, r->filename );
  2168. mod_gzip_printf( "%s: 1 ***: r->content_type=[%s]\n", cn, r->content_type );
  2169. mod_gzip_printf( "%s: 1 ***: r->handler =[%s]\n", cn, r->handler );
  2170. mod_gzip_printf( "%s: Call mod_gzip_run_mod_action(r)...\n",cn);
  2171. #endif
  2172. rc = mod_gzip_run_mod_action( (request_rec *) r );
  2173. #ifdef MOD_GZIP_DEBUG1
  2174. mod_gzip_printf( "%s: Back mod_gzip_run_mod_action(r)...\n",cn);
  2175. if ( rc == OK )
  2176. {
  2177. mod_gzip_printf( "%s: rc = %d = OK\n",cn, rc );
  2178. }
  2179. else if ( rc == DECLINED )
  2180. {
  2181. mod_gzip_printf( "%s: rc = %d = DECLINED\n",cn, rc );
  2182. }
  2183. else if ( rc == DONE ) /* -2 means 'totally done' */
  2184. {
  2185. mod_gzip_printf( "%s: rc = %d = DONE\n",cn, rc );
  2186. }
  2187. else /* Probably an HTTP ERROR value... */
  2188. {
  2189. mod_gzip_printf( "%s: rc = %d = HTTP_ERROR?\n",cn, rc );
  2190. }
  2191. mod_gzip_printf( "%s: 2 ***: r->uri =[%s]\n", cn, r->uri );
  2192. mod_gzip_printf( "%s: 2 ***: r->unparsed_uri=[%s]\n", cn, r->unparsed_uri );
  2193. mod_gzip_printf( "%s: 2 ***: r->filename =[%s]\n", cn, r->filename );
  2194. mod_gzip_printf( "%s: 2 ***: r->content_type=[%s]\n", cn, r->content_type );
  2195. mod_gzip_printf( "%s: 2 ***: r->handler =[%s]\n", cn, r->handler );
  2196. #endif /* MOD_GZIP_DEBUG1 */
  2197. /*
  2198. * Now run mod_alias and get any aliases converted
  2199. * to real pathnames...
  2200. */
  2201. #ifdef MOD_GZIP_DEBUG1
  2202. mod_gzip_printf( "%s: Call mod_gzip_run_mod_alias(r)...\n",cn);
  2203. #endif
  2204. rc = mod_gzip_run_mod_alias( (request_rec *) r );
  2205. #ifdef MOD_GZIP_DEBUG1
  2206. mod_gzip_printf( "%s: Back mod_gzip_run_mod_alias(r)...\n",cn);
  2207. if ( rc == OK )
  2208. {
  2209. mod_gzip_printf( "%s: rc = %d = OK\n",cn, rc );
  2210. }
  2211. else if ( rc == DECLINED )
  2212. {
  2213. mod_gzip_printf( "%s: rc = %d = DECLINED\n",cn, rc );
  2214. }
  2215. else if ( rc == DONE ) /* -2 means 'totally done' */
  2216. {
  2217. mod_gzip_printf( "%s: rc = %d = DONE\n",cn, rc );
  2218. }
  2219. else /* Probably an HTTP ERROR value... */
  2220. {
  2221. mod_gzip_printf( "%s: rc = %d = HTTP_ERROR?\n",cn, rc );
  2222. }
  2223. mod_gzip_printf( "%s: 3 ***: r->uri =[%s]\n", cn, r->uri );
  2224. mod_gzip_printf( "%s: 3 ***: r->unparsed_uri=[%s]\n", cn, r->unparsed_uri );
  2225. mod_gzip_printf( "%s: 3 ***: r->filename =[%s]\n", cn, r->filename );
  2226. mod_gzip_printf( "%s: 3 ***: r->content_type=[%s]\n", cn, r->content_type );
  2227. mod_gzip_printf( "%s: 3 ***: r->handler =[%s]\n", cn, r->handler );
  2228. #endif /* MOD_GZIP_DEBUG1 */
  2229. return OK;
  2230. }/* End of mod_gzip_prepare_for_dynamic_call() */
  2231. int mod_gzip_static_file_handler( request_rec *r )
  2232. {
  2233. int rc = 0;
  2234. long input_size = 0;
  2235. FILE* ifh1 = 0;
  2236. #ifdef MOD_GZIP_DEBUG1
  2237. char cn[]="mod_gzip_static_file_handler()";
  2238. #endif
  2239. /*
  2240. * Start...
  2241. */
  2242. #ifdef MOD_GZIP_DEBUG1
  2243. mod_gzip_printf( "%s: Processing file [%s]\n",cn,r->filename);
  2244. mod_gzip_printf( "%s: r->finfo.st_size = %ld\n",
  2245. cn, (long) r->finfo.st_size);
  2246. #endif
  2247. /*
  2248. * If there is a valid file size already associated with
  2249. * the request then we can assume the core stat() call succeeded
  2250. * and that r->filename actually exists. We shouldn't need
  2251. * to waste a call to 'fopen()' just to find out for ourselves
  2252. * if the file exists.
  2253. *
  2254. * If the inbound file size was '0' then we need to do some
  2255. * verifications of our own before we give up since the
  2256. * absence of size might just be a simple bug in the parent code.
  2257. */
  2258. if ( r->finfo.st_size > 0 )
  2259. {
  2260. #ifdef MOD_GZIP_DEBUG1
  2261. mod_gzip_printf( "%s: Source file length already known...\n",cn);
  2262. #endif
  2263. input_size = (long) r->finfo.st_size;
  2264. }
  2265. else /* Do our own checking... */
  2266. {
  2267. /*
  2268. * See if the requested source file exists...
  2269. * Be SURE to open the file in BINARY mode...
  2270. */
  2271. ifh1 = fopen( r->filename, "rb" );
  2272. if ( !ifh1 ) /* The file cannot be found or opened... */
  2273. {
  2274. #ifdef MOD_GZIP_DEBUG1
  2275. mod_gzip_printf( "%s: The requested source file was NOT FOUND.\n",cn);
  2276. mod_gzip_printf( "%s: Exit > return( HTTP_NOT_FOUND ) >\n",cn);
  2277. #endif
  2278. #ifdef MOD_GZIP_USES_APACHE_LOGS
  2279. /* HTTP ERROR conditions provides a short ':WHYTAG' for logs */
  2280. ap_table_setn(
  2281. r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:HTTP_NOT_FOUND"));
  2282. #endif /* MOD_GZIP_USES_APACHE_LOGS */
  2283. return HTTP_NOT_FOUND;
  2284. }
  2285. else /* The file was found and opened OK... */
  2286. {
  2287. #ifdef MOD_GZIP_DEBUG1
  2288. mod_gzip_printf( "%s: The requested source file is now OPEN...\n",cn);
  2289. #endif
  2290. }
  2291. /*
  2292. * Move the current file pointer to the end of the file...
  2293. */
  2294. if ( fseek( ifh1, 0, SEEK_END ) )
  2295. {
  2296. #ifdef MOD_GZIP_DEBUG1
  2297. mod_gzip_printf( "%s: ERROR: fseek() call failed...\n",cn);
  2298. #endif
  2299. fclose( ifh1 ); /* FILE is still open so CLOSE it... */
  2300. /* fseek() failure could be a platform issue so log the event... */
  2301. ap_log_error( APLOG_MARK,APLOG_NOERRNO|APLOG_ERR, r->server,
  2302. "mod_gzip: fseek() failed for r->filename=[%s]",r->filename );
  2303. /* Return DECLINED and let default logic finish the request... */
  2304. #ifdef MOD_GZIP_DEBUG1
  2305. mod_gzip_printf( "%s: Exit > return( DECLINED ) >\n",cn);
  2306. #endif
  2307. #ifdef MOD_GZIP_USES_APACHE_LOGS
  2308. /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */
  2309. ap_table_setn(
  2310. r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:FSEEK_FAIL"));
  2311. #endif /* MOD_GZIP_USES_APACHE_LOGS */
  2312. return DECLINED;
  2313. }
  2314. /*
  2315. * Get the current SIZE of the requested file...
  2316. */
  2317. input_size = (long) ftell( ifh1 );
  2318. if ( input_size == -1l )
  2319. {
  2320. #ifdef MOD_GZIP_DEBUG1
  2321. mod_gzip_printf( "%s: ERROR: ftell() call failed...\n",cn);
  2322. #endif
  2323. fclose( ifh1 ); /* FILE is still open so CLOSE it... */
  2324. /* ftell() failure could be a platform issue so log the event... */
  2325. ap_log_error( APLOG_MARK,APLOG_NOERRNO|APLOG_ERR, r->server,
  2326. "mod_gzip: ftell() failed for r->filename=[%s]", r->filename );
  2327. /* Return DECLINED and let default logic finish the request... */
  2328. #ifdef MOD_GZIP_DEBUG1
  2329. mod_gzip_printf( "%s: Exit > return( DECLINED ) >\n",cn);
  2330. #endif
  2331. #ifdef MOD_GZIP_USES_APACHE_LOGS
  2332. /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */
  2333. ap_table_setn(
  2334. r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:FTELL_FAIL"));
  2335. #endif /* MOD_GZIP_USES_APACHE_LOGS */
  2336. return DECLINED;
  2337. }
  2338. /*
  2339. * Once we have the length just close the file...
  2340. */
  2341. if ( fclose( ifh1 ) == EOF )
  2342. {
  2343. #ifdef MOD_GZIP_DEBUG1
  2344. mod_gzip_printf( "%s: ERROR: fclose() following ftell() call failed...\n",cn);
  2345. #endif
  2346. /* fclose() failure could be a platform issue so log the event... */
  2347. ap_log_error( APLOG_MARK,APLOG_NOERRNO|APLOG_ERR, r->server,
  2348. "mod_gzip: fclose() failed for r->filename=[%s]",r->filename );
  2349. /* Return DECLINED and let default logic finish the request... */
  2350. #ifdef MOD_GZIP_DEBUG1
  2351. mod_gzip_printf( "%s: Exit > return( DECLINED ) >\n",cn);
  2352. #endif
  2353. #ifdef MOD_GZIP_USES_APACHE_LOGS
  2354. /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */
  2355. ap_table_setn(
  2356. r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:FCLOSE_FAIL"));
  2357. #endif /* MOD_GZIP_USES_APACHE_LOGS */
  2358. return DECLINED;
  2359. }
  2360. }/* End 'else' */
  2361. /*
  2362. * We have the static filename and the length.
  2363. * That's pretty much all we need at this point so
  2364. * go ahead and encode/transmit the object...
  2365. */
  2366. #ifdef MOD_GZIP_DEBUG1
  2367. mod_gzip_printf( "%s: Call mod_gzip_encode_and_transmit()...\n",cn);
  2368. #endif
  2369. rc =
  2370. mod_gzip_encode_and_transmit(
  2371. (request_rec *) r, /* request_rec */
  2372. (char *) r->filename, /* source ( Filename or Memory buffer ) */
  2373. (int ) 1, /* 1=Source is a file 0=Memory buffer */
  2374. (long ) input_size, /* input_size */
  2375. (int ) 0 /* nodecline flag 0=Ok to DECLINE 1=No */
  2376. );
  2377. #ifdef MOD_GZIP_DEBUG1
  2378. mod_gzip_printf( "%s: Back mod_gzip_encode_and_transmit()...\n",cn);
  2379. #endif
  2380. /*
  2381. * The encode/transmit path should have already updated
  2382. * any relevant 'r->note' values ( if used ) for the transaction
  2383. * to reflect the results of the operation.
  2384. *
  2385. * Just return the result code and finish the transaction.
  2386. */
  2387. #ifdef MOD_GZIP_DEBUG1
  2388. if ( rc == OK )
  2389. {
  2390. mod_gzip_printf( "%s: Exit > return( rc = %d OK ) >\n",cn,rc);
  2391. }
  2392. else if ( rc == DECLINED )
  2393. {
  2394. mod_gzip_printf( "%s: Exit > return( rc = %d DECLINED ) >\n",cn,rc);
  2395. }
  2396. else /* HTTP ERROR */
  2397. {
  2398. mod_gzip_printf( "%s: Exit > return( rc = %d HTTP_ERROR ) >\n",cn,rc);
  2399. }
  2400. #endif /* MOD_GZIP_DEBUG1 */
  2401. return( rc );
  2402. }/* End of mod_gzip_static_file_handler() */
  2403. int mod_gzip_create_unique_filename(
  2404. mod_gzip_conf *mgc,
  2405. char *target,
  2406. int targetmaxlen
  2407. )
  2408. {
  2409. /*
  2410. * Creates a unique work file name.
  2411. */
  2412. long process_id = 0; /* Current Process ID */
  2413. long thread_id = 0; /* Current thread ID */
  2414. #ifdef MOD_GZIP_DEBUG1
  2415. char cn[]="mod_gzip_create_unique_filename()";
  2416. #endif
  2417. /* Start... */
  2418. #ifdef WIN32
  2419. process_id = (long) GetCurrentProcessId();
  2420. thread_id = (long) GetCurrentThreadId();
  2421. #else /* !WIN32 */
  2422. process_id = (long) getpid();
  2423. thread_id = (long) process_id; /* TODO: Add pthreads call */
  2424. #endif /* WIN32 */
  2425. #ifdef MOD_GZIP_DEBUG1
  2426. mod_gzip_printf( "%s: Entry...\n",cn );
  2427. mod_gzip_printf( "%s: target = %ld\n",cn,(long)target);
  2428. mod_gzip_printf( "%s: targetmaxlen = %ld\n",cn,(long)targetmaxlen);
  2429. mod_gzip_printf( "%s: process_id = %ld\n",cn,(long)process_id );
  2430. mod_gzip_printf( "%s: thread_id = %ld\n",cn,(long)thread_id );
  2431. mod_gzip_printf( "%s: mod_gzip_iusn = %ld\n",cn,(long)mod_gzip_iusn );
  2432. #endif
  2433. /*
  2434. * Sanity checks...
  2435. */
  2436. if ( ( !target ) || ( targetmaxlen == 0 ) )
  2437. {
  2438. #ifdef MOD_GZIP_DEBUG1
  2439. mod_gzip_printf( "%s: Invalid target or targetmaxlen value.\n",cn);
  2440. mod_gzip_printf( "%s: Exit > return( 1 ) > ERROR >\n",cn );
  2441. #endif
  2442. return 1;
  2443. }
  2444. /*
  2445. * Use the PROCESS + THREAD ID's and the current IUSN
  2446. * ( Instance Unique Sequence Number ) transaction ID to
  2447. * create a one-time only unique output workfile name...
  2448. */
  2449. sprintf(
  2450. target,
  2451. "%s%s_%ld_%ld_%ld.wrk",
  2452. mgc->cache.root, /* Either ServerRoot or Config specified dir. */
  2453. mod_gzip_dirsep, /* Forward slash for UNIX, backslash for WIN32 */
  2454. (long) process_id, /* Current process ID */
  2455. (long) thread_id, /* Current thread ID */
  2456. (long) mod_gzip_iusn /* Instance Unique Sequence Number */
  2457. );
  2458. mod_gzip_iusn++; /* Increment Instance Unique Sequence Number */
  2459. if ( mod_gzip_iusn > 999999999L ) mod_gzip_iusn = 1; /* Wrap */
  2460. #ifdef MOD_GZIP_DEBUG1
  2461. mod_gzip_printf( "%s: target = [%s]\n",cn,target);
  2462. mod_gzip_printf( "%s: Exit > return( 0 ) >\n",cn );
  2463. #endif
  2464. return 0;
  2465. }/* End of mod_gzip_create_unique_filename() */
  2466. #ifdef MOD_GZIP_ALLOWS_INTERNAL_COMMANDS
  2467. int mod_gzip_send_html_command_response(
  2468. request_rec *r, /* Request record */
  2469. char *tmp, /* Response to send */
  2470. char *ctype /* Content type string */
  2471. )
  2472. {
  2473. /* Generic command response transmitter... */
  2474. int tmplen=0;
  2475. char content_length[20];
  2476. #ifdef MOD_GZIP_DEBUG1
  2477. char cn[]="mod_gzip_send_html_command_response()";
  2478. #endif
  2479. /* Start... */
  2480. #ifdef MOD_GZIP_DEBUG1
  2481. mod_gzip_printf( "%s: Entry...\n",cn);
  2482. mod_gzip_printf( "%s: ctype=[%s]\n",cn,ctype);
  2483. #endif
  2484. /* Add the length of the response to the output header... */
  2485. /* The third parameter to ap_table_set() MUST be a string. */
  2486. tmplen = strlen( tmp );
  2487. sprintf( content_length, "%d", tmplen );
  2488. #ifdef MOD_GZIP_DEBUG1
  2489. mod_gzip_printf( "%s: content_length = [%s]\n",cn,content_length);
  2490. #endif
  2491. ap_table_set( r->headers_out, "Content-Length", content_length );
  2492. /* Make sure the content type matches this response... */
  2493. r->content_type = ctype; /* Actual type passed by caller */
  2494. #ifdef MOD_GZIP_DEBUG1
  2495. mod_gzip_printf( "%s: r->content_type = [%s]\n",cn,r->content_type);
  2496. #endif
  2497. /* Start a timer... */
  2498. #ifdef MOD_GZIP_DEBUG1
  2499. mod_gzip_printf( "%s: Call ap_soft_timeout()...\n",cn);
  2500. #endif
  2501. ap_soft_timeout( "mod_gzip_send_html_command", r );
  2502. #ifdef MOD_GZIP_DEBUG1
  2503. mod_gzip_printf( "%s: Back ap_soft_timeout()...\n",cn);
  2504. #endif
  2505. #ifdef MOD_GZIP_COMMANDS_USE_LAST_MODIFIED
  2506. /* Be sure to update the modifcation 'time' to current */
  2507. /* time before calling 'ap_set_last_modified()'. All that */
  2508. /* call does is set the r->xxxx value into the output */
  2509. /* header. It doesn't actually update the time itself. */
  2510. #ifdef MOD_GZIP_DEBUG1
  2511. mod_gzip_printf( "%s: Call ap_update_mtime(r,r-finfo.st_mtime)...\n",cn);
  2512. #endif
  2513. ap_update_mtime( r, r->finfo.st_mtime );
  2514. #ifdef MOD_GZIP_DEBUG1
  2515. mod_gzip_printf( "%s: Back ap_update_mtime(r,r-finfo.st_mtime)...\n",cn);
  2516. #endif
  2517. /* Update the 'Last modified' stamp in output header... */
  2518. #ifdef MOD_GZIP_DEBUG1
  2519. mod_gzip_printf( "%s: Call ap_set_last_modified()...\n",cn);
  2520. #endif
  2521. ap_set_last_modified(r);
  2522. /* TODO: Add 'no-cache' option(s) to mod_gzip command responses */
  2523. /* so user doesn't have hit reload to get fresh data. */
  2524. #ifdef MOD_GZIP_DEBUG1
  2525. mod_gzip_printf( "%s: Back ap_set_last_modified()...\n",cn);
  2526. #endif
  2527. #endif /* MOD_GZIP_COMMANDS_USE_LAST_MODIFIED */
  2528. /* Send the HTTP response header... */
  2529. #ifdef MOD_GZIP_DEBUG1
  2530. mod_gzip_printf( "%s: Call ap_send_http_header()...\n",cn);
  2531. #endif
  2532. ap_send_http_header(r);
  2533. #ifdef MOD_GZIP_DEBUG1
  2534. mod_gzip_printf( "%s: Back ap_send_http_header()...\n",cn);
  2535. #endif
  2536. /* Send the response BODY... */
  2537. #ifdef MOD_GZIP_DEBUG1
  2538. mod_gzip_printf( "%s: Sending response...\n%s\n",cn,tmp);
  2539. #endif
  2540. #ifdef MOD_GZIP_USES_AP_SEND_MMAP
  2541. /* Use ap_send_mmap() call to send the data... */
  2542. ap_send_mmap( tmp, r, 0, tmplen );
  2543. #else /* !MOD_GZIP_USES_AP_SEND_MMAP */
  2544. /* Use ap_rwrite() call to send the data... */
  2545. ap_rwrite( tmp, tmplen, r );
  2546. #endif /* MOD_GZIP_USES_AP_SEND_MMAP */
  2547. /* Clean up and exit... */
  2548. #ifdef MOD_GZIP_DEBUG1
  2549. mod_gzip_printf( "%s: Call ap_kill_timeout()...\n",cn);
  2550. #endif
  2551. ap_kill_timeout(r);
  2552. #ifdef MOD_GZIP_DEBUG1
  2553. mod_gzip_printf( "%s: Back ap_kill_timeout()...\n",cn);
  2554. mod_gzip_printf( "%s: Exit > return( OK ) >\n",cn);
  2555. #endif
  2556. return OK;
  2557. }/* End of mod_gzip_send_html_command_response() */
  2558. #endif /* MOD_GZIP_ALLOWS_INTERNAL_COMMANDS */
  2559. static void *
  2560. mod_gzip_create_config( pool *p, server_rec *s )
  2561. {
  2562. int i;
  2563. mod_gzip_conf *ps = 0;
  2564. #ifdef MOD_GZIP_DEBUG1
  2565. char cn[]="mod_gzip_create_config()";
  2566. #endif
  2567. /*
  2568. * Set all the configuration default values...
  2569. */
  2570. #ifdef MOD_GZIP_DEBUG1
  2571. mod_gzip_printf( "%s: Entry\n", cn );
  2572. #endif
  2573. /*
  2574. * Allocate a new config structure...
  2575. */
  2576. ps = ( mod_gzip_conf * ) ap_pcalloc( p, sizeof( mod_gzip_conf ) );
  2577. /*
  2578. * Set all default values...
  2579. */
  2580. ps->req = 1; /* Default is ON */
  2581. ps->req_set = 1; /* Default is ON */
  2582. ps->do_static_files = 1; /* Default is ON */
  2583. ps->do_cgi = 1; /* Default is ON */
  2584. ps->keep_workfiles = 0; /* 1=Keep workfiles 0=No */
  2585. ps->min_http = 0; /* 1001=HTTP/1.1 Default=All HTTP levels */
  2586. ps->minimum_file_size = (long) mod_gzip_minimum_file_size;
  2587. /* Minimum file size in bytes */
  2588. ps->maximum_inmem_size = (long) mod_gzip_maximum_inmem_size;
  2589. /* Maximum size for in-memory compression */
  2590. /* Compressed object cache control variables... */
  2591. /* Using these default values the compressed object cache
  2592. /* can have 2^18 directories (256,000) */
  2593. ps->cache.root = ap_server_root; /* Default DIR is ServerRoot */
  2594. ps->cache.space = MOD_GZIP_DEFAULT_CACHE_SPACE;
  2595. ps->cache.space_set = 0;
  2596. ps->cache.maxexpire = MOD_GZIP_DEFAULT_CACHE_MAXEXPIRE;
  2597. ps->cache.maxexpire_set = 0;
  2598. ps->cache.defaultexpire = MOD_GZIP_DEFAULT_CACHE_EXPIRE;
  2599. ps->cache.defaultexpire_set = 0;
  2600. ps->cache.lmfactor = MOD_GZIP_DEFAULT_CACHE_LMFACTOR;
  2601. ps->cache.lmfactor_set = 0;
  2602. ps->cache.gcinterval = -1;
  2603. ps->cache.gcinterval_set = 0;
  2604. ps->cache.dirlevels = 3;
  2605. ps->cache.dirlevels_set = 0;
  2606. ps->cache.dirlength = 1;
  2607. ps->cache.dirlength_set = 0;
  2608. /* Initialize the include/exclude item map list... */
  2609. /* For now all init values are ZERO but don't use */
  2610. /* memset() since this may not always be the case. */
  2611. ps->imap_total_entries = 0;
  2612. for ( i=0; i<MOD_GZIP_IMAP_MAXNAMES; i++ )
  2613. {
  2614. ps->imap[i].include = 0;
  2615. ps->imap[i].type = 0;
  2616. ps->imap[i].action = 0;
  2617. ps->imap[i].name[0] = 0;
  2618. }/* End 'i' loop */
  2619. #ifdef MOD_GZIP_DEBUG1
  2620. mod_gzip_printf( "%s: ps->imap_total_entries = %d\n", cn, ps->imap_total_entries );
  2621. mod_gzip_printf( "%s: Exit > return( ps ) >\n", cn );
  2622. #endif
  2623. return ps;
  2624. }/* End of mod_gzip_create_config() */
  2625. static void *
  2626. mod_gzip_merge_config( pool *p, void *basev, void *overridesv )
  2627. {
  2628. mod_gzip_conf *ps = ap_pcalloc(p, sizeof(mod_gzip_conf));
  2629. mod_gzip_conf *base = (mod_gzip_conf *) basev;
  2630. mod_gzip_conf *overrides = (mod_gzip_conf *) overridesv;
  2631. ps->req = (overrides->req_set == 0) ? base->req : overrides->req;
  2632. ps->cache.root = (overrides->cache.root == NULL) ? base->cache.root : overrides->cache.root;
  2633. ps->cache.space = (overrides->cache.space_set == 0) ? base->cache.space : overrides->cache.space;
  2634. ps->cache.maxexpire = (overrides->cache.maxexpire_set == 0) ? base->cache.maxexpire : overrides->cache.maxexpire;
  2635. ps->cache.defaultexpire = (overrides->cache.defaultexpire_set == 0) ? base->cache.defaultexpire : overrides->cache.defaultexpire;
  2636. ps->cache.lmfactor = (overrides->cache.lmfactor_set == 0) ? base->cache.lmfactor : overrides->cache.lmfactor;
  2637. ps->cache.gcinterval = (overrides->cache.gcinterval_set == 0) ? base->cache.gcinterval : overrides->cache.gcinterval;
  2638. ps->cache.dirlevels = (overrides->cache.dirlevels_set == 0) ? base->cache.dirlevels : overrides->cache.dirlevels;
  2639. ps->cache.dirlength = (overrides->cache.dirlength_set == 0) ? base->cache.dirlength : overrides->cache.dirlength;
  2640. return ps;
  2641. }/* End of mod_gzip_merge_config() */
  2642. /*
  2643. * Module configuration directive handlers...
  2644. */
  2645. static const char *
  2646. mod_gzip_set_on(cmd_parms *parms, void *dummy, char *arg)
  2647. {
  2648. mod_gzip_conf *mgc;
  2649. #ifdef MOD_GZIP_DEBUG1
  2650. char cn[]="mod_gzip_set_on()";
  2651. #endif
  2652. /* Start... */
  2653. #ifdef MOD_GZIP_DEBUG1
  2654. mod_gzip_printf( "%s: Entry\n", cn );
  2655. mod_gzip_printf( "%s: arg=[%s]\n", cn, arg );
  2656. #endif
  2657. mgc = ( mod_gzip_conf * )
  2658. ap_get_module_config(parms->server->module_config, &gzip_module);
  2659. if ( ( arg[0] == 'Y' )||( arg[0] == 'y' ) )
  2660. {
  2661. /* Set the master 'request control' switches ON... */
  2662. mgc->req = 1; /* Yes */
  2663. mgc->req_set = 1; /* Yes */
  2664. }
  2665. else /* Set the master 'request control' switches OFF... */
  2666. {
  2667. mgc->req = 0; /* No */
  2668. mgc->req_set = 0; /* No */
  2669. }
  2670. #ifdef MOD_GZIP_DEBUG1
  2671. mod_gzip_printf( "%s: mgc->req = %ld\n", cn, (long) mgc->req );
  2672. mod_gzip_printf( "%s: mgc->req_set = %ld\n", cn, (long) mgc->req_set );
  2673. #endif
  2674. return NULL;
  2675. }
  2676. static const char *
  2677. mod_gzip_set_keep_workfiles(cmd_parms *parms, void *dummy, char *arg)
  2678. {
  2679. mod_gzip_conf *mgc;
  2680. #ifdef MOD_GZIP_DEBUG1
  2681. char cn[]="mod_gzip_set_keep_workfiles()";
  2682. #endif
  2683. /* Start... */
  2684. #ifdef MOD_GZIP_DEBUG1
  2685. mod_gzip_printf( "%s: Entry\n", cn );
  2686. mod_gzip_printf( "%s: arg=[%s]\n", cn, arg );
  2687. #endif
  2688. mgc = ( mod_gzip_conf * )
  2689. ap_get_module_config(parms->server->module_config, &gzip_module);
  2690. if ( ( arg[0] == 'Y' )||( arg[0] == 'y' ) )
  2691. {
  2692. mgc->keep_workfiles = 1; /* Yes */
  2693. }
  2694. else
  2695. {
  2696. mgc->keep_workfiles = 0; /* No */
  2697. }
  2698. #ifdef MOD_GZIP_DEBUG1
  2699. mod_gzip_printf( "%s: mgc->keep_workfiles = %ld\n", cn,
  2700. (long) mgc->keep_workfiles );
  2701. #endif
  2702. return NULL;
  2703. }
  2704. static const char *
  2705. mod_gzip_set_min_http(cmd_parms *parms, void *dummy, char *arg)
  2706. {
  2707. mod_gzip_conf *mgc;
  2708. #ifdef MOD_GZIP_DEBUG1
  2709. char cn[]="mod_gzip_set_min_http()";
  2710. #endif
  2711. /* Start... */
  2712. #ifdef MOD_GZIP_DEBUG1
  2713. mod_gzip_printf( "%s: Entry\n", cn );
  2714. mod_gzip_printf( "%s: arg=[%s]\n", cn, arg );
  2715. #endif
  2716. mgc = ( mod_gzip_conf * )
  2717. ap_get_module_config(parms->server->module_config, &gzip_module);
  2718. mgc->min_http = (int) atoi( arg );
  2719. #ifdef MOD_GZIP_DEBUG1
  2720. mod_gzip_printf( "%s: mgc->min_http = %ld\n", cn,
  2721. (long) mgc->min_http );
  2722. #endif
  2723. return NULL;
  2724. }
  2725. static const char *
  2726. mod_gzip_imap_add_item( mod_gzip_conf *mgc, char *arg, int flag1 )
  2727. {
  2728. int x;
  2729. char *p1;
  2730. int ch1;
  2731. int this_type=0;
  2732. int this_action=0;
  2733. int this_include=flag1;
  2734. #ifdef MOD_GZIP_DEBUG1
  2735. char cn[]="mod_gzip_imap_add_item()";
  2736. #endif
  2737. /* Start... */
  2738. #ifdef MOD_GZIP_DEBUG1
  2739. mod_gzip_printf( "%s: Entry\n", cn );
  2740. mod_gzip_printf( "%s: 1 arg=[%s]\n", cn, arg );
  2741. if ( flag1 == 1 )
  2742. {
  2743. mod_gzip_printf( "%s: flag1 = %d = INCLUDE\n", cn, flag1 );
  2744. }
  2745. else if ( flag1 == 0 )
  2746. {
  2747. mod_gzip_printf( "%s: flag1 = %d = EXCLUDE\n", cn, flag1 );
  2748. }
  2749. else
  2750. {
  2751. mod_gzip_printf( "%s: flag1 = %d = ??? Unknown value\n", cn, flag1 );
  2752. }
  2753. mod_gzip_printf( "%s: MOD-GZIP_IMAP_MAXNAMES = %d\n",
  2754. cn, MOD_GZIP_IMAP_MAXNAMES );
  2755. mod_gzip_printf( "%s: mgc->imap_total_entries = %d\n",
  2756. cn, mgc->imap_total_entries );
  2757. #endif /* MOD_GZIP_DEBUG1 */
  2758. /*
  2759. * Parse the config line...
  2760. */
  2761. p1 = arg;
  2762. while((*p1!=0)&&(*p1<33)) p1++;
  2763. ch1 = *p1;
  2764. this_type = MOD_GZIP_IMAP_ISHANDLER;
  2765. this_action = MOD_GZIP_IMAP_DYNAMIC1;
  2766. if ( ch1 == '!' )
  2767. {
  2768. arg++;
  2769. p1 = arg;
  2770. while((*p1!=0)&&(*p1<33)) p1++;
  2771. ch1 = *p1;
  2772. }
  2773. else
  2774. {
  2775. this_action = MOD_GZIP_IMAP_STATIC1;
  2776. }
  2777. if ( ch1 == '.' )
  2778. {
  2779. this_type = MOD_GZIP_IMAP_ISEXT;
  2780. }
  2781. else
  2782. {
  2783. p1 = arg;
  2784. while (*p1!=0)
  2785. {
  2786. if ( *p1 == '/' )
  2787. {
  2788. this_type = MOD_GZIP_IMAP_ISMIME;
  2789. }
  2790. p1++;
  2791. }
  2792. }
  2793. /*
  2794. * Safety checks...
  2795. */
  2796. if ( ( this_type != MOD_GZIP_IMAP_ISMIME ) &&
  2797. ( this_type != MOD_GZIP_IMAP_ISEXT ) &&
  2798. ( this_type != MOD_GZIP_IMAP_ISHANDLER ) )
  2799. {
  2800. #ifdef MOD_GZIP_DEBUG1
  2801. mod_gzip_printf( "%s: this_type = %d = MOD_GZIP_IMAP_IS??? Unknown type\n",cn,this_type);
  2802. mod_gzip_printf( "%s: return( mod_gzip: ERROR: Unrecognized item 'type'\n",cn);
  2803. #endif
  2804. return( "mod_gzip: ERROR: Unrecognized item 'type'" );
  2805. }
  2806. if ( ( this_action != MOD_GZIP_IMAP_DYNAMIC1 ) &&
  2807. ( this_action != MOD_GZIP_IMAP_STATIC1 ) )
  2808. {
  2809. #ifdef MOD_GZIP_DEBUG1
  2810. mod_gzip_printf( "%s: this_action = %d = MOD_GZIP_IMAP_??? Unknown action\n",cn,this_action);
  2811. mod_gzip_printf( "%s: return( mod_gzip: ERROR: Unrecognized item 'action'\n",cn);
  2812. #endif
  2813. return( "mod_gzip: ERROR: Unrecognized item 'action'" );
  2814. }
  2815. /*
  2816. * Wildcards...
  2817. */
  2818. if ( this_type != MOD_GZIP_IMAP_ISMIME )
  2819. {
  2820. /*
  2821. * Wildcards are only allowed in MIME strings such as 'image/*'
  2822. */
  2823. p1 = arg;
  2824. while (*p1!=0)
  2825. {
  2826. if ( *p1 == '*' )
  2827. {
  2828. return( "mod_gzip: ERROR: Wildcards are only allowed in MIME strings." );
  2829. }
  2830. p1++;
  2831. }
  2832. }
  2833. /*
  2834. * If there is room for a new record then add it...
  2835. */
  2836. if ( mgc->imap_total_entries < MOD_GZIP_IMAP_MAXNAMES )
  2837. {
  2838. if ( strlen( arg ) < MOD_GZIP_IMAP_MAXNAMELEN )
  2839. {
  2840. x = mgc->imap_total_entries;
  2841. p1 = arg;
  2842. while((*p1!=0)&&(*p1<33)) p1++;
  2843. strcpy( mgc->imap[x].name, p1 );
  2844. mgc->imap[x].include = this_include;
  2845. mgc->imap[x].type = this_type;
  2846. mgc->imap[x].action = this_action;
  2847. mgc->imap_total_entries++; /* Increase onboard items */
  2848. }
  2849. else /* ERROR: Name is too long */
  2850. {
  2851. #ifdef MOD_GZIP_DEBUG1
  2852. mod_gzip_printf( "%s: return( mod_gzip: ERROR: Item name is too long\n",cn);
  2853. #endif
  2854. return( "mod_gzip: ERROR: Item name is too long" );
  2855. }
  2856. }
  2857. else /* ERROR: INDEX is FULL */
  2858. {
  2859. #ifdef MOD_GZIP_DEBUG1
  2860. mod_gzip_printf( "%s: return( mod_gzip: ERROR: Item index is full\n",cn);
  2861. #endif
  2862. return( "mod_gzip: ERROR: Item index is full" );
  2863. }
  2864. #ifdef MOD_GZIP_DEBUG1
  2865. mod_gzip_printf( "%s: Exit > return( NULL ) >\n",cn);
  2866. #endif
  2867. return NULL;
  2868. }/* End of mod_gzip_imap_add_item() */
  2869. #ifdef MOD_GZIP_DEBUG1
  2870. int mod_gzip_imap_show_items( mod_gzip_conf *mgc )
  2871. {
  2872. /*
  2873. * DEBUG only. Show the complete include/exclude list.
  2874. * This is normally called from mod_gzip_init()
  2875. * after all the configuration routines have executed.
  2876. */
  2877. int i;
  2878. int x;
  2879. char cn[]="mod_gzip_imap_show_items()";
  2880. /* Start... */
  2881. mod_gzip_printf( "\n");
  2882. mod_gzip_printf( "%s: Entry\n", cn );
  2883. mod_gzip_printf( "%s: mgc->imap_total_entries= %d\n", cn,
  2884. (long) mgc->imap_total_entries );
  2885. for ( i=0; i<mgc->imap_total_entries; i++ )
  2886. {
  2887. x = i; /* Work variable */
  2888. mod_gzip_printf( "\n");
  2889. mod_gzip_printf( "%s: mgc->imap[%3.3d].include = %d\n", cn,x,mgc->imap[x].include);
  2890. mod_gzip_printf( "%s: mgc->imap[%3.3d].type = %d\n", cn,x,mgc->imap[x].type);
  2891. if ( mgc->imap[x].type == MOD_GZIP_IMAP_ISMIME )
  2892. {
  2893. mod_gzip_printf( "%s: mgc->imap[%3.3d].type = MOD_GZIP_IMAP_ISMIME\n",cn,x);
  2894. }
  2895. else if ( mgc->imap[x].type == MOD_GZIP_IMAP_ISEXT )
  2896. {
  2897. mod_gzip_printf( "%s: mgc->imap[%3.3d].type = MOD_GZIP_IMAP_ISEXT\n",cn,x);
  2898. }
  2899. else if ( mgc->imap[x].type == MOD_GZIP_IMAP_ISHANDLER )
  2900. {
  2901. mod_gzip_printf( "%s: mgc->imap[%3.3d].type = MOD_GZIP_IMAP_ISHANDLER\n",cn,x);
  2902. }
  2903. else /* Unrecognized item type... */
  2904. {
  2905. mod_gzip_printf( "%s: mgc->imap[%3.3d].type = MOD_GZIP_IMAP_IS??? Unknown type\n",cn,x);
  2906. }
  2907. mod_gzip_printf( "%s: mgc->imap[%3.3d].action = %d\n", cn,x,mgc->imap[x].action);
  2908. if ( mgc->imap[x].action == MOD_GZIP_IMAP_DYNAMIC1 )
  2909. {
  2910. mod_gzip_printf( "%s: mgc->imap[%3.3d].action = MOD_GZIP_IMAP_DYNAMIC1\n",cn,x);
  2911. }
  2912. else if ( mgc->imap[x].action == MOD_GZIP_IMAP_STATIC1 )
  2913. {
  2914. mod_gzip_printf( "%s: mgc->imap[%3.3d].action = MOD_GZIP_IMAP_STATIC1\n",cn,x);
  2915. }
  2916. else /* Unrecognized action type... */
  2917. {
  2918. mod_gzip_printf( "%s: mgc->imap[%3.3d].action = MOD_GZIP_IMAP_??? Unknown action\n",cn,x);
  2919. }
  2920. mod_gzip_printf( "%s: mgc->imap[%3.3d].name = [%s]\n",cn,x,mgc->imap[x].name);
  2921. }/* End 'i' loop */
  2922. mod_gzip_printf( "\n");
  2923. return 0;
  2924. }/* End of mod_gzip_imap_show_items() */
  2925. #endif /* MOD_GZIP_DEBUG1 */
  2926. static const char *
  2927. mod_gzip_set_item_include(cmd_parms *parms, void *dummy, char *arg)
  2928. {
  2929. mod_gzip_conf *mgc;
  2930. #ifdef MOD_GZIP_DEBUG1
  2931. char cn[]="mod_gzip_set_item_include()";
  2932. #endif
  2933. /* Start... */
  2934. #ifdef MOD_GZIP_DEBUG1
  2935. mod_gzip_printf( "%s: Entry\n", cn );
  2936. mod_gzip_printf( "%s: arg=[%s]\n", cn, arg );
  2937. #endif
  2938. mgc = ( mod_gzip_conf * )
  2939. ap_get_module_config(parms->server->module_config, &gzip_module);
  2940. /* Pass pre-determined pointer to config structure... */
  2941. /* Pass '1' for parm 3 to INCLUDE this item... */
  2942. return( mod_gzip_imap_add_item( mgc, arg, 1 ) );
  2943. }
  2944. static const char *
  2945. mod_gzip_set_item_exclude(cmd_parms *parms, void *dummy, char *arg)
  2946. {
  2947. mod_gzip_conf *mgc;
  2948. #ifdef MOD_GZIP_DEBUG1
  2949. char cn[]="mod_gzip_set_item_exclude()";
  2950. #endif
  2951. /* Start... */
  2952. #ifdef MOD_GZIP_DEBUG1
  2953. mod_gzip_printf( "%s: Entry\n", cn );
  2954. mod_gzip_printf( "%s: arg=[%s]\n", cn, arg );
  2955. #endif
  2956. mgc = ( mod_gzip_conf * )
  2957. ap_get_module_config(parms->server->module_config, &gzip_module);
  2958. /* Pass pre-determined pointer to config structure... */
  2959. /* Pass '0' for parm 3 to EXCLUDE this item... */
  2960. return( mod_gzip_imap_add_item( mgc, arg, 0 ) );
  2961. }
  2962. static const char *
  2963. mod_gzip_set_temp_dir(cmd_parms *parms, void *dummy, char *arg)
  2964. {
  2965. mod_gzip_conf *mgc;
  2966. char cn[]="mod_gzip_set_temp_dir()";
  2967. /* Start... */
  2968. #ifdef MOD_GZIP_DEBUG1
  2969. mod_gzip_printf( "%s: Entry\n", cn );
  2970. mod_gzip_printf( "%s: arg=[%s]\n", cn, arg );
  2971. #endif
  2972. mgc = ( mod_gzip_conf * )
  2973. ap_get_module_config(parms->server->module_config, &gzip_module);
  2974. mgc->cache.root = arg; /* For now temp dir is used as cache root */
  2975. strcpy( mod_gzip_temp_dir, arg );
  2976. mgc->cache.root = mod_gzip_temp_dir;
  2977. #ifdef MOD_GZIP_DEBUG1
  2978. mod_gzip_printf( "%s: mgc->cache.root=[%s]\n", cn, mgc->cache.root );
  2979. #endif
  2980. return NULL;
  2981. }
  2982. static const char *
  2983. mod_gzip_set_minimum_file_size(cmd_parms *parms, void *dummy, char *arg)
  2984. {
  2985. mod_gzip_conf *mgc;
  2986. long lval;
  2987. #ifdef MOD_GZIP_DEBUG1
  2988. char cn[]="mod_gzip_set_minimum_file_size()";
  2989. #endif
  2990. /* Start... */
  2991. #ifdef MOD_GZIP_DEBUG1
  2992. mod_gzip_printf( "%s: Entry\n", cn );
  2993. mod_gzip_printf( "%s: arg=[%s]\n", cn, arg );
  2994. #endif
  2995. mgc = ( mod_gzip_conf * )
  2996. ap_get_module_config(parms->server->module_config, &gzip_module);
  2997. lval = (long) atol(arg);
  2998. /* 300 bytes is the minimum at all times */
  2999. if ( lval < 300L ) lval = 300L;
  3000. mgc->minimum_file_size = (long) lval; /* Set config */
  3001. mod_gzip_minimum_file_size = (long) lval; /* Set global */
  3002. #ifdef MOD_GZIP_DEBUG1
  3003. mod_gzip_printf( "%s: ....mgc->minimum_file_size = %ld\n", cn,
  3004. (long) mgc->minimum_file_size );
  3005. mod_gzip_printf( "%s: mod_gzip_minimum_file_size = %ld\n", cn,
  3006. (long) mod_gzip_minimum_file_size );
  3007. #endif
  3008. return NULL;
  3009. }
  3010. static const char *
  3011. mod_gzip_set_maximum_inmem_size(cmd_parms *parms, void *dummy, char *arg)
  3012. {
  3013. mod_gzip_conf *mgc;
  3014. long lval=0;
  3015. #ifdef MOD_GZIP_DEBUG1
  3016. char cn[]="mod_gzip_set_maximum_inmem_size()";
  3017. #endif
  3018. /* Start... */
  3019. #ifdef MOD_GZIP_DEBUG1
  3020. mod_gzip_printf( "%s: Entry\n", cn );
  3021. mod_gzip_printf( "%s: arg=[%s]\n", cn, arg );
  3022. #endif
  3023. mgc = ( mod_gzip_conf * )
  3024. ap_get_module_config(parms->server->module_config, &gzip_module);
  3025. lval = (long) atol(arg);
  3026. /* 60000 bytes is the current maximum since a malloc() call is used */
  3027. if ( lval > 60000L ) lval = 60000L;
  3028. mgc->maximum_inmem_size = (long) lval; /* Set config */
  3029. mod_gzip_maximum_inmem_size = (long) lval; /* Set global */
  3030. #ifdef MOD_GZIP_DEBUG1
  3031. mod_gzip_printf( "%s: ....mgc->maximum_inmem_size = %ld\n", cn,
  3032. (long) mgc->maximum_inmem_size );
  3033. mod_gzip_printf( "%s: mod_gzip_maximum_inmem_size = %ld\n", cn,
  3034. (long) mod_gzip_maximum_inmem_size );
  3035. #endif
  3036. return NULL;
  3037. }
  3038. static const char *
  3039. mod_gzip_set_do_static_files(cmd_parms *parms, void *dummy, char *arg)
  3040. {
  3041. mod_gzip_conf *mgc;
  3042. #ifdef MOD_GZIP_DEBUG1
  3043. char cn[]="mod_gzip_set_do_static_files()";
  3044. #endif
  3045. /* Start... */
  3046. #ifdef MOD_GZIP_DEBUG1
  3047. mod_gzip_printf( "%s: Entry\n", cn );
  3048. mod_gzip_printf( "%s: arg=[%s]\n", cn, arg );
  3049. #endif
  3050. mgc = ( mod_gzip_conf * )
  3051. ap_get_module_config(parms->server->module_config, &gzip_module);
  3052. if ( ( arg[0] == 'Y' )||( arg[0] == 'y' ) )
  3053. {
  3054. mgc->do_static_files = 1; /* Yes */
  3055. }
  3056. else
  3057. {
  3058. mgc->do_static_files = 0; /* No */
  3059. }
  3060. #ifdef MOD_GZIP_DEBUG1
  3061. mod_gzip_printf( "%s: mgc->do_static_files = %ld\n", cn,
  3062. (long) mgc->do_static_files );
  3063. #endif
  3064. return NULL;
  3065. }
  3066. static const char *
  3067. mod_gzip_set_do_cgi(cmd_parms *parms, void *dummy, char *arg)
  3068. {
  3069. mod_gzip_conf *mgc;
  3070. #ifdef MOD_GZIP_DEBUG1
  3071. char cn[]="mod_gzip_set_do_cgi()";
  3072. #endif
  3073. /* Start... */
  3074. #ifdef MOD_GZIP_DEBUG1
  3075. mod_gzip_printf( "%s: Entry\n", cn );
  3076. mod_gzip_printf( "%s: arg=[%s]\n", cn, arg );
  3077. #endif
  3078. mgc = ( mod_gzip_conf * )
  3079. ap_get_module_config(parms->server->module_config, &gzip_module);
  3080. if ( ( arg[0] == 'Y' )||( arg[0] == 'y' ) )
  3081. {
  3082. mgc->do_cgi = 1; /* Yes */
  3083. }
  3084. else
  3085. {
  3086. mgc->do_cgi = 0; /* No */
  3087. }
  3088. #ifdef MOD_GZIP_DEBUG1
  3089. mod_gzip_printf( "%s: mgc->do_cgi = %ld\n", cn,
  3090. (long) mgc->do_cgi );
  3091. #endif
  3092. return NULL;
  3093. }
  3094. static const handler_rec mod_gzip_handlers[] =
  3095. {
  3096. /*
  3097. * This is where we associate an ASCII NAME for our 'handler'
  3098. * which is what gets set into the r->handler field for a
  3099. * request and allows the function name associated with the
  3100. * ASCII name to be called and handle the request...
  3101. */
  3102. /* Add a 'name' and some types to our handler... */
  3103. {"mod_gzip_handler", mod_gzip_handler},
  3104. {CGI_MAGIC_TYPE, mod_gzip_handler},
  3105. {"cgi-script", mod_gzip_handler},
  3106. {"*", mod_gzip_handler},
  3107. {NULL}
  3108. };
  3109. static const command_rec mod_gzip_cmds[] =
  3110. {
  3111. /*
  3112. * Define our httpd.conf configuration diectives and
  3113. * the local routines that are responsible for processing
  3114. * those directives when the time comes...
  3115. */
  3116. {"mod_gzip_on", mod_gzip_set_on, NULL, RSRC_CONF, TAKE1,
  3117. "Yes=mod_gzip will handle requests No=mod_gzip runs in 'passthrough' mode"},
  3118. {"mod_gzip_do_static_files", mod_gzip_set_do_static_files, NULL, RSRC_CONF, TAKE1,
  3119. "'Yes' means mod_gzip will compress static files."},
  3120. {"mod_gzip_do_cgi", mod_gzip_set_do_cgi, NULL, RSRC_CONF, TAKE1,
  3121. "'Yes' means mod_gzip will compress dynamic CGI script output."},
  3122. {"mod_gzip_keep_workfiles", mod_gzip_set_keep_workfiles, NULL, RSRC_CONF, TAKE1,
  3123. "On=Keep work files Off=No"},
  3124. {"mod_gzip_min_http", mod_gzip_set_min_http, NULL, RSRC_CONF, TAKE1,
  3125. "Minimum HTTP support level to receive compression. 1001=HTTP/1.1"},
  3126. {"mod_gzip_minimum_file_size", mod_gzip_set_minimum_file_size, NULL, RSRC_CONF, TAKE1,
  3127. "The minimum size ( in bytes ) before compression will be attempted"},
  3128. {"mod_gzip_maximum_inmem_size", mod_gzip_set_maximum_inmem_size, NULL, RSRC_CONF, TAKE1,
  3129. "The maximum size ( in bytes ) to use for in-memory compression."},
  3130. {"mod_gzip_temp_dir", mod_gzip_set_temp_dir, NULL, RSRC_CONF, TAKE1,
  3131. "The directory to use for work files and compression cache"},
  3132. {"mod_gzip_item_include", mod_gzip_set_item_include, NULL, RSRC_CONF, TAKE1,
  3133. "Add the item the inclusion list"},
  3134. {"mod_gzip_item_exclude", mod_gzip_set_item_exclude, NULL, RSRC_CONF, TAKE1,
  3135. "Add the item the exclusion list"},
  3136. {NULL}
  3137. };
  3138. /*
  3139. * The actual module 'jump' table...
  3140. *
  3141. * If one of the fixed 'call' points has a valid function
  3142. * address then Apache will 'call' into it at the appropriate time.
  3143. *
  3144. * When the compressed object cache is engaged we will need to
  3145. * simply add some handlers for the URI detection and translation
  3146. * call point(s).
  3147. */
  3148. module MODULE_VAR_EXPORT gzip_module =
  3149. {
  3150. STANDARD_MODULE_STUFF,
  3151. mod_gzip_init, /* initializer */
  3152. NULL, /* create per-directory config structure */
  3153. NULL, /* merge per-directory config structures */
  3154. mod_gzip_create_config, /* create per-server config structure */
  3155. mod_gzip_merge_config, /* merge per-server config structures */
  3156. mod_gzip_cmds, /* command table */
  3157. mod_gzip_handlers, /* handlers */
  3158. NULL, /* translate_handler */
  3159. NULL, /* check_user_id */
  3160. NULL, /* check auth */
  3161. NULL, /* check access */
  3162. NULL, /* type_checker */
  3163. NULL, /* pre-run fixups */
  3164. NULL, /* logger */
  3165. NULL, /* header parser */
  3166. NULL, /* child_init */
  3167. NULL, /* child_exit */
  3168. NULL /* post read-request */
  3169. };
  3170. #ifdef NETWARE
  3171. int main(int argc, char *argv[])
  3172. {
  3173. ExitThread(TSR_THREAD, 0);
  3174. }
  3175. #endif
  3176. FILE *mod_gzip_open_output_file(
  3177. request_rec *r,
  3178. char *output_filename,
  3179. int *rc
  3180. )
  3181. {
  3182. FILE *ifh;
  3183. #ifdef MOD_GZIP_DEBUG1
  3184. char cn[]="mod_gzip_open_output_file():::";
  3185. #endif
  3186. /*
  3187. * Start...
  3188. */
  3189. #ifdef MOD_GZIP_DEBUG1
  3190. mod_gzip_printf( "%s: Entry...\n",cn);
  3191. mod_gzip_printf( "%s: output_filename=[%s]\n",cn,output_filename);
  3192. #endif
  3193. ifh = fopen( output_filename, "rb" ); /* Open in BINARY mode */
  3194. if ( !ifh ) /* The file failed to open... */
  3195. {
  3196. #ifdef MOD_GZIP_DEBUG1
  3197. mod_gzip_printf( "%s: ERROR: Cannot open file [%s]\n",
  3198. cn,output_filename);
  3199. #endif
  3200. /*
  3201. * The workfile was created OK but now will not re-open.
  3202. * This is worth a strike in the ERROR log.
  3203. */
  3204. ap_log_error( APLOG_MARK,APLOG_NOERRNO|APLOG_ERR, r->server,
  3205. "mod_gzip: Cannot re-open output_filename=[%s]",
  3206. output_filename );
  3207. /* Return DECLINED and let default logic finish the request... */
  3208. #ifdef MOD_GZIP_DEBUG1
  3209. mod_gzip_printf( "%s: Exit > return( NULL ) >\n",cn);
  3210. #endif
  3211. #ifdef MOD_GZIP_USES_APACHE_LOGS
  3212. /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */
  3213. ap_table_setn(
  3214. r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:WORK_OPENFAIL"));
  3215. #endif /* MOD_GZIP_USES_APACHE_LOGS */
  3216. *rc = DECLINED; /* Update caller's result code... */
  3217. return NULL;
  3218. }/* End 'if ( !ifh )' */
  3219. #ifdef MOD_GZIP_DEBUG1
  3220. mod_gzip_printf( "%s: File is now open...\n",cn);
  3221. mod_gzip_printf( "%s: Exit > return( FILE *ifh ) >\n",cn);
  3222. #endif
  3223. *rc = OK; /* Update caller's result code */
  3224. return ifh; /* Return the file handle */
  3225. }/* End of mod_gzip_open_output_file() */
  3226. int mod_gzip_encode_and_transmit(
  3227. request_rec *r,
  3228. char *source,
  3229. int source_is_a_file,
  3230. long input_size,
  3231. int nodecline
  3232. )
  3233. {
  3234. GZP_CONTROL gzc;
  3235. GZP_CONTROL* gzp = &gzc;
  3236. int rc = 0;
  3237. FILE *ifh = 0;
  3238. int bytesread = 0;
  3239. long output_size = 0;
  3240. long compression_ratio = 0;
  3241. char* gz1_ismem_obuf = 0;
  3242. int finalize_stats = 1;
  3243. int gz1_ismem_obuf_was_allocated = 0;
  3244. char content_length[20]; /* For Content-length updates */
  3245. #define MOD_GZIP_LARGE_BUFFER_SIZE 8192
  3246. char tmp[ MOD_GZIP_LARGE_BUFFER_SIZE + 2 ]; /* Scratch buffer */
  3247. char *actual_content_encoding_name = "gzip"; /* Adjustable */
  3248. const char *compression_format;
  3249. #ifdef MOD_GZIP_DEBUG1
  3250. char cn[]="mod_gzip_encode_and_transmit()";
  3251. #endif
  3252. void *modconf = r->server->module_config;
  3253. #ifdef MOD_GZIP_USES_APACHE_LOGS
  3254. char log_info[40]; /* Scratch buffer */
  3255. #endif
  3256. /*
  3257. * Start...
  3258. *
  3259. * Establish a local pointer to module configuration data...
  3260. */
  3261. mod_gzip_conf *conf =
  3262. (mod_gzip_conf *) ap_get_module_config( modconf, &gzip_module );
  3263. #ifdef MOD_GZIP_DEBUG1
  3264. mod_gzip_printf( "%s: Entry...\n", cn);
  3265. mod_gzip_printf( "%s: source_is_a_file = %d\n", cn, source_is_a_file);
  3266. mod_gzip_printf( "%s: nodecline = %d\n", cn, nodecline);
  3267. if ( source_is_a_file ) /* Show the filename... */
  3268. {
  3269. mod_gzip_printf( "%s: source = [%s]\n", cn, source);
  3270. }
  3271. else /* Don't try to print the memory buffer... */
  3272. {
  3273. mod_gzip_printf( "%s: source = MEMORY BUFFER\n", cn );
  3274. }
  3275. mod_gzip_printf( "%s: input_size = %ld\n", cn,(long)input_size);
  3276. #endif /* MOD_GZIP_DEBUG1 */
  3277. #ifdef MOD_GZIP_USES_APACHE_LOGS
  3278. /* This routine 'assumes' that the final result is 'OK' */
  3279. /* and lets the remainder of the processing set the result */
  3280. /* string to some other value, if necessary. */
  3281. /* Since we are now using the 'nodecline' flag and might */
  3282. /* have to 'stand and deliver' then this allows the right */
  3283. /* result code to appear in the log files even if we */
  3284. /* cannot DECLINE the processing. */
  3285. ap_table_setn(
  3286. r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"OK"));
  3287. /* We can also update the 'input' size right away since it is known */
  3288. sprintf( log_info,"%d", (int) input_size );
  3289. ap_table_setn( r->notes,"mod_gzip_input_size",ap_pstrdup(r->pool,log_info));
  3290. #endif /* MOD_GZIP_USES_APACHE_LOGS */
  3291. /*
  3292. * If the source has no length then DECLINE the processing...
  3293. */
  3294. if ( input_size < 1 )
  3295. {
  3296. #ifdef MOD_GZIP_DEBUG1
  3297. mod_gzip_printf( "%s: ERROR: Input source has no valid length.\n",cn);
  3298. mod_gzip_printf( "%s: This request will not be processed...\n",cn);
  3299. #endif
  3300. /* An existing request object with no length is worth a warning... */
  3301. ap_log_error( APLOG_MARK,APLOG_NOERRNO|APLOG_WARNING, r->server,
  3302. "mod_gzip: r->filename=[%s] has no length",r->filename );
  3303. #ifdef MOD_GZIP_DEBUG1
  3304. mod_gzip_printf( "%s: Exit > return( DECLINED ) >\n",cn);
  3305. #endif
  3306. #ifdef MOD_GZIP_USES_APACHE_LOGS
  3307. /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */
  3308. ap_table_setn(
  3309. r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:NO_I_LEN"));
  3310. #endif /* MOD_GZIP_USES_APACHE_LOGS */
  3311. return DECLINED;
  3312. }
  3313. /*
  3314. * If we're only supposed to send header information (HEAD request)
  3315. * then all we need to do is call ap_send_http_header() at this point
  3316. * and then return 'OK'...
  3317. */
  3318. if ( r->header_only )
  3319. {
  3320. #ifdef MOD_GZIP_DEBUG1
  3321. mod_gzip_printf( "%s: HEAD request only... ignore body data...\n",cn);
  3322. #endif
  3323. /*
  3324. * Set outbound response header fields...
  3325. *
  3326. * NOTE: If this is just a HEAD request then
  3327. * there is no need to make the API call...
  3328. *
  3329. * ap_update_mtime( r, r->finfo.st_mtime );
  3330. *
  3331. * ...and update the actual time. Use the time
  3332. * that's currently associated with the object.
  3333. */
  3334. ap_set_last_modified(r);
  3335. ap_set_etag(r);
  3336. ap_table_setn(r->headers_out, "Accept-Ranges", "bytes");
  3337. /* Start a timer for this transaction... */
  3338. ap_soft_timeout( "mod_gzip: HEAD request handler", r );
  3339. #ifdef MOD_GZIP_DEBUG1
  3340. mod_gzip_printf( "%s: r->content_type=[%s]\n",cn,r->content_type);
  3341. mod_gzip_printf( "%s: Call ap_send_http_header()...\n",cn);
  3342. #endif
  3343. ap_send_http_header(r);
  3344. #ifdef MOD_GZIP_DEBUG1
  3345. mod_gzip_printf( "%s: Back ap_send_http_header()...\n",cn);
  3346. mod_gzip_printf( "%s: Call ap_kill_timeout()...\n",cn);
  3347. #endif
  3348. ap_kill_timeout(r);
  3349. #ifdef MOD_GZIP_DEBUG1
  3350. mod_gzip_printf( "%s: Back ap_kill_timeout()...\n",cn);
  3351. mod_gzip_printf( "%s: Exit > return( OK ) >\n",cn);
  3352. #endif
  3353. #ifdef MOD_GZIP_USES_APACHE_LOGS
  3354. /* Return OK but distinguish it from a 'GET' request in logs... */
  3355. ap_table_setn(
  3356. r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"OK:HEAD_ONLY"));
  3357. #endif /* MOD_GZIP_USES_APACHE_LOGS */
  3358. return OK;
  3359. }/* End 'if( r->header_only )' */
  3360. /*
  3361. * See if the source meets the MINUMUM SIZE requirement...
  3362. *
  3363. * Default to 300 bytes as a minimum size requirement for it
  3364. * to even be worth a compression attempt. This works well as a
  3365. * minimum for both GZIP and ZLIB which are both LZ77 based and,
  3366. * as such, always have the potential to actually increase the
  3367. * size of the file.
  3368. *
  3369. * The value is a module global that can be adjusted 'on the fly'
  3370. * as load conditions change or as required for other reasons.
  3371. */
  3372. #ifdef MOD_GZIP_DEBUG1
  3373. mod_gzip_printf( "%s: conf->minimum_file_size = %ld\n",
  3374. cn, (long) conf->minimum_file_size );
  3375. #endif
  3376. if ( input_size < (long) conf->minimum_file_size )
  3377. {
  3378. #ifdef MOD_GZIP_DEBUG1
  3379. mod_gzip_printf( "%s: Source does not meet the minimum size requirement...\n",cn);
  3380. mod_gzip_printf( "%s: nodecline = %d\n",cn,nodecline);
  3381. #endif
  3382. /* Set the 'mod_gzip_result' note value to something */
  3383. /* that indicates this was too small... */
  3384. #ifdef MOD_GZIP_USES_APACHE_LOGS
  3385. /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */
  3386. ap_table_setn(
  3387. r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:TOO_SMALL"));
  3388. #endif /* MOD_GZIP_USES_APACHE_LOGS */
  3389. /* Is it OK to DECLINE?... */
  3390. if ( nodecline ) /* We have been told NOT to DECLINE */
  3391. {
  3392. #ifdef MOD_GZIP_DEBUG1
  3393. mod_gzip_printf( "%s: DECLINE is NOT allowed...\n",cn);
  3394. #endif
  3395. /* Skip the compression phase and just set the output */
  3396. /* control skid up to send the real input data... */
  3397. output_size = input_size;
  3398. if ( source_is_a_file ) /* Source is a workfile... */
  3399. {
  3400. #ifdef MOD_GZIP_DEBUG1
  3401. mod_gzip_printf( "%s: Force send - source = FILE[%s]\n",
  3402. cn,source);
  3403. #endif
  3404. strcpy( gzp->output_filename, source );
  3405. gzp->output_ismem = 0; /* Output is a disk file */
  3406. gz1_ismem_obuf = 0; /* Make sure this is NULL */
  3407. gzp->output_ismem_obuf = 0; /* Not used for this method */
  3408. gzp->output_ismem_obuflen = 0; /* Not used for this method */
  3409. ifh = mod_gzip_open_output_file( r, gzp->output_filename, &rc );
  3410. if ( !ifh ) /* The file failed to open... */
  3411. {
  3412. /* We really MUST decline... */
  3413. /* Logs have already been updated... */
  3414. return( rc );
  3415. }
  3416. }
  3417. else /* Source is just a memory buffer... */
  3418. {
  3419. #ifdef MOD_GZIP_DEBUG1
  3420. mod_gzip_printf( "%s: Force send - source = MEMORY BUFFER\n",cn);
  3421. #endif
  3422. gzp->output_ismem = 1;
  3423. gz1_ismem_obuf = source;
  3424. gz1_ismem_obuf_was_allocated = 0; /* No 'free' is required */
  3425. }
  3426. #ifdef MOD_GZIP_DEBUG1
  3427. mod_gzip_printf( "%s: No compression attempt was made.\n",cn);
  3428. mod_gzip_printf( "%s: Advancing directly to transmit phase...\n",cn);
  3429. #endif
  3430. goto mod_gzip_encode_and_transmit_send_start; /* Jump */
  3431. }
  3432. else /* It's OK to DECLINE the processing... */
  3433. {
  3434. #ifdef MOD_GZIP_DEBUG1
  3435. mod_gzip_printf( "%s: DECLINE is allowed...\n",cn);
  3436. mod_gzip_printf( "%s: Exit > return( DECLINED ) >\n",cn);
  3437. #endif
  3438. return DECLINED;
  3439. }
  3440. }
  3441. else /* The source is larger than the minimum size requirement... */
  3442. {
  3443. #ifdef MOD_GZIP_DEBUG1
  3444. mod_gzip_printf( "%s: Source meets the minimum size requirement.\n",cn);
  3445. mod_gzip_printf( "%s: Assuming OK to proceed...\n",cn);
  3446. #endif
  3447. }
  3448. /*
  3449. * We must now encode the requested object...
  3450. *
  3451. * Statistically speaking, most 'text/*' pages are
  3452. * less than 60k. XML documents are an exception.
  3453. *
  3454. * If the size of the requested object is less than 60k
  3455. * then go ahead and compress the source directly to a
  3456. * small memory buffer. If the requested object is greater
  3457. * than 60k then go ahead and swap the results to an output
  3458. * disk file and then send the contents of the result file.
  3459. *
  3460. * We can't ever allocate all the memory we want inside of
  3461. * a Server task thread so there must always be this kind
  3462. * of 'decision' making about when we can compress to
  3463. * a memory buffer ( Less than 60k ) and when we must
  3464. * compress to DISK. ( Greater than 60k ).
  3465. *
  3466. * There is a trade-off here between running the risk of
  3467. * too many tasks stealing away all the heap space and
  3468. * still maintaining performance. Given all the variables
  3469. * involved such as the true efficiency of the compression
  3470. * algorithm(s) and the speed of the CPU and the amount of
  3471. * memory/disk space available there is no 'real' answer to
  3472. * this dilemma other than relying on statistical data
  3473. * and empirical observations. The 60k limit on in-memory
  3474. * compression seems to strike a good balance and performs
  3475. * incredibly well under the heaviest of loads.
  3476. *
  3477. * At all times, the greatest benefit being gained is the
  3478. * appreciable reduction of data that must actually be
  3479. * sent by the TCP/IP sub-system and the reduced usage
  3480. * of those resources to perform the transmission task(s),
  3481. *
  3482. * The key, then, is to always strive for a balance where
  3483. * the time and resource usage it takes to compress a
  3484. * deliverable object will always be less than the processor
  3485. * burden that would otherwise be realized by handing the
  3486. * full, uncompressed object to the TCP/IP sub-system which
  3487. * always extend the time that the thread and all its
  3488. * locked resources must be maintained as well as the
  3489. * overhead for keeping a connection active any longer
  3490. * than is absolutely necessary.
  3491. *
  3492. * As long as the resource usage it takes to accomplish
  3493. * a significant reduction in the amount of data that
  3494. * must actually be processed by the remainder of the
  3495. * HTTP task thread and the TCP/IP sub-system itself
  3496. * is always less than the processor burden seen by
  3497. * NOT doing so then we are always 'ahead of the game'.
  3498. */
  3499. /*
  3500. * See if the object size exceeds the current MAXIMUM size
  3501. * to use for in-memory compression...
  3502. *
  3503. * See notes above about a range of 60k or so being the best
  3504. * value for heavy load conditions.
  3505. *
  3506. * This number is currently a global so it can be changed
  3507. * 'on the fly' and can 'breathe' as the load changes.
  3508. * It should probably become a thread specific variable
  3509. * so each task can have its 'own' max value depending
  3510. * on current load conditions.
  3511. */
  3512. #ifdef MOD_GZIP_DEBUG1
  3513. mod_gzip_printf( "%s: conf->maximum_inmem_size = %ld\n",
  3514. cn, (long) conf->maximum_inmem_size );
  3515. #endif
  3516. /*
  3517. * Set up the INPUT target...
  3518. */
  3519. /* The size and type of the input source is always known */
  3520. /* and was passed by the caller... */
  3521. if ( source_is_a_file )
  3522. {
  3523. #ifdef MOD_GZIP_DEBUG1
  3524. mod_gzip_printf( "%s: Input source is file[%s]\n",cn,source);
  3525. #endif
  3526. strcpy( gzp->input_filename, source );
  3527. gzp->input_ismem = 0; /* Input is a disk file */
  3528. gzp->input_ismem_ibuf = 0; /* Source buffer */
  3529. gzp->input_ismem_ibuflen = 0; /* Length of data */
  3530. }
  3531. else
  3532. {
  3533. #ifdef MOD_GZIP_DEBUG1
  3534. mod_gzip_printf( "%s: Input source is a MEMORY BUFFER\n",cn);
  3535. #endif
  3536. *gzp->input_filename = 0; /* Not used */
  3537. gzp->input_ismem = 1; /* Input is a memory buffer */
  3538. gzp->input_ismem_ibuf = source; /* Source buffer */
  3539. gzp->input_ismem_ibuflen = input_size; /* Length of data */
  3540. }
  3541. /*
  3542. * Set up the OUTPUT target...
  3543. */
  3544. gzp->decompress = 0; /* Perform encoding */
  3545. /* Recover the compression format we're supposed to use. */
  3546. compression_format = ap_table_get(r->notes, "mod_gzip_compression_format");
  3547. if (compression_format && strcmp(compression_format, "deflate") == 0)
  3548. {
  3549. actual_content_encoding_name = "deflate";
  3550. gzp->compression_format = DEFLATE_FORMAT;
  3551. }
  3552. else
  3553. {
  3554. gzp->compression_format = GZIP_FORMAT;
  3555. }
  3556. if ( input_size <= (long) conf->maximum_inmem_size )
  3557. {
  3558. /* The input source is small enough to compress directly */
  3559. /* to an in-memory output buffer... */
  3560. #ifdef MOD_GZIP_DEBUG1
  3561. mod_gzip_printf( "%s: Input source is small enough for in-memory compression.\n",cn);
  3562. #endif
  3563. *gzp->output_filename = 0; /* Not used */
  3564. gzp->output_ismem = 1; /* Output is a memory buffer */
  3565. /*
  3566. * Allocate a memory buffer to hold compressed output.
  3567. *
  3568. * For now this is borrowed from the heap for only
  3569. * the lifetime of this function call. If the stack
  3570. * can handle the current in-memory MAXSIZE then
  3571. * that will work just as well.
  3572. *
  3573. * Add at least 1000 bytes in case the compression
  3574. * algorithm(s) actually expands the source ( which is
  3575. * not likely but is always a possibility when using
  3576. * any LZ77 based compression such as GZIP or ZLIB )
  3577. */
  3578. gz1_ismem_obuf = (char *) malloc( input_size + 1000 );
  3579. if ( !gz1_ismem_obuf )
  3580. {
  3581. /*
  3582. * There wasn't enough memory left for another
  3583. * in-memory compression buffer so default to using
  3584. * an output disk file instead...
  3585. */
  3586. #ifdef MOD_GZIP_DEBUG1
  3587. mod_gzip_printf( "%s: ERROR: Cannot allocate GZP memory...\n",cn);
  3588. mod_gzip_printf( "%s: Defaulting to output file method... \n",cn);
  3589. #endif
  3590. gzp->output_ismem = 0; /* Switch to using a disk file */
  3591. }
  3592. else /* We got the memory we need for in-memory compression... */
  3593. {
  3594. /* Set the local flag which tells the exit logic */
  3595. /* that 'gz1_ismem_obuf' was actually allocated */
  3596. /* and not simply set to 'source' so that the */
  3597. /* allocation can be 'freed' on exit... */
  3598. gz1_ismem_obuf_was_allocated = 1; /* 'free' is required */
  3599. /* Compression codecs require a 'clean' buffer so */
  3600. /* we need to spend the cycles for a memset() call. */
  3601. memset( gz1_ismem_obuf, 0, ( input_size + 1000 ) );
  3602. /* Set OUTPUT buffer control variables... */
  3603. gzp->output_ismem_obuf = gz1_ismem_obuf;
  3604. gzp->output_ismem_obuflen = input_size + 1000;
  3605. }
  3606. }/* End 'if ( input_size <= conf->maximum_inmem_size )' */
  3607. /*
  3608. * If we are unable ( or it is unadvisable ) to use
  3609. * an in-memory output buffer at this time then the
  3610. * 'gzp->output_ismem' flag will still be ZERO at this point.
  3611. */
  3612. if ( gzp->output_ismem != 1 )
  3613. {
  3614. /*
  3615. * The input source is NOT small enough to compress to an
  3616. * in-memory output buffer or it is unadvisable to do
  3617. * so at this time so just use an output file...
  3618. */
  3619. #ifdef MOD_GZIP_DEBUG1
  3620. mod_gzip_printf( "%s: Input source too big for in-memory compression.\n",cn);
  3621. #endif
  3622. /*
  3623. * Create the GZP output target name...
  3624. */
  3625. mod_gzip_create_unique_filename(
  3626. (mod_gzip_conf *) conf,
  3627. (char *) gzp->output_filename,
  3628. MOD_GZIP_MAX_PATH_LEN
  3629. );
  3630. /*
  3631. * COMPRESSION OBJECT CACHE
  3632. *
  3633. * TODO: Obviously one place to add the compression cache
  3634. * logic is right here. If there is already a pre-compressed
  3635. * version of the requested entity sitting in the special
  3636. * compression cache and it is 'fresh' then go ahead and
  3637. * send it as the actual response. Add a CRC/MD5 checksum
  3638. * to the stored compression object(s) so we can quickly
  3639. * determine if the compressed object is 'fresh'. Relying
  3640. * on Content-length and/or modification time/date won't handle
  3641. * all possible expiration scenarios for compressed objects.
  3642. */
  3643. gzp->output_ismem = 0; /* Output is a disk file */
  3644. gz1_ismem_obuf = 0; /* Make sure this is NULL */
  3645. /* Set OUTPUT buffer control variables... */
  3646. gzp->output_ismem_obuf = 0; /* Not used for this method */
  3647. gzp->output_ismem_obuflen = 0; /* Not used for this method */
  3648. }/* End 'else' */
  3649. #ifdef MOD_GZIP_DEBUG1
  3650. mod_gzip_printf( "%s: gzp->decompress = %d\n" ,cn,gzp->decompress);
  3651. mod_gzip_printf( "%s: gzp->compression_format = %d\n",cn,gzp->compression_format);
  3652. mod_gzip_printf( "%s: gzp->input_ismem = %d\n", cn,gzp->input_ismem);
  3653. mod_gzip_printf( "%s: gzp->output_ismem = %d\n", cn,gzp->output_ismem);
  3654. mod_gzip_printf( "%s: gzp->input_filename = [%s]\n",cn,gzp->input_filename);
  3655. mod_gzip_printf( "%s: gzp->output_filename = [%s]\n",cn,gzp->output_filename);
  3656. mod_gzip_printf( "%s: Call gzp_main()...\n",cn);
  3657. #endif
  3658. rc = gzp_main( gzp ); /* Perform the compression... */
  3659. output_size = (long) gzp->bytes_out;
  3660. #ifdef MOD_GZIP_DEBUG1
  3661. mod_gzip_printf( "%s: Back gzp_main()...\n",cn);
  3662. mod_gzip_printf( "%s: input_size = %ld\n",cn,(long)input_size);
  3663. mod_gzip_printf( "%s: output_size = %ld\n",cn,(long)output_size);
  3664. mod_gzip_printf( "%s: gzp->bytes_out = %ld\n",cn,(long)gzp->bytes_out);
  3665. mod_gzip_printf( "%s: Bytes saved = %ld\n",cn,
  3666. (long)input_size-gzp->bytes_out );
  3667. #endif
  3668. /* Compute the compresion ratio for access.log and */
  3669. /* internal statistics update... */
  3670. compression_ratio = 0; /* Reset */
  3671. /* Prevent 'Divide by zero' error... */
  3672. if ( ( input_size > 0 ) &&
  3673. ( output_size > 0 ) )
  3674. {
  3675. compression_ratio = 100 - (int)
  3676. ( output_size * 100L / input_size );
  3677. }
  3678. #ifdef MOD_GZIP_DEBUG1
  3679. mod_gzip_printf( "%s: Compression ratio = %ld percent\n",cn,
  3680. (long) compression_ratio );
  3681. #endif
  3682. /*
  3683. * Update the logs with output size information
  3684. * as soon as it is known in case there was an
  3685. * error or we must DECLINE. At least the logs
  3686. * will then show the sizes and the results.
  3687. */
  3688. #ifdef MOD_GZIP_USES_APACHE_LOGS
  3689. sprintf( log_info,"%d", (int) output_size );
  3690. ap_table_setn( r->notes,"mod_gzip_output_size",ap_pstrdup(r->pool,log_info));
  3691. sprintf( log_info,"%d", (int) compression_ratio );
  3692. ap_table_setn( r->notes,"mod_gzip_compression_ratio",ap_pstrdup(r->pool,log_info));
  3693. #endif /* MOD_GZIP_USES_APACHE_LOGS */
  3694. /*
  3695. * Evaluate the compression result(s)...
  3696. *
  3697. * If the compression pass failed then the output length
  3698. * will be ZERO bytes...
  3699. */
  3700. if ( output_size < 1 )
  3701. {
  3702. #ifdef MOD_GZIP_DEBUG1
  3703. mod_gzip_printf( "%s: Compressed version has no length.\n",cn);
  3704. mod_gzip_printf( "%s: Sending the original version uncompressed...\n",cn);
  3705. #endif
  3706. finalize_stats = 0; /* Don't update stats again */
  3707. if ( r->server->loglevel == APLOG_DEBUG )
  3708. {
  3709. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  3710. "mod_gzip: gzp_main(ERR): r->uri=[%s] input_size=%ld output_size=%ld gzp->output_filename=[%s]",
  3711. r->uri,(long)input_size,(long)output_size,gzp->output_filename);
  3712. }
  3713. /*
  3714. * NOTE: It's perfectly possible that we have made it all
  3715. * the way to here and the straight execution of the
  3716. * compressor is the first time there has been a check for
  3717. * the actual existence of the requested object. This will
  3718. * be especially true for STATIC requests.
  3719. *
  3720. * The compressor itself will fail if/when it can't find
  3721. * the input target so 'DECLINED:NO_O_LEN' could simply
  3722. * means the file was not found. In these cases the Apache
  3723. * logs should also contain the correct '404 Not Found' code.
  3724. */
  3725. #ifdef MOD_GZIP_USES_APACHE_LOGS
  3726. /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */
  3727. ap_table_setn(
  3728. r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:NO_O_LEN"));
  3729. #endif /* MOD_GZIP_USES_APACHE_LOGS */
  3730. /* Is it OK to DECLINE?... */
  3731. if ( nodecline ) /* We have been told NOT to DECLINE... */
  3732. {
  3733. #ifdef MOD_GZIP_DEBUG1
  3734. mod_gzip_printf( "%s: DECLINE is NOT allowed...\n",cn);
  3735. #endif
  3736. /* Just set the output control skid */
  3737. /* to send the real input data... */
  3738. output_size = input_size;
  3739. if ( source_is_a_file ) /* Source is a workfile... */
  3740. {
  3741. strcpy( gzp->output_filename, source );
  3742. gzp->output_ismem = 0; /* Output is a disk file */
  3743. gz1_ismem_obuf = 0; /* Make sure this is NULL */
  3744. gzp->output_ismem_obuf = 0; /* Not used for this method */
  3745. gzp->output_ismem_obuflen = 0; /* Not used for this method */
  3746. ifh = mod_gzip_open_output_file( r, gzp->output_filename, &rc );
  3747. if ( !ifh ) /* We really must DECLINE... */
  3748. {
  3749. return( rc );
  3750. }
  3751. }
  3752. else /* Source is just a memory buffer... */
  3753. {
  3754. gzp->output_ismem = 1;
  3755. gz1_ismem_obuf = source;
  3756. }
  3757. #ifdef MOD_GZIP_DEBUG1
  3758. mod_gzip_printf( "%s: Advancing directly to transmit phase...\n",cn);
  3759. #endif
  3760. goto mod_gzip_encode_and_transmit_send_start; /* Jump */
  3761. }
  3762. else /* It's OK to DECLINE the processing... */
  3763. {
  3764. #ifdef MOD_GZIP_DEBUG1
  3765. mod_gzip_printf( "%s: DECLINE is allowed...\n",cn);
  3766. mod_gzip_printf( "%s: Exit > return( DECLINED ) >\n",cn);
  3767. #endif
  3768. /* Free the local memory buffer allocation ( if necessary )... */
  3769. if ( gz1_ismem_obuf )
  3770. {
  3771. /* The pointer may have been 'borrowed' and was */
  3772. /* not actually 'allocated' so check the flag... */
  3773. if ( gz1_ismem_obuf_was_allocated )
  3774. {
  3775. free( gz1_ismem_obuf );
  3776. gz1_ismem_obuf = 0;
  3777. gz1_ismem_obuf_was_allocated = 0;
  3778. }/* End 'if( gz1_ismem_obuf_was_allocated )' */
  3779. }/* End 'if( gz1_ismem_obuf )' */
  3780. /* Return... */
  3781. return DECLINED;
  3782. }
  3783. }/* End 'if( output_size < 1 )' */
  3784. /*
  3785. * If we reach this point then the compressed version has
  3786. * a valid length. Time to see if it it's worth sending.
  3787. *
  3788. * If the original source is SMALLER than the COMPRESSED
  3789. * version ( not likely but possible with LZ77 ) then
  3790. * just punt and send the original source...
  3791. */
  3792. if ( output_size > input_size )
  3793. {
  3794. #ifdef MOD_GZIP_DEBUG1
  3795. mod_gzip_printf( "%s: Compressed version is larger than original.\n",cn);
  3796. mod_gzip_printf( "%s: Sending the original version uncompressed...\n",cn);
  3797. #endif
  3798. finalize_stats = 0; /* Don't update stats again */
  3799. #ifdef MOD_GZIP_USES_APACHE_LOGS
  3800. /* Each 'DECLINE' condition provides a short ':WHYTAG' for logs */
  3801. ap_table_setn(
  3802. r->notes,"mod_gzip_result",ap_pstrdup(r->pool,"DECLINED:ORIGINAL_SMALLER"));
  3803. #endif /* MOD_GZIP_USES_APACHE_LOGS */
  3804. /* Is it OK to DECLINE?... */
  3805. if ( nodecline ) /* We have been told NOT to DECLINE... */
  3806. {
  3807. #ifdef MOD_GZIP_DEBUG1
  3808. mod_gzip_printf( "%s: DECLINE is NOT allowed...\n",cn);
  3809. #endif
  3810. /* Just set the output control skid */
  3811. /* to send the real input data... */
  3812. output_size = input_size;
  3813. if ( source_is_a_file ) /* Source is a workfile... */
  3814. {
  3815. strcpy( gzp->output_filename, source );
  3816. gzp->output_ismem = 0; /* Output is a disk file */
  3817. gz1_ismem_obuf = 0; /* Make sure this is NULL */
  3818. gzp->output_ismem_obuf = 0; /* Not used for this method */
  3819. gzp->output_ismem_obuflen = 0; /* Not used for this method */
  3820. ifh = mod_gzip_open_output_file( r, gzp->output_filename, &rc );
  3821. if ( !ifh ) /* We really must DECLINE... */
  3822. {
  3823. return( rc );
  3824. }
  3825. }
  3826. else /* Source is just a memory buffer... */
  3827. {
  3828. gzp->output_ismem = 1;
  3829. gz1_ismem_obuf = source;
  3830. gz1_ismem_obuf_was_allocated = 0; /* No 'free' is required */
  3831. }
  3832. #ifdef MOD_GZIP_DEBUG1
  3833. mod_gzip_printf( "%s: Advancing directly to transmit phase...\n",cn);
  3834. #endif
  3835. goto mod_gzip_encode_and_transmit_send_start; /* Jump */
  3836. }
  3837. else /* It's OK to DECLINE the processing... */
  3838. {
  3839. #ifdef MOD_GZIP_DEBUG1
  3840. mod_gzip_printf( "%s: DECLINE is allowed...\n",cn);
  3841. mod_gzip_printf( "%s: Exit > return( DECLINED ) >\n",cn);
  3842. #endif
  3843. /* Free the local memory buffer allocation ( if necessary )... */
  3844. if ( gz1_ismem_obuf )
  3845. {
  3846. /* The pointer may have been 'borrowed' and was */
  3847. /* not actually 'allocated' so check the flag... */
  3848. if ( gz1_ismem_obuf_was_allocated )
  3849. {
  3850. free( gz1_ismem_obuf );
  3851. gz1_ismem_obuf = 0;
  3852. gz1_ismem_obuf_was_allocated = 0;
  3853. }/* End 'if( gz1_ismem_obuf_was_allocated )' */
  3854. }/* End 'if( gz1_ismem_obuf )' */
  3855. /* Return... */
  3856. return DECLINED;
  3857. }
  3858. }
  3859. else /* Compressed version is smaller than original... */
  3860. {
  3861. #ifdef MOD_GZIP_DEBUG1
  3862. mod_gzip_printf( "%s: Compressed version is smaller than original.\n",cn);
  3863. mod_gzip_printf( "%s: Sending the compressed version...\n",cn);
  3864. #endif
  3865. }
  3866. /*
  3867. * If an output workfile was used then make SURE it is going
  3868. * to reopen before beginning the transmit phase.
  3869. *
  3870. * If we begin the transmit phase before discovering a problem
  3871. * re-opening the workfile then we have lost the chance to
  3872. * DECLINE the processing and allow the default logic to
  3873. * deliver the requested object.
  3874. *
  3875. * This only matters for 'static' files or times when the
  3876. * 'nodecline' flag is FALSE and it is actually OK to DECLINE.
  3877. */
  3878. if ( !gzp->output_ismem ) /* Workfile was used... */
  3879. {
  3880. #ifdef MOD_GZIP_DEBUG1
  3881. mod_gzip_printf( "%s: Opening compressed output file [%s]...\n",
  3882. cn, gzp->output_filename );
  3883. #endif
  3884. ifh = mod_gzip_open_output_file( r, gzp->output_filename, &rc );
  3885. if ( !ifh ) /* The file failed to open... */
  3886. {
  3887. #ifdef MOD_GZIP_DEBUG1
  3888. mod_gzip_printf( "%s: ERROR: Cannot re-open file [%s]\n",
  3889. cn,gzp->output_filename);
  3890. #endif
  3891. /* We really must DECLINE... */
  3892. /* Logs have already been updated... */
  3893. #ifdef MOD_GZIP_DEBUG1
  3894. mod_gzip_printf( "%s: Exit > return( DECLINED ) >\n",cn);
  3895. #endif
  3896. return DECLINED;
  3897. }/* End 'if ( !ifh )' */
  3898. #ifdef MOD_GZIP_DEBUG1
  3899. mod_gzip_printf( "%s: Workile re-opened OK...\n",cn);
  3900. #endif
  3901. }/* End 'if ( !gzp->output_ismem )' */
  3902. /*
  3903. * IMPORTANT
  3904. *
  3905. * If we have made it to here then all is well and only
  3906. * now can we set the encoding for this response...
  3907. *
  3908. * We must do this 'above' any jump points that might
  3909. * be sending the 'untouched' data or the browser will
  3910. * get confused regarding the actual content.
  3911. */
  3912. r->content_encoding = actual_content_encoding_name;
  3913. #ifdef MOD_GZIP_DEBUG1
  3914. mod_gzip_printf( "%s: r->content_encoding is now [%s]\n",
  3915. cn, r->content_encoding );
  3916. #endif
  3917. /*
  3918. * Begin the transmission phase...
  3919. *
  3920. * Even if the 'nodecline' flag is TRUE if we encounter
  3921. * any fatal errors at this point we must 'DECLINE'.
  3922. */
  3923. mod_gzip_encode_and_transmit_send_start: ; /* <<-- Jump point */
  3924. #ifdef MOD_GZIP_DEBUG1
  3925. mod_gzip_printf( "%s: Starting transmit phase...\n",cn);
  3926. #endif
  3927. /*
  3928. * We are ready to send content so update the "Content-length:"
  3929. * response field and send the HTTP header. We don't need to
  3930. * worry about setting the "Content-type:" field since we are
  3931. * simply accepting the value that was passed to us as indicated
  3932. * by the inbound r->content_type string. The "Content-type:"
  3933. * field never changes even when multiple encodings have been
  3934. * applied to the content itself.
  3935. *
  3936. * This version does not make any attempt to use 'Chunked'
  3937. * transfer encoding since there are so many user agents that
  3938. * do not support it and when Content-length is known prior
  3939. * to header transmission ( as is always the case with this
  3940. * code ) then there is simply no reason to even think about
  3941. * using the slower and more problematic 'Chunked' encoding
  3942. * transfer method.
  3943. */
  3944. /*
  3945. * Set relevant outbound response header fields...
  3946. *
  3947. * Be sure to call ap_update_mtime() before calling
  3948. * ap_set_last_modified() to be sure the 'current'
  3949. * time is actually updated in outbound response header.
  3950. */
  3951. ap_update_mtime( r, r->finfo.st_mtime );
  3952. ap_set_last_modified(r);
  3953. ap_set_etag(r);
  3954. ap_table_setn(r->headers_out, "Accept-Ranges", "bytes");
  3955. /*
  3956. * Start a timer for this transaction...
  3957. */
  3958. ap_soft_timeout( "mod_gzip: Encoded data transmit", r );
  3959. /*
  3960. * Return the length of the compressed output in
  3961. * the response header.
  3962. *
  3963. * See notes above about there never being a requirement
  3964. * to use 'Chunked' transfer encoding since the content
  3965. * length is always 'known' prior to transmission.
  3966. */
  3967. sprintf( content_length, "%ld", output_size );
  3968. ap_table_set (r->headers_out, "Content-Length", content_length );
  3969. #ifdef MOD_GZIP_DEBUG1
  3970. mod_gzip_printf( "%s: output_size = %ld\n",cn,(long)output_size);
  3971. mod_gzip_printf( "%s: r->content_type = [%s]\n",cn,r->content_type);
  3972. mod_gzip_printf( "%s: Call ap_send_http_header()...\n",cn);
  3973. #endif
  3974. ap_send_http_header(r);
  3975. #ifdef MOD_GZIP_DEBUG1
  3976. mod_gzip_printf( "%s: Back ap_send_http_header()...\n",cn);
  3977. #endif
  3978. /*
  3979. * Send the response...
  3980. *
  3981. * If the requested object was small enough to fit into
  3982. * our special in-memory output space then send the result
  3983. * directly from memory. If the requested object exceeded
  3984. * the minimum size for in-memory compression then an output
  3985. * file was used so re-open and send the results file...
  3986. */
  3987. if ( gzp->output_ismem )
  3988. {
  3989. /* Send the in-memory output buffer... */
  3990. #ifdef MOD_GZIP_DEBUG1
  3991. mod_gzip_printf( "%s: Sending the in-memory output buffer...\n",cn);
  3992. mod_gzip_printf( "%s: output_size = %ld\n",cn,(long)output_size);
  3993. /* Turn this 'on' for VERY verbose diagnostics...
  3994. #define MOD_GZIP_DUMP_JUST_BEFORE_SENDING
  3995. */
  3996. #ifdef MOD_GZIP_DUMP_JUST_BEFORE_SENDING
  3997. mod_gzip_hexdump( gz1_ismem_obuf, output_size );
  3998. #endif
  3999. #endif /* MOD_GZIP_DEBUG1 */
  4000. /* This module can use either ap_send_mmap() or ap_rwrite()... */
  4001. #ifdef MOD_GZIP_USES_AP_SEND_MMAP
  4002. /* Use ap_send_mmap() call to send the data... */
  4003. #ifdef MOD_GZIP_DEBUG1
  4004. mod_gzip_printf( "%s: Call ap_send_mmap( gz1_ismem_obuf, bytes=%ld )...\n",
  4005. cn, (long)output_size );
  4006. #endif
  4007. ap_send_mmap( gz1_ismem_obuf, r, 0, output_size );
  4008. #ifdef MOD_GZIP_DEBUG1
  4009. mod_gzip_printf( "%s: Back ap_send_mmap( gz1_ismem_obuf, bytes=%ld )...\n",
  4010. cn, (long)output_size );
  4011. #endif
  4012. #else /* !MOD_GZIP_USES_AP_SEND_MMAP */
  4013. /* Use ap_rwrite() call to send the data... */
  4014. #ifdef MOD_GZIP_DEBUG1
  4015. mod_gzip_printf( "%s: Call ap_rwrite( gz1_ismem_obuf, bytes=%ld )...\n",
  4016. cn, (long)output_size );
  4017. #endif
  4018. ap_rwrite( gz1_ismem_obuf, output_size, r );
  4019. #ifdef MOD_GZIP_DEBUG1
  4020. mod_gzip_printf( "%s: Back ap_rwrite( gz1_ismem_obuf, bytes=%ld )...\n",
  4021. cn, (long)output_size );
  4022. #endif
  4023. #endif /* MOD_GZIP_USES_AP_SEND_MMAP */
  4024. /* Stop the timer... */
  4025. #ifdef MOD_GZIP_DEBUG1
  4026. mod_gzip_printf( "%s: Call ap_kill_timeout()...\n",cn);
  4027. #endif
  4028. ap_kill_timeout(r);
  4029. #ifdef MOD_GZIP_DEBUG1
  4030. mod_gzip_printf( "%s: Back ap_kill_timeout()...\n",cn);
  4031. #endif
  4032. /* Free the local memory buffer allocation ( if necessary )... */
  4033. if ( gz1_ismem_obuf )
  4034. {
  4035. /* The pointer may have been 'borrowed' and was */
  4036. /* not actually 'allocated' so check the flag... */
  4037. if ( gz1_ismem_obuf_was_allocated )
  4038. {
  4039. free( gz1_ismem_obuf );
  4040. gz1_ismem_obuf = 0;
  4041. gz1_ismem_obuf_was_allocated = 0;
  4042. }/* End 'if( gz1_ismem_obuf_was_allocated )' */
  4043. }/* End 'if( gz1_ismem_obuf )' */
  4044. }
  4045. else /* Output workfile was used so send the contents... */
  4046. {
  4047. /*
  4048. * NOTE: The workfile was already 're-opened' up above
  4049. * before the transmit phase began so that we still had
  4050. * the chance to return DECLINED if, for some reason, the
  4051. * workfile could not be re-opened.
  4052. */
  4053. #ifdef MOD_GZIP_DEBUG1
  4054. mod_gzip_printf( "%s: sizeof( tmp ) = %d\n",cn,sizeof(tmp));
  4055. mod_gzip_printf( "%s: Transmit buffer size = %d\n",cn,sizeof(tmp));
  4056. mod_gzip_printf( "%s: Sending compressed output file...\n",cn);
  4057. #endif
  4058. for (;;)
  4059. {
  4060. bytesread = fread( tmp, 1, sizeof( tmp ), ifh );
  4061. #ifdef MOD_GZIP_DEBUG1
  4062. mod_gzip_printf( "%s: Back fread(): bytesread=%d\n",cn,bytesread);
  4063. #endif
  4064. if ( bytesread < 1 ) break; /* File is exhausted... We are done...*/
  4065. /* This module can use either ap_send_mmap() or ap_rwrite()... */
  4066. #ifdef MOD_GZIP_USES_AP_SEND_MMAP
  4067. /* Use ap_send_mmap() call to send the data... */
  4068. ap_send_mmap( tmp, r, 0, bytesread );
  4069. #else /* !MOD_GZIP_USES_AP_SEND_MMAP */
  4070. /* Use ap_rwrite() call to send the data... */
  4071. ap_rwrite( tmp, bytesread, r );
  4072. #endif /* MOD_GZIP_USES_AP_SEND_MMAP */
  4073. }
  4074. #ifdef MOD_GZIP_DEBUG1
  4075. mod_gzip_printf( "%s: Done Sending compressed output file...\n",cn);
  4076. mod_gzip_printf( "%s: Closing workfile [%s]...\n",
  4077. cn, gzp->output_filename );
  4078. #endif
  4079. fclose( ifh ); /* Close the input file */
  4080. /* Stop the timer before attempting to delete the workfile... */
  4081. #ifdef MOD_GZIP_DEBUG1
  4082. mod_gzip_printf( "%s: Call ap_kill_timeout()...\n",cn);
  4083. #endif
  4084. ap_kill_timeout(r);
  4085. #ifdef MOD_GZIP_DEBUG1
  4086. mod_gzip_printf( "%s: Back ap_kill_timeout()...\n",cn);
  4087. #endif
  4088. /* Delete the workfile if 'keep' flag is OFF... */
  4089. #ifdef MOD_GZIP_DEBUG1
  4090. mod_gzip_printf( "%s: conf->keep_workfiles = %d\n",
  4091. cn, conf->keep_workfiles );
  4092. #endif
  4093. if ( !conf->keep_workfiles ) /* Default is OFF */
  4094. {
  4095. #ifdef MOD_GZIP_DEBUG1
  4096. mod_gzip_printf( "%s: Deleting workfile [%s]...\n",
  4097. cn, gzp->output_filename );
  4098. #endif
  4099. #ifdef WIN32
  4100. DeleteFile( gzp->output_filename );
  4101. #else /* !WIN32 */
  4102. unlink( gzp->output_filename );
  4103. #endif /* WIN32 */
  4104. }
  4105. else /* Keep all work files... */
  4106. {
  4107. #ifdef MOD_GZIP_DEBUG1
  4108. mod_gzip_printf( "%s: Keeping workfile [%s]...\n",
  4109. cn, gzp->output_filename );
  4110. #endif
  4111. }
  4112. }/* End 'else' that sends compressed workfile */
  4113. /*
  4114. * The compressed object has been sent...
  4115. */
  4116. #ifdef MOD_GZIP_USES_APACHE_LOGS
  4117. if ( finalize_stats )
  4118. {
  4119. sprintf( log_info,"%d", (int) output_size );
  4120. ap_table_setn( r->notes,"mod_gzip_output_size",ap_pstrdup(r->pool,log_info));
  4121. sprintf( log_info,"%d", (int) compression_ratio );
  4122. ap_table_setn( r->notes,"mod_gzip_compression_ratio",ap_pstrdup(r->pool,log_info));
  4123. }
  4124. #endif /* MOD_GZIP_USES_APACHE_LOGS */
  4125. if ( r->server->loglevel == APLOG_DEBUG )
  4126. {
  4127. /*
  4128. * If LogLevel is 'debug' then show the compression results
  4129. * in the log(s)...
  4130. */
  4131. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  4132. "mod_gzip: r->uri=[%s] OK: Bytes In:%ld Out:%ld Compression: %ld pct.",
  4133. r->uri,
  4134. (long) input_size,
  4135. (long) output_size,
  4136. (long) compression_ratio
  4137. );
  4138. }/* End 'if( r->server->loglevel == APLOG_DEBUG )' */
  4139. /*
  4140. * Return OK to the Server to indicate SUCCESS...
  4141. */
  4142. #ifdef MOD_GZIP_DEBUG1
  4143. mod_gzip_printf( "%s: Exit > return( OK ) >\n",cn);
  4144. #endif
  4145. return OK;
  4146. }/* End of mod_gzip_encode_and_transmit() */
  4147. int mod_gzip_ismatch( char *s1, char *s2, int len1, int haswilds )
  4148. {
  4149. /* Behaves just like strncmp() but IGNORES differences */
  4150. /* between FORWARD or BACKWARD slashes in a STRING, allows */
  4151. /* wildcard matches, and can ignore length value. */
  4152. /* It uses pointers and is faster than using lib calls. */
  4153. /* Unlike strncmp() this routine returns TRUE (1) if the */
  4154. /* strings match and FALSE (0) if they do not... */
  4155. int i;
  4156. int l1;
  4157. int l2;
  4158. int distance;
  4159. char ch1;
  4160. char ch2;
  4161. /* WARNING! We MUST have a check for 'NULL' on the pointer(s) */
  4162. /* themselves or we might GP */
  4163. if ( ( s1 == 0 ) || ( s2 == 0 ) )
  4164. {
  4165. /* SAFETY! If pointer itself if NULL */
  4166. /* don't enter LOOP... */
  4167. return( 0 ); /* Return FALSE for NOMATCH... */
  4168. }
  4169. distance = len1; /* Default to value passed... */
  4170. /* If no length was given then the 2 strings must already */
  4171. /* have the same length or this is a 'no match'... */
  4172. /* Exception to this is if wildcards are present. */
  4173. if ( len1 == 0 )
  4174. {
  4175. l1 = strlen( s1 );
  4176. l2 = strlen( s2 );
  4177. /* If either string had a valid pointer but is EMPTY */
  4178. /* then this is an automatic 'no match'... */
  4179. if ((l1==0)||(l2==0))
  4180. {
  4181. return( 0 ); /* Return FALSE for NOMATCH... */
  4182. }
  4183. if ( l1 != l2 )
  4184. {
  4185. if ( haswilds == 0 )
  4186. {
  4187. return( 0 ); /* Return FALSE for NOMATCH... */
  4188. }
  4189. }
  4190. /* If the lengths ARE equal then this is a possible */
  4191. /* match. Use the smaller of the 2 values for scan...*/
  4192. if ( l1 < l2 ) distance = l1;
  4193. else distance = l2;
  4194. }
  4195. /* Final check... if distance is still 0 then this */
  4196. /* is an automatic 'no match'... */
  4197. if ( distance == 0 )
  4198. {
  4199. return( 0 ); /* Return FALSE for NOMATCH... */
  4200. }
  4201. /* Do the deed... */
  4202. for ( i=0; i<distance; i++ )
  4203. {
  4204. /* If we encounter a null in either string before we */
  4205. /* have 'gone the distance' then the strings don't match... */
  4206. if ( ( *s1 == 0 ) || ( *s2 == 0 ) ) return( 0 ); /* No match! */
  4207. ch1 = *s1;
  4208. ch2 = *s2;
  4209. if ( ( ch1 == '*' ) || ( ch2 == '*' ) )
  4210. {
  4211. /* If we are still here and wildcards are allowed */
  4212. /* then the first one seen in either string causes */
  4213. /* us to return SUCCESS... */
  4214. if ( haswilds )
  4215. {
  4216. return( 1 ); /* Wildcard match was OK this time... */
  4217. }
  4218. }
  4219. if ( ch1 == '/' ) ch1 = '\\';
  4220. if ( ch2 == '/' ) ch2 = '\\';
  4221. if ( ch1 != ch2 ) return( 0 ); /* No match! */
  4222. s1++;
  4223. s2++;
  4224. }/* End 'i' loop */
  4225. /* If we make it to here then everything MATCHED! */
  4226. return( 1 ); /* MATCH! */
  4227. }/* End mod_gzip_ismatch() */
  4228. int mod_gzip_get_action_flag( request_rec *r, mod_gzip_conf *mgc )
  4229. {
  4230. int x = 0;
  4231. int pass = 0;
  4232. int clen = 0;
  4233. int hlen = 0;
  4234. int flen = 0;
  4235. int pass_result = 0;
  4236. int filter_value = 0;
  4237. int item_is_included = 0;
  4238. int item_is_excluded = 0;
  4239. int action_flag = 0;
  4240. int this_type = 0;
  4241. int this_action = 0;
  4242. char *this_name = 0;
  4243. char *file_extension = 0;
  4244. int file_extension_len = 0;
  4245. char *p1 = 0;
  4246. #ifdef MOD_GZIP_DEBUG1
  4247. char cn[]="mod_gzip_get_action_flag()";
  4248. #endif
  4249. /*
  4250. * Start...
  4251. */
  4252. if ( r->content_type ) clen = strlen( r->content_type );
  4253. if ( r->handler ) hlen = strlen( r->handler );
  4254. if ( r->filename )
  4255. {
  4256. flen = strlen( r->filename );
  4257. p1 = r->filename;
  4258. while(*p1!=0){if (*p1=='.') file_extension=p1; p1++;}
  4259. if ( file_extension ) file_extension_len = strlen( file_extension );
  4260. }
  4261. #ifdef MOD_GZIP_DEBUG1
  4262. mod_gzip_printf( "%s: Entry...\n",cn);
  4263. mod_gzip_printf( "%s: r->content_type = [%s]\n",cn,r->content_type);
  4264. mod_gzip_printf( "%s: clen = %d\n", cn,clen);
  4265. mod_gzip_printf( "%s: r->handler = [%s]\n",cn,r->handler);
  4266. mod_gzip_printf( "%s: hlen = %d\n", cn,hlen);
  4267. mod_gzip_printf( "%s: r->filename = [%s]\n",cn,r->filename);
  4268. mod_gzip_printf( "%s: flen = %d\n", cn,flen);
  4269. mod_gzip_printf( "%s: file_extension = [%s]\n",cn,file_extension);
  4270. mod_gzip_printf( "%s: file_extension_len = %d\n", cn,file_extension_len);
  4271. #endif /* MOD_GZIP_DEBUG1 */
  4272. /*
  4273. * Sanity checks...
  4274. */
  4275. if ( ( hlen == 0 ) && ( clen == 0 ) )
  4276. {
  4277. /*
  4278. * If the header analysis and/or negotiation phase has
  4279. * determined this to be a CGI script then the r->content_type
  4280. * field will be (null) but r->handler will contain "cgi-script".
  4281. * or "php-script" or the like.
  4282. *
  4283. * If the analysis has determined this is a static file
  4284. * then r->handler will be (null) but the r->content_type
  4285. * field will be "text/html" or "text/plain" or whatever.
  4286. *
  4287. * Both the r->content_type field and the r->handler
  4288. * field are empty. Ignore this one...
  4289. */
  4290. #ifdef MOD_GZIP_DEBUG1
  4291. mod_gzip_printf( "%s: Both hlen and clen are ZERO...\n",cn);
  4292. mod_gzip_printf( "%s: Exit > return( MOD_GZIP_IMAP_DECLINED1 ) >\n",cn);
  4293. #endif
  4294. if ( r->server->loglevel == APLOG_DEBUG )
  4295. {
  4296. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  4297. "mod_gzip: There is no valid r->handler or r->content_length ");
  4298. }
  4299. return( MOD_GZIP_IMAP_DECLINED1 );
  4300. }
  4301. /*
  4302. * Perform 2 passes at the Include/Exclude list...
  4303. *
  4304. * The first pass is the higher-priority EXCLUSION check.
  4305. * The second pass is the lower-priority INCLUSION check.
  4306. */
  4307. for ( pass=0; pass<2; pass++ )
  4308. {
  4309. pass_result = 0; /* Reset result */
  4310. if ( pass == 0 ) /* EXCLUSION CHECK */
  4311. {
  4312. filter_value = 0;
  4313. #ifdef MOD_GZIP_DEBUG1
  4314. mod_gzip_printf( "%s: EXCLUSION CHECK...\n",cn);
  4315. #endif
  4316. }
  4317. else if ( pass == 1 ) /* INCLUSION CHECK */
  4318. {
  4319. filter_value = 1;
  4320. #ifdef MOD_GZIP_DEBUG1
  4321. mod_gzip_printf( "%s: INCLUSION CHECK...\n",cn);
  4322. #endif
  4323. }
  4324. #ifdef MOD_GZIP_DEBUG1
  4325. mod_gzip_printf( "%s: pass = %d\n", cn, pass );
  4326. mod_gzip_printf( "%s: filter_value = %d\n", cn, filter_value );
  4327. mod_gzip_printf( "%s: mgc->imap_total_entries = %d\n", cn,
  4328. (int) mgc->imap_total_entries );
  4329. #endif
  4330. for ( x=0; x<mgc->imap_total_entries; x++ )
  4331. {
  4332. if ( r->server->loglevel == APLOG_DEBUG )
  4333. {
  4334. /* Show the lookups in the Apache ERROR log if DEBUG is on */
  4335. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  4336. "mod_gzip: mgc->imap[%3.3d] = i%2.2d t%4.4d a%4.4d n[%s]",
  4337. x,
  4338. mgc->imap[x].include,
  4339. mgc->imap[x].type,
  4340. mgc->imap[x].action,
  4341. mgc->imap[x].name
  4342. );
  4343. }
  4344. #ifdef MOD_GZIP_DEBUG1
  4345. mod_gzip_printf( "%s: --------------------------------------------\n",cn);
  4346. mod_gzip_printf( "%s: r->handler = [%s]\n",cn,r->handler);
  4347. mod_gzip_printf( "%s: r->content_type = [%s]\n",cn,r->content_type);
  4348. mod_gzip_printf( "%s: r->filename = [%s]\n",cn,r->filename);
  4349. mod_gzip_printf( "%s: file_extension = [%s]\n",cn,file_extension);
  4350. mod_gzip_printf( "%s: mgc->imap[%3.3d].include = %d\n",cn,x,mgc->imap[x].include);
  4351. mod_gzip_printf( "%s: mgc->imap[%3.3d].type = %d\n",cn,x,mgc->imap[x].type);
  4352. if ( mgc->imap[x].type == MOD_GZIP_IMAP_ISMIME )
  4353. {
  4354. mod_gzip_printf( "%s: mgc->imap[%3.3d].type = MOD_GZIP_IMAP_ISMIME\n",cn,x);
  4355. }
  4356. else if ( mgc->imap[x].type == MOD_GZIP_IMAP_ISEXT )
  4357. {
  4358. mod_gzip_printf( "%s: mgc->imap[%3.3d].type = MOD_GZIP_IMAP_ISEXT\n",cn,x);
  4359. }
  4360. else if ( mgc->imap[x].type == MOD_GZIP_IMAP_ISHANDLER )
  4361. {
  4362. mod_gzip_printf( "%s: mgc->imap[%3.3d].type = MOD_GZIP_IMAP_ISHANDLER\n",cn,x);
  4363. }
  4364. else /* Unrecognized item type... */
  4365. {
  4366. mod_gzip_printf( "%s: mgc->imap[%3.3d].type = MOD_GZIP_IMAP_IS??? Unknown type\n",cn,x);
  4367. }
  4368. mod_gzip_printf( "%s: mgc->imap[%3.3d].action = %d\n", cn,x,mgc->imap[x].action);
  4369. if ( mgc->imap[x].action == MOD_GZIP_IMAP_DYNAMIC1 )
  4370. {
  4371. mod_gzip_printf( "%s: mgc->imap[%3.3d].action = MOD_GZIP_IMAP_DYNAMIC1\n",cn,x);
  4372. }
  4373. else if ( mgc->imap[x].action == MOD_GZIP_IMAP_STATIC1 )
  4374. {
  4375. mod_gzip_printf( "%s: mgc->imap[%3.3d].action = MOD_GZIP_IMAP_STATIC1\n",cn,x);
  4376. }
  4377. else /* Unrecognized action type... */
  4378. {
  4379. mod_gzip_printf( "%s: mgc->imap[%3.3d].action = MOD_GZIP_IMAP_??? Unknown action\n",cn,x);
  4380. }
  4381. mod_gzip_printf( "%s: mgc->imap[%3.3d].name = [%s]\n",cn,x,mgc->imap[x].name);
  4382. #endif /* MOD_GZIP_DEBUG1 */
  4383. /* 'filter_value' mirrors 'pass' value for now but this might */
  4384. /* not always be true. First pass is EXCLUDE and second is INCLUDE */
  4385. if ( mgc->imap[x].include == filter_value )
  4386. {
  4387. #ifdef MOD_GZIP_DEBUG1
  4388. mod_gzip_printf( "%s: This record matches filter_value %d\n",
  4389. cn, filter_value );
  4390. mod_gzip_printf( "%s: The record will be checked...\n",cn);
  4391. #endif
  4392. /*
  4393. * Set work values for this record...
  4394. */
  4395. this_type = mgc->imap[x].type;
  4396. this_action = mgc->imap[x].action;
  4397. this_name = mgc->imap[x].name;
  4398. /*
  4399. * If the header analysis and/or negotiation phase has
  4400. * determined this to be a CGI script then the r->content_type
  4401. * field will be (null) but r->handler will contain "cgi-script".
  4402. *
  4403. * If the analysis has determined this is a static file
  4404. * then r->handler will be (null) but the r->content_type
  4405. * field will be "text/html" or "text/plain" or whatever.
  4406. */
  4407. if ( hlen > 0 ) /* r->handler field has a value... */
  4408. {
  4409. #ifdef MOD_GZIP_DEBUG1
  4410. mod_gzip_printf( "%s: hlen has value...\n",cn);
  4411. #endif
  4412. if ( this_type == MOD_GZIP_IMAP_ISHANDLER )
  4413. {
  4414. #ifdef MOD_GZIP_DEBUG1
  4415. mod_gzip_printf( "%s: this_type = ISHANDLER\n",cn);
  4416. mod_gzip_printf( "%s: Call mod_gzip_ismatch(%s,%s,0,0)...\n",
  4417. cn, this_name, r->handler );
  4418. #endif
  4419. /* mod_gzip_ismatch()... */
  4420. /* The 2 strings must match exactly so */
  4421. /* pass '0' for parm 3... */
  4422. /* Wildcard matches are not allowed for */
  4423. /* handler strings like 'cgi-script' so */
  4424. /* Fourth parm should be 0.. */
  4425. if ( mod_gzip_ismatch(
  4426. this_name, (char *)r->handler,0,0) )
  4427. {
  4428. pass_result = 1; /* We found a match */
  4429. action_flag = this_action; /* What to do */
  4430. break; /* Stop now */
  4431. }
  4432. }/* End 'if ( this_type == MOD_GZIP_IMAP_ISHANDLER )' */
  4433. }/* End 'if( hlen > 0 )' */
  4434. if ( clen > 0 ) /* r->content_type field has a value... */
  4435. {
  4436. #ifdef MOD_GZIP_DEBUG1
  4437. mod_gzip_printf( "%s: clen has value...\n",cn);
  4438. #endif
  4439. if ( this_type == MOD_GZIP_IMAP_ISMIME )
  4440. {
  4441. #ifdef MOD_GZIP_DEBUG1
  4442. mod_gzip_printf( "%s: this_type = ISMIME\n",cn);
  4443. mod_gzip_printf( "%s: Wildcards matches are OK for MIME types.\n",cn);
  4444. mod_gzip_printf( "%s: Call mod_gzip_ismatch(%s,%s,0,1)...\n",
  4445. cn, this_name, r->content_type );
  4446. #endif
  4447. /* mod_gzip_ismatch()... */
  4448. /* Wildcard matches are ALLOWED for */
  4449. /* MIME type strings like 'cgi-script' */
  4450. /* so fourth parm should be 1... */
  4451. if ( mod_gzip_ismatch(
  4452. this_name, (char *)r->content_type, 0, 1 ) )
  4453. {
  4454. pass_result = 1; /* We found a match */
  4455. action_flag = this_action; /* What to do */
  4456. break; /* Stop now */
  4457. }
  4458. }/* End 'if ( this_type == MOD_GZIP_IMAP_ISMIME )' */
  4459. }/* End 'if( clen > 0 )' */
  4460. if ( flen > 0 ) /* r->filename field has a value... */
  4461. {
  4462. #ifdef MOD_GZIP_DEBUG1
  4463. mod_gzip_printf( "%s: flen has value...\n",cn);
  4464. #endif
  4465. if ( this_type == MOD_GZIP_IMAP_ISEXT )
  4466. {
  4467. #ifdef MOD_GZIP_DEBUG1
  4468. mod_gzip_printf( "%s: this_type = ISEXT\n",cn);
  4469. #endif
  4470. if ( file_extension_len > 0 ) /* There is a file extension */
  4471. {
  4472. #ifdef MOD_GZIP_DEBUG1
  4473. mod_gzip_printf( "%s: file_extension_len has value...\n",cn);
  4474. mod_gzip_printf( "%s: Call mod_gzip_ismatch(%s,%s,0,0)...\n",
  4475. cn, this_name, file_extension );
  4476. #endif
  4477. /* mod_gzip_ismatch()... */
  4478. /* The 2 strings must match exactly so */
  4479. /* pass '0' for parm 3... */
  4480. /* Wildcard matches are not allowed for */
  4481. /* file extensions like '.html' so */
  4482. /* Fourth parm should be 0.. */
  4483. if ( mod_gzip_ismatch(
  4484. this_name, file_extension, 0, 0 ) )
  4485. {
  4486. pass_result = 1; /* We found a match */
  4487. action_flag = this_action; /* What to do */
  4488. break; /* Stop now */
  4489. }
  4490. }/* End 'if( file_extension_len > 0 )' */
  4491. }/* End 'if( this_type == MOD_GZIP)IMAP_ISEXT )' */
  4492. }/* End 'if( flen > 0 )' */
  4493. }/* End 'if ( mgc->imap[x].include == filter )' */
  4494. else /* The record did not match the current 'filter' value... */
  4495. {
  4496. #ifdef MOD_GZIP_DEBUG1
  4497. mod_gzip_printf( "%s: This record does NOT match filter_value %d\n",
  4498. cn, filter_value );
  4499. mod_gzip_printf( "%s: The record has been SKIPPED...\n",cn);
  4500. #endif
  4501. }
  4502. }/* End 'x' loop that looks at 'filtered' records... */
  4503. #ifdef MOD_GZIP_DEBUG1
  4504. mod_gzip_printf( "%s: --------------------------------------------\n",cn);
  4505. mod_gzip_printf( "%s: pass_result = %d\n",cn,pass_result);
  4506. #endif
  4507. if ( pass_result ) /* We are done... */
  4508. {
  4509. if ( pass == 0 ) item_is_excluded = 1;
  4510. else item_is_included = 1;
  4511. break; /* Break out of 'pass' loop now... */
  4512. }
  4513. }/* End 'pass' loop */
  4514. #ifdef MOD_GZIP_DEBUG1
  4515. mod_gzip_printf( "%s: item_is_excluded = %d\n",cn,item_is_excluded);
  4516. mod_gzip_printf( "%s: item_is_included = %d\n",cn,item_is_included);
  4517. mod_gzip_printf( "%s: action_flag = %d\n",cn,action_flag);
  4518. #endif
  4519. if ( item_is_excluded )
  4520. {
  4521. #ifdef MOD_GZIP_DEBUG1
  4522. mod_gzip_printf( "%s: The item is excluded...\n",cn);
  4523. mod_gzip_printf( "%s: Exit > return( MOD_GZIP_IMAP_DECLINED1 ) >\n",cn);
  4524. #endif
  4525. if ( r->server->loglevel == APLOG_DEBUG )
  4526. {
  4527. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  4528. "mod_gzip: This item is EXCLUDED as per httpd.conf");
  4529. }
  4530. return( MOD_GZIP_IMAP_DECLINED1 );
  4531. }
  4532. else if ( item_is_included )
  4533. {
  4534. #ifdef MOD_GZIP_DEBUG1
  4535. mod_gzip_printf( "%s: The item is included...\n",cn);
  4536. mod_gzip_printf( "%s: Exit > return( action_flag = %d ) >\n",cn,action_flag);
  4537. #endif
  4538. if ( r->server->loglevel == APLOG_DEBUG )
  4539. {
  4540. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  4541. "mod_gzip: This item is INCLUDED as per httpd.conf");
  4542. }
  4543. return( action_flag ); /* STATIC1 or DYNAMIC1 */
  4544. }
  4545. /*
  4546. * Default action is to DECLINE processing...
  4547. */
  4548. #ifdef MOD_GZIP_DEBUG1
  4549. mod_gzip_printf( "%s: Exit > return( MOD_GZIP_IMAP_DECLINED1 ) >\n",cn);
  4550. #endif
  4551. if ( r->server->loglevel == APLOG_DEBUG )
  4552. {
  4553. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  4554. "mod_gzip: This item was NOT FOUND in any mod_gzip httpd item record.");
  4555. ap_log_error( "",0,APLOG_NOERRNO|APLOG_DEBUG, r->server,
  4556. "mod_gzip: This item will NOT be processed.");
  4557. }
  4558. return( MOD_GZIP_IMAP_DECLINED1 );
  4559. }/* End of mod_gzip_get_action_flag() */
  4560. /*--------------------------------------------------------------------------*/
  4561. /* ALL SOURCE CODE BELOW THIS POINT IS COMPRESSION SPECIFIC... */
  4562. /*--------------------------------------------------------------------------*/
  4563. #define USE_GATHER
  4564. extern MODULE_VAR_EXPORT int ap_suexec_enabled;
  4565. extern API_EXPORT(void)
  4566. ap_internal_redirect_handler(const char *new_uri, request_rec *);
  4567. long mod_gzip_ap_send_fb(
  4568. BUFF *fb,
  4569. request_rec *r,
  4570. int *final_return_code
  4571. );
  4572. long mod_gzip_ap_send_fb_length(
  4573. BUFF *fb,
  4574. request_rec *r,
  4575. long length,
  4576. int *final_return_code
  4577. );
  4578. #define DEFAULT_LOGBYTES 10385760
  4579. #define DEFAULT_BUFBYTES 1024
  4580. static int mod_gzip_cgi_child(void *child_stuff, child_info *pinfo);
  4581. typedef struct {
  4582. char *logname;
  4583. long logbytes;
  4584. int bufbytes;
  4585. } cgi_server_conf;
  4586. struct mod_gzip_cgi_child_stuff {
  4587. #ifdef TPF
  4588. TPF_FORK_CHILD t;
  4589. #endif
  4590. request_rec *r;
  4591. int nph;
  4592. int debug;
  4593. char *argv0;
  4594. };
  4595. static int is_scriptaliased( request_rec *r )
  4596. {
  4597. const char *t = ap_table_get(r->notes, "alias-forced-type");
  4598. return t && (!strcasecmp(t, "cgi-script"));
  4599. }
  4600. static int log_scripterror(request_rec *r, cgi_server_conf * conf, int ret,
  4601. int show_errno, char *error)
  4602. {
  4603. FILE *f;
  4604. struct stat finfo;
  4605. ap_log_rerror(APLOG_MARK, show_errno|APLOG_ERR, r,
  4606. "%s: %s", error, r->filename);
  4607. if (!conf->logname ||
  4608. ((stat(ap_server_root_relative(r->pool, conf->logname), &finfo) == 0)
  4609. && (finfo.st_size > conf->logbytes)) ||
  4610. ((f = ap_pfopen(r->pool, ap_server_root_relative(r->pool, conf->logname),
  4611. "a")) == NULL)) {
  4612. return ret;
  4613. }
  4614. fprintf(f, "%%%% [%s] %s %s%s%s %s\n", ap_get_time(), r->method, r->uri,
  4615. r->args ? "?" : "", r->args ? r->args : "", r->protocol);
  4616. fprintf(f, "%%%% %d %s\n", ret, r->filename);
  4617. fprintf(f, "%%error\n%s\n", error);
  4618. ap_pfclose(r->pool, f);
  4619. return ret;
  4620. }
  4621. static int log_script(request_rec *r, cgi_server_conf * conf, int ret,
  4622. char *dbuf, const char *sbuf, BUFF *script_in, BUFF *script_err)
  4623. {
  4624. array_header *hdrs_arr = ap_table_elts(r->headers_in);
  4625. table_entry *hdrs = (table_entry *) hdrs_arr->elts;
  4626. char argsbuffer[HUGE_STRING_LEN];
  4627. FILE *f;
  4628. int i;
  4629. struct stat finfo;
  4630. if (!conf->logname ||
  4631. ((stat(ap_server_root_relative(r->pool, conf->logname), &finfo) == 0)
  4632. && (finfo.st_size > conf->logbytes)) ||
  4633. ((f = ap_pfopen(r->pool, ap_server_root_relative(r->pool, conf->logname),
  4634. "a")) == NULL)) {
  4635. while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_in) > 0)
  4636. continue;
  4637. #if defined(WIN32) || defined(NETWARE)
  4638. while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0) {
  4639. ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, r,
  4640. "%s", argsbuffer);
  4641. }
  4642. #else
  4643. while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0)
  4644. continue;
  4645. #endif
  4646. return ret;
  4647. }
  4648. fprintf(f, "%%%% [%s] %s %s%s%s %s\n", ap_get_time(), r->method, r->uri,
  4649. r->args ? "?" : "", r->args ? r->args : "", r->protocol);
  4650. fprintf(f, "%%%% %d %s\n", ret, r->filename);
  4651. fputs("%request\n", f);
  4652. for (i = 0; i < hdrs_arr->nelts; ++i) {
  4653. if (!hdrs[i].key)
  4654. continue;
  4655. fprintf(f, "%s: %s\n", hdrs[i].key, hdrs[i].val);
  4656. }
  4657. if ((r->method_number == M_POST || r->method_number == M_PUT)
  4658. && *dbuf) {
  4659. fprintf(f, "\n%s\n", dbuf);
  4660. }
  4661. fputs("%response\n", f);
  4662. hdrs_arr = ap_table_elts(r->err_headers_out);
  4663. hdrs = (table_entry *) hdrs_arr->elts;
  4664. for (i = 0; i < hdrs_arr->nelts; ++i) {
  4665. if (!hdrs[i].key)
  4666. continue;
  4667. fprintf(f, "%s: %s\n", hdrs[i].key, hdrs[i].val);
  4668. }
  4669. if (sbuf && *sbuf)
  4670. fprintf(f, "%s\n", sbuf);
  4671. if (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_in) > 0) {
  4672. fputs("%stdout\n", f);
  4673. fputs(argsbuffer, f);
  4674. while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_in) > 0)
  4675. fputs(argsbuffer, f);
  4676. fputs("\n", f);
  4677. }
  4678. if (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0) {
  4679. fputs("%stderr\n", f);
  4680. fputs(argsbuffer, f);
  4681. while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0)
  4682. fputs(argsbuffer, f);
  4683. fputs("\n", f);
  4684. }
  4685. ap_bclose( script_in );
  4686. ap_bclose( script_err );
  4687. ap_pfclose(r->pool, f);
  4688. return ret;
  4689. }
  4690. int mod_gzip_cgi_handler( request_rec *r )
  4691. {
  4692. int bytesread;
  4693. int retval, nph, dbpos = 0;
  4694. char *argv0, *dbuf = NULL;
  4695. BUFF *script_out, *script_in, *script_err;
  4696. char argsbuffer[HUGE_STRING_LEN];
  4697. int is_included = !strcmp(r->protocol, "INCLUDED");
  4698. void *sconf = r->server->module_config;
  4699. int final_result = DECLINED;
  4700. #define MOD_GZIP_ENGAGED
  4701. #ifdef MOD_GZIP_ENGAGED
  4702. cgi_server_conf conf_local;
  4703. cgi_server_conf *conf = &conf_local;
  4704. char cgi_logname[]="";
  4705. #else
  4706. cgi_server_conf *conf =
  4707. (cgi_server_conf *) ap_get_module_config(sconf, &cgi_module);
  4708. #endif
  4709. const char *location;
  4710. struct mod_gzip_cgi_child_stuff cld;
  4711. #ifdef MOD_GZIP_ENGAGED
  4712. conf->logname = cgi_logname;
  4713. conf->logbytes = (long) 60000L;
  4714. conf->bufbytes = (int) 20000;
  4715. #endif
  4716. if ( r->method_number == M_OPTIONS )
  4717. {
  4718. r->allowed |= (1 << M_GET);
  4719. r->allowed |= (1 << M_POST);
  4720. return DECLINED;
  4721. }
  4722. if ((argv0 = strrchr(r->filename, '/')) != NULL)
  4723. {
  4724. argv0++;
  4725. }
  4726. else
  4727. {
  4728. argv0 = r->filename;
  4729. }
  4730. nph = !(strncmp(argv0, "nph-", 4));
  4731. if ( !(ap_allow_options(r) & OPT_EXECCGI) && !is_scriptaliased(r) )
  4732. {
  4733. return log_scripterror(r, conf, FORBIDDEN, APLOG_NOERRNO,
  4734. "Options ExecCGI is off in this directory");
  4735. }
  4736. if ( nph && is_included )
  4737. {
  4738. return log_scripterror(r, conf, FORBIDDEN, APLOG_NOERRNO,
  4739. "attempt to include NPH CGI script");
  4740. }
  4741. #if defined(OS2) || defined(WIN32)
  4742. if ( r->finfo.st_mode == 0 )
  4743. {
  4744. struct stat statbuf;
  4745. char *newfile;
  4746. newfile = ap_pstrcat(r->pool, r->filename, ".EXE", NULL);
  4747. if ((stat(newfile, &statbuf) != 0) || (!S_ISREG(statbuf.st_mode)))
  4748. {
  4749. return log_scripterror(r, conf, NOT_FOUND, 0,
  4750. "script not found or unable to stat");
  4751. }
  4752. else
  4753. {
  4754. r->filename = newfile;
  4755. }
  4756. }
  4757. #else
  4758. if ( r->finfo.st_mode == 0 )
  4759. {
  4760. return log_scripterror(r, conf, NOT_FOUND, APLOG_NOERRNO,
  4761. "script not found or unable to stat");
  4762. }
  4763. #endif
  4764. if ( S_ISDIR( r->finfo.st_mode ) )
  4765. {
  4766. return log_scripterror(r, conf, FORBIDDEN, APLOG_NOERRNO,
  4767. "attempt to invoke directory as script");
  4768. }
  4769. if ( !ap_suexec_enabled )
  4770. {
  4771. if ( !ap_can_exec( &r->finfo ) )
  4772. {
  4773. return log_scripterror(r, conf, FORBIDDEN, APLOG_NOERRNO,
  4774. "file permissions deny server execution");
  4775. }
  4776. }
  4777. if ((retval = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)))
  4778. {
  4779. return retval;
  4780. }
  4781. ap_add_common_vars(r);
  4782. cld.argv0 = argv0;
  4783. cld.r = r;
  4784. cld.nph = nph;
  4785. cld.debug = conf->logname ? 1 : 0;
  4786. #ifdef TPF
  4787. cld.t.filename = r->filename;
  4788. cld.t.subprocess_env = r->subprocess_env;
  4789. cld.t.prog_type = FORK_FILE;
  4790. #endif
  4791. #ifdef CHARSET_EBCDIC
  4792. ap_bsetflag( r->connection->client, B_EBCDIC2ASCII, 1 );
  4793. #endif
  4794. if ( !ap_bspawn_child(
  4795. r->main ? r->main->pool : r->pool,
  4796. mod_gzip_cgi_child,
  4797. (void *) &cld,
  4798. kill_after_timeout,
  4799. &script_out,
  4800. &script_in,
  4801. &script_err
  4802. )
  4803. )
  4804. {
  4805. ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
  4806. "couldn't spawn child process: %s", r->filename);
  4807. return HTTP_INTERNAL_SERVER_ERROR;
  4808. }
  4809. else
  4810. {
  4811. }
  4812. if ( ap_should_client_block(r) )
  4813. {
  4814. int dbsize, len_read;
  4815. if ( conf->logname )
  4816. {
  4817. dbuf = ap_pcalloc( r->pool, conf->bufbytes + 1 );
  4818. dbpos = 0;
  4819. }
  4820. ap_hard_timeout("copy script args", r);
  4821. for (;;)
  4822. {
  4823. len_read =
  4824. ap_get_client_block( r, argsbuffer, HUGE_STRING_LEN );
  4825. if ( len_read < 1 )
  4826. {
  4827. break;
  4828. }
  4829. if (conf->logname)
  4830. {
  4831. if ((dbpos + len_read) > conf->bufbytes)
  4832. {
  4833. dbsize = conf->bufbytes - dbpos;
  4834. }
  4835. else
  4836. {
  4837. dbsize = len_read;
  4838. }
  4839. memcpy(dbuf + dbpos, argsbuffer, dbsize);
  4840. dbpos += dbsize;
  4841. }
  4842. ap_reset_timeout(r);
  4843. if ( ap_bwrite(script_out, argsbuffer, len_read) < len_read )
  4844. {
  4845. while ( len_read=
  4846. ap_get_client_block(r, argsbuffer, HUGE_STRING_LEN) > 0)
  4847. {
  4848. }
  4849. break;
  4850. }
  4851. else
  4852. {
  4853. }
  4854. }
  4855. ap_bflush( script_out );
  4856. ap_kill_timeout(r);
  4857. }
  4858. else
  4859. {
  4860. }
  4861. ap_bclose( script_out );
  4862. if ( script_in && !nph )
  4863. {
  4864. char sbuf[MAX_STRING_LEN];
  4865. int ret;
  4866. if ((ret = ap_scan_script_header_err_buff(r, script_in, sbuf)))
  4867. {
  4868. return log_script(r, conf, ret, dbuf, sbuf, script_in, script_err);
  4869. }
  4870. #ifdef CHARSET_EBCDIC
  4871. ap_checkconv(r);
  4872. #endif
  4873. location = ap_table_get( r->headers_out, "Location" );
  4874. if ( location && location[0] == '/' && r->status == 200 )
  4875. {
  4876. ap_hard_timeout("read from script", r);
  4877. while ( ap_bgets(argsbuffer, HUGE_STRING_LEN, script_in) > 0 )
  4878. {
  4879. continue;
  4880. }
  4881. while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0)
  4882. {
  4883. continue;
  4884. }
  4885. ap_kill_timeout(r);
  4886. r->method = ap_pstrdup(r->pool, "GET");
  4887. r->method_number = M_GET;
  4888. ap_table_unset( r->headers_in, "Content-Length" );
  4889. ap_internal_redirect_handler( location, r );
  4890. return OK;
  4891. }
  4892. else if ( location && r->status == 200 )
  4893. {
  4894. return REDIRECT;
  4895. }
  4896. #ifdef USE_GATHER
  4897. if ( r->header_only )
  4898. {
  4899. ap_send_http_header(r);
  4900. }
  4901. else
  4902. {
  4903. }
  4904. #else /* !USE_GATHER */
  4905. ap_send_http_header(r);
  4906. #endif /* USE_GATHER */
  4907. if (!r->header_only)
  4908. {
  4909. mod_gzip_ap_send_fb( script_in, r, &final_result );
  4910. }
  4911. ap_bclose( script_in );
  4912. ap_soft_timeout("soaking script stderr", r);
  4913. for (;;)
  4914. {
  4915. bytesread = ap_bgets( argsbuffer, HUGE_STRING_LEN, script_err );
  4916. if ( bytesread < 1 )
  4917. {
  4918. break;
  4919. }
  4920. }
  4921. ap_kill_timeout(r);
  4922. ap_bclose( script_err );
  4923. }
  4924. else
  4925. {
  4926. }
  4927. if ( script_in && nph )
  4928. {
  4929. #ifdef RUSSIAN_APACHE
  4930. if (ra_charset_active(r))
  4931. {
  4932. r->ra_codep=NULL;
  4933. }
  4934. #endif
  4935. mod_gzip_ap_send_fb( script_in, r, &final_result );
  4936. }
  4937. else
  4938. {
  4939. }
  4940. #ifdef ORIGINAL
  4941. return OK;
  4942. #endif
  4943. return final_result;
  4944. }
  4945. static int mod_gzip_cgi_child(void *child_stuff, child_info *pinfo)
  4946. {
  4947. struct mod_gzip_cgi_child_stuff *cld = (struct mod_gzip_cgi_child_stuff *) child_stuff;
  4948. request_rec *r = cld->r;
  4949. char *argv0 = cld->argv0;
  4950. int child_pid;
  4951. /* WARNING! If the following DEBUG_CGI switch is ON you may need to */
  4952. /* run Apache with the -X switch or the dynamic compression */
  4953. /* of some CGI output ( most notable Zope ) will start to fail. */
  4954. /* This DEBUG_CGI switch should NEVER be on for production runs. */
  4955. /*
  4956. #define DEBUG_CGI
  4957. */
  4958. #ifdef DEBUG_CGI
  4959. #ifdef OS2
  4960. FILE *dbg = fopen("con", "w");
  4961. #else
  4962. #ifdef WIN32
  4963. FILE *dbg = fopen("c:\\script.dbg", "a" );
  4964. #else
  4965. FILE *dbg = fopen("/dev/tty", "w");
  4966. #endif
  4967. #endif
  4968. int i;
  4969. #endif
  4970. char **env;
  4971. RAISE_SIGSTOP(CGI_CHILD);
  4972. #ifdef DEBUG_CGI
  4973. fprintf(dbg, "Attempting to exec %s as %sCGI child (argv0 = %s)\n",
  4974. r->filename, cld->nph ? "NPH " : "", argv0);
  4975. #endif
  4976. ap_add_cgi_vars(r);
  4977. env = ap_create_environment(r->pool, r->subprocess_env);
  4978. #ifdef DEBUG_CGI
  4979. fprintf(dbg, "Environment: \n");
  4980. for (i = 0; env[i]; ++i)
  4981. fprintf(dbg, "'%s'\n", env[i]);
  4982. #endif
  4983. #ifndef WIN32
  4984. #ifdef DEBUG_CGI
  4985. fprintf(dbg, "Call ap_chdir_file(r->filename=[%s]\n",r->filename);
  4986. #endif
  4987. ap_chdir_file(r->filename);
  4988. #ifdef DEBUG_CGI
  4989. fprintf(dbg, "Back ap_chdir_file(r->filename=[%s]\n",r->filename);
  4990. #endif
  4991. #endif
  4992. if (!cld->debug)
  4993. ap_error_log2stderr(r->server);
  4994. #ifdef TPF
  4995. #ifdef DEBUG_CGI
  4996. #ifdef WIN32
  4997. fprintf(dbg, "TPF defined... return( 0 ) now...\n");
  4998. if ( dbg ) { fclose(dbg); dbg=0; }
  4999. #endif
  5000. #endif
  5001. return (0);
  5002. #else
  5003. #ifdef DEBUG_CGI
  5004. fprintf(dbg, "Call ap_cleanup_for_exec()...\n");
  5005. #endif
  5006. ap_cleanup_for_exec();
  5007. #ifdef DEBUG_CGI
  5008. fprintf(dbg, "Back ap_cleanup_for_exec()...\n");
  5009. fprintf(dbg, "Call ap_call_exec()...\n");
  5010. #endif
  5011. child_pid = ap_call_exec(r, pinfo, argv0, env, 0);
  5012. #ifdef DEBUG_CGI
  5013. fprintf(dbg, "Back ap_call_exec()...\n");
  5014. #endif
  5015. #if defined(WIN32) || defined(OS2)
  5016. #ifdef DEBUG_CGI
  5017. #ifdef WIN32
  5018. fprintf(dbg, "WIN32 or OS2 defined... return( child_pid ) now...\n");
  5019. if ( dbg ) { fclose(dbg); dbg=0; }
  5020. #endif
  5021. #endif
  5022. return (child_pid);
  5023. #else
  5024. ap_log_error(APLOG_MARK, APLOG_ERR, NULL, "exec of %s failed", r->filename);
  5025. exit(0);
  5026. #ifdef DEBUG_CGI
  5027. #ifdef WIN32
  5028. if ( dbg ) { fclose(dbg); dbg=0; }
  5029. #endif
  5030. #endif
  5031. return (0);
  5032. #endif
  5033. #endif
  5034. }
  5035. #define MOD_GZIP_SET_BYTES_SENT(r) \
  5036. do { if (r->sent_bodyct) \
  5037. ap_bgetopt (r->connection->client, BO_BYTECT, &r->bytes_sent); \
  5038. } while (0)
  5039. long mod_gzip_ap_send_fb( BUFF *fb, request_rec *r, int *final_return_code )
  5040. {
  5041. long lrc;
  5042. int return_code=DECLINED;
  5043. lrc = (long ) mod_gzip_ap_send_fb_length( fb, r, -1, &return_code );
  5044. *final_return_code = return_code;
  5045. return lrc;
  5046. }
  5047. #ifdef USE_TPF_SELECT
  5048. #define mod_gzip_ap_select(_a, _b, _c, _d, _e) \
  5049. tpf_select(_a, _b, _c, _d, _e)
  5050. #elif defined(SELECT_NEEDS_CAST)
  5051. #define mod_gzip_ap_select(_a, _b, _c, _d, _e) \
  5052. select((_a), (int *)(_b), (int *)(_c), (int *)(_d), (_e))
  5053. #else
  5054. #define mod_gzip_ap_select(_a, _b, _c, _d, _e) \
  5055. select(_a, _b, _c, _d, _e)
  5056. #endif
  5057. long mod_gzip_ap_send_fb_length(
  5058. BUFF *fb,
  5059. request_rec *r,
  5060. long length,
  5061. int *final_return_code
  5062. )
  5063. {
  5064. char cn[]="mod_gzip_ab_send_fb_length()";
  5065. char buf[IOBUFSIZE];
  5066. long total_bytes_sent = 0;
  5067. register int n;
  5068. register int len;
  5069. register int fd;
  5070. fd_set fds;
  5071. int rc;
  5072. #ifndef USE_GATHER
  5073. register int w;
  5074. register int o;
  5075. #endif
  5076. #ifdef USE_GATHER
  5077. int gather_on = 0;
  5078. int gather_todisk = 0;
  5079. int gather_origin = 0;
  5080. char *gather_bufstart = 0;
  5081. char *gather_source = 0;
  5082. char *gather_buf = 0;
  5083. int gather_bufmaxlen = 60000;
  5084. int gather_byteswritten = 0;
  5085. int gather_length = 0;
  5086. int gather_maxlen = 0;
  5087. long gather_totlen = 0;
  5088. FILE *gather_fh1 = 0;
  5089. char gather_filename[ MOD_GZIP_MAX_PATH_LEN + 2 ];
  5090. #endif
  5091. void *modconf = r->server->module_config;
  5092. mod_gzip_conf *conf;
  5093. *final_return_code = DECLINED;
  5094. conf = (mod_gzip_conf *) ap_get_module_config( modconf, &gzip_module );
  5095. if ( length == 0 )
  5096. {
  5097. return 0;
  5098. }
  5099. ap_bsetflag( fb, B_RD, 0 );
  5100. #ifndef TPF
  5101. ap_bnonblock( fb, B_RD );
  5102. #endif
  5103. fd = ap_bfileno( fb, B_RD );
  5104. #ifdef CHECK_FD_SETSIZE
  5105. if ( fd >= FD_SETSIZE )
  5106. {
  5107. ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL,
  5108. "send body: filedescriptor (%u) larger than FD_SETSIZE (%u) "
  5109. "found, you probably need to rebuild Apache with a "
  5110. "larger FD_SETSIZE", fd, FD_SETSIZE);
  5111. return 0;
  5112. }
  5113. else
  5114. {
  5115. }
  5116. #else
  5117. #endif
  5118. ap_soft_timeout("send body", r);
  5119. FD_ZERO( &fds );
  5120. #ifdef USE_GATHER
  5121. gather_on = 0;
  5122. if ( (long) conf->maximum_inmem_size < (long) gather_bufmaxlen )
  5123. {
  5124. gather_maxlen = (int) conf->maximum_inmem_size;
  5125. }
  5126. else
  5127. {
  5128. gather_maxlen = (int) gather_bufmaxlen;
  5129. }
  5130. gather_bufstart = malloc( (int)(gather_maxlen + 2) );
  5131. if ( gather_bufstart )
  5132. {
  5133. gather_on = 1;
  5134. gather_buf = gather_bufstart;
  5135. gather_source = gather_bufstart;
  5136. gather_origin = 0;
  5137. }
  5138. else
  5139. {
  5140. }
  5141. #endif
  5142. while( !r->connection->aborted )
  5143. {
  5144. #ifdef NDELAY_PIPE_RETURNS_ZERO
  5145. int afterselect = 0;
  5146. #endif
  5147. if ( (length > 0) && (total_bytes_sent + IOBUFSIZE) > length )
  5148. {
  5149. len = length - total_bytes_sent;
  5150. }
  5151. else
  5152. {
  5153. len = IOBUFSIZE;
  5154. }
  5155. do {
  5156. n = ap_bread( fb, buf, len );
  5157. #ifdef NDELAY_PIPE_RETURNS_ZERO
  5158. if ((n > 0) || (n == 0 && afterselect))
  5159. {
  5160. break;
  5161. }
  5162. #else
  5163. if (n >= 0)
  5164. {
  5165. break;
  5166. }
  5167. #endif
  5168. if ( r->connection->aborted )
  5169. {
  5170. break;
  5171. }
  5172. if ( n < 0 && errno != EAGAIN )
  5173. {
  5174. break;
  5175. }
  5176. if ( ap_bflush( r->connection->client ) < 0 )
  5177. {
  5178. ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
  5179. "client stopped connection before send body completed");
  5180. ap_bsetflag( r->connection->client, B_EOUT, 1 );
  5181. r->connection->aborted = 1;
  5182. break;
  5183. }
  5184. #ifdef WIN32
  5185. FD_SET( (unsigned) fd, &fds );
  5186. #else
  5187. FD_SET( fd, &fds );
  5188. #endif
  5189. #ifdef FUTURE_USE
  5190. mod_gzip_ap_select(fd + 1, &fds, NULL, NULL, NULL);
  5191. #endif
  5192. #ifdef NDELAY_PIPE_RETURNS_ZERO
  5193. afterselect = 1;
  5194. #endif
  5195. } while ( !r->connection->aborted );
  5196. if ( n < 1 || r->connection->aborted )
  5197. {
  5198. break;
  5199. }
  5200. #ifdef USE_GATHER
  5201. if ( gather_on )
  5202. {
  5203. if ( ( gather_length + n ) >= gather_maxlen )
  5204. {
  5205. if ( !gather_fh1 )
  5206. {
  5207. mod_gzip_create_unique_filename(
  5208. (mod_gzip_conf *) conf,
  5209. (char *) gather_filename,
  5210. sizeof( gather_filename )
  5211. );
  5212. gather_fh1 = fopen( gather_filename, "wb" );
  5213. if ( gather_fh1 )
  5214. {
  5215. gather_source = gather_filename;
  5216. gather_origin = 1;
  5217. }
  5218. else
  5219. {
  5220. gather_on = 0;
  5221. }
  5222. }
  5223. if ( ( gather_fh1 ) && ( gather_length > 0 ) )
  5224. {
  5225. gather_byteswritten =
  5226. fwrite( gather_bufstart, 1, gather_length, gather_fh1 );
  5227. if ( gather_byteswritten != gather_length )
  5228. {
  5229. gather_on = 0;
  5230. }
  5231. }
  5232. if ( ( gather_fh1 ) && ( n > 0 ) )
  5233. {
  5234. gather_byteswritten =
  5235. fwrite( buf, 1, n, gather_fh1 );
  5236. if ( gather_byteswritten != n )
  5237. {
  5238. gather_on = 0;
  5239. }
  5240. }
  5241. gather_buf = gather_bufstart;
  5242. gather_length = 0;
  5243. }
  5244. else
  5245. {
  5246. if ( gather_on )
  5247. {
  5248. memcpy( gather_buf, buf, n );
  5249. gather_buf += n;
  5250. gather_length += n;
  5251. }
  5252. }
  5253. gather_totlen += n;
  5254. }
  5255. #endif
  5256. #ifdef FUTURE_USE
  5257. o = 0;
  5258. while ( n && !r->connection->aborted )
  5259. {
  5260. #ifdef RUSSIAN_APACHE
  5261. unsigned char *newbuf,*p;
  5262. int newlen=0;
  5263. if ( ra_charset_active(r) )
  5264. {
  5265. if ( ra_flag( r, RA_WIDE_CHARS_SC ) )
  5266. {
  5267. ra_data_server2client(r,&buf[o],n,&newbuf,&newlen);
  5268. p=newbuf;
  5269. while( newlen > 0 )
  5270. {
  5271. w = ap_bwrite( r->connection->client, p, newlen );
  5272. if(w<=0) goto RECODE_DONE;
  5273. newlen-=w;
  5274. p+=w;
  5275. }
  5276. w=n;
  5277. }
  5278. else
  5279. {
  5280. unsigned char *t = r->ra_codep->cp_otabl_p;
  5281. unsigned char *b = (unsigned char *)&buf[o];
  5282. unsigned char *end = b+n;
  5283. while( b < end )
  5284. {
  5285. *b = t[*b];
  5286. b++;
  5287. }
  5288. w = ap_bwrite( r->connection->client, &buf[o], n );
  5289. }
  5290. }
  5291. else
  5292. {
  5293. w = ap_bwrite( r->connection->client, &buf[o], n );
  5294. }
  5295. RECODE_DONE:;
  5296. #else
  5297. w = ap_bwrite( r->connection->client, &buf[o], n );
  5298. #endif
  5299. if ( w > 0 )
  5300. {
  5301. ap_reset_timeout(r);
  5302. total_bytes_sent += w;
  5303. n -= w;
  5304. o += w;
  5305. }
  5306. else if ( w < 0 )
  5307. {
  5308. if ( !r->connection->aborted )
  5309. {
  5310. ap_log_rerror(APLOG_MARK, APLOG_INFO, r,
  5311. "client stopped connection before send body completed");
  5312. ap_bsetflag(r->connection->client, B_EOUT, 1);
  5313. r->connection->aborted = 1;
  5314. }
  5315. break;
  5316. }
  5317. }
  5318. #endif
  5319. }
  5320. ap_kill_timeout(r);
  5321. MOD_GZIP_SET_BYTES_SENT(r);
  5322. #ifdef USE_GATHER
  5323. if ( gather_fh1 )
  5324. {
  5325. if ( gather_length > 0 )
  5326. {
  5327. gather_byteswritten =
  5328. fwrite( gather_bufstart, 1, gather_length, gather_fh1 );
  5329. if ( gather_byteswritten != gather_length )
  5330. {
  5331. gather_on = 0;
  5332. }
  5333. }
  5334. fclose( gather_fh1 );
  5335. gather_fh1 = 0;
  5336. }
  5337. if ( gather_totlen > 0 )
  5338. {
  5339. rc =
  5340. mod_gzip_encode_and_transmit(
  5341. (request_rec *) r,
  5342. (char *) gather_source,
  5343. (int ) gather_origin,
  5344. (long ) gather_totlen,
  5345. (int ) 1
  5346. );
  5347. *final_return_code = rc;
  5348. }
  5349. if ( gather_bufstart )
  5350. {
  5351. free( gather_bufstart );
  5352. gather_bufstart = 0;
  5353. }
  5354. gather_on = 0;
  5355. #endif
  5356. return total_bytes_sent;
  5357. }
  5358. /*--------------------------------------------------------------------------*/
  5359. /* COMPRESSION SUPPORT ROUTINES */
  5360. /*--------------------------------------------------------------------------*/
  5361. #define BIG_MEM
  5362. typedef unsigned uns;
  5363. typedef unsigned int uni;
  5364. typedef unsigned char uch;
  5365. typedef unsigned short ush;
  5366. typedef unsigned long ulg;
  5367. typedef int gz1_file_t;
  5368. #ifdef __STDC__
  5369. typedef void *voidp;
  5370. #else
  5371. typedef char *voidp;
  5372. #endif
  5373. #if defined(__MSDOS__) && !defined(MSDOS)
  5374. # define MSDOS
  5375. #endif
  5376. #if defined(__OS2__) && !defined(OS2)
  5377. # define OS2
  5378. #endif
  5379. #if defined(OS2) && defined(MSDOS)
  5380. # undef MSDOS
  5381. #endif
  5382. #ifdef MSDOS
  5383. # ifdef __GNUC__
  5384. # define near
  5385. # else
  5386. # define MAXSEG_64K
  5387. # ifdef __TURBOC__
  5388. # define NO_OFF_T
  5389. # ifdef __BORLANDC__
  5390. # define DIRENT
  5391. # else
  5392. # define NO_UTIME
  5393. # endif
  5394. # else
  5395. # define HAVE_SYS_UTIME_H
  5396. # define NO_UTIME_H
  5397. # endif
  5398. # endif
  5399. # define PATH_SEP2 '\\'
  5400. # define PATH_SEP3 ':'
  5401. # define MAX_PATH_LEN 128
  5402. # define NO_MULTIPLE_DOTS
  5403. # define MAX_EXT_CHARS 3
  5404. # define Z_SUFFIX "z"
  5405. # define NO_CHOWN
  5406. # define PROTO
  5407. # define STDC_HEADERS
  5408. # define NO_SIZE_CHECK
  5409. # define casemap(c) tolow(c)
  5410. # include <io.h>
  5411. # undef OS_CODE
  5412. # define OS_CODE 0x00
  5413. # define SET_BINARY_MODE(fd) setmode(fd, O_BINARY)
  5414. # if !defined(NO_ASM) && !defined(ASMV)
  5415. # define ASMV
  5416. # endif
  5417. #else
  5418. # define near
  5419. #endif
  5420. #ifdef OS2
  5421. # define PATH_SEP2 '\\'
  5422. # define PATH_SEP3 ':'
  5423. # define MAX_PATH_LEN 260
  5424. # ifdef OS2FAT
  5425. # define NO_MULTIPLE_DOTS
  5426. # define MAX_EXT_CHARS 3
  5427. # define Z_SUFFIX "z"
  5428. # define casemap(c) tolow(c)
  5429. # endif
  5430. # define NO_CHOWN
  5431. # define PROTO
  5432. # define STDC_HEADERS
  5433. # include <io.h>
  5434. # undef OS_CODE
  5435. # define OS_CODE 0x06
  5436. # define SET_BINARY_MODE(fd) setmode(fd, O_BINARY)
  5437. # ifdef _MSC_VER
  5438. # define HAVE_SYS_UTIME_H
  5439. # define NO_UTIME_H
  5440. # define MAXSEG_64K
  5441. # undef near
  5442. # define near _near
  5443. # endif
  5444. # ifdef __EMX__
  5445. # define HAVE_SYS_UTIME_H
  5446. # define NO_UTIME_H
  5447. # define DIRENT
  5448. # define EXPAND(argc,argv) \
  5449. {_response(&argc, &argv); _wildcard(&argc, &argv);}
  5450. # endif
  5451. # ifdef __BORLANDC__
  5452. # define DIRENT
  5453. # endif
  5454. # ifdef __ZTC__
  5455. # define NO_DIR
  5456. # define NO_UTIME_H
  5457. # include <dos.h>
  5458. # define EXPAND(argc,argv) \
  5459. {response_expand(&argc, &argv);}
  5460. # endif
  5461. #endif
  5462. #ifdef WIN32
  5463. # define HAVE_SYS_UTIME_H
  5464. # define NO_UTIME_H
  5465. # define PATH_SEP2 '\\'
  5466. # define PATH_SEP3 ':'
  5467. # undef MAX_PATH_LEN
  5468. # define MAX_PATH_LEN 260
  5469. # define NO_CHOWN
  5470. # define PROTO
  5471. # define STDC_HEADERS
  5472. # define SET_BINARY_MODE(fd) setmode(fd, O_BINARY)
  5473. # include <io.h>
  5474. # ifdef NTFAT
  5475. # define NO_MULTIPLE_DOTS
  5476. # define MAX_EXT_CHARS 3
  5477. # define Z_SUFFIX "z"
  5478. # define casemap(c) tolow(c)
  5479. # endif
  5480. # undef OS_CODE
  5481. # define OS_CODE 0x00
  5482. #endif
  5483. #ifdef MSDOS
  5484. # ifdef __TURBOC__
  5485. # include <alloc.h>
  5486. # define DYN_ALLOC
  5487. void * fcalloc (unsigned items, unsigned size);
  5488. void fcfree (void *ptr);
  5489. # else
  5490. # define fcalloc(nitems,itemsize) halloc((long)(nitems),(itemsize))
  5491. # define fcfree(ptr) hfree(ptr)
  5492. # endif
  5493. #else
  5494. # ifdef MAXSEG_64K
  5495. # define fcalloc(items,size) calloc((items),(size))
  5496. # else
  5497. # define fcalloc(items,size) malloc((size_t)(items)*(size_t)(size))
  5498. # endif
  5499. # define fcfree(ptr) free(ptr)
  5500. #endif
  5501. #if defined(VAXC) || defined(VMS)
  5502. # define PATH_SEP ']'
  5503. # define PATH_SEP2 ':'
  5504. # define SUFFIX_SEP ';'
  5505. # define NO_MULTIPLE_DOTS
  5506. # define Z_SUFFIX "-gz"
  5507. # define RECORD_IO 1
  5508. # define casemap(c) tolow(c)
  5509. # undef OS_CODE
  5510. # define OS_CODE 0x02
  5511. # define OPTIONS_VAR "GZIP_OPT"
  5512. # define STDC_HEADERS
  5513. # define NO_UTIME
  5514. # define EXPAND(argc,argv) vms_expand_args(&argc,&argv);
  5515. # include <file.h>
  5516. # define unlink delete
  5517. # ifdef VAXC
  5518. # define NO_FCNTL_H
  5519. # include <unixio.h>
  5520. # endif
  5521. #endif
  5522. #ifdef AMIGA
  5523. # define PATH_SEP2 ':'
  5524. # define STDC_HEADERS
  5525. # undef OS_CODE
  5526. # define OS_CODE 0x01
  5527. # define ASMV
  5528. # ifdef __GNUC__
  5529. # define DIRENT
  5530. # define HAVE_UNISTD_H
  5531. # else
  5532. # define NO_STDIN_FSTAT
  5533. # define SYSDIR
  5534. # define NO_SYMLINK
  5535. # define NO_CHOWN
  5536. # define NO_FCNTL_H
  5537. # include <fcntl.h>
  5538. # define direct dirent
  5539. extern void _expand_args(int *argc, char ***argv);
  5540. # define EXPAND(argc,argv) _expand_args(&argc,&argv);
  5541. # undef O_BINARY
  5542. # endif
  5543. #endif
  5544. #if defined(ATARI) || defined(atarist)
  5545. # ifndef STDC_HEADERS
  5546. # define STDC_HEADERS
  5547. # define HAVE_UNISTD_H
  5548. # define DIRENT
  5549. # endif
  5550. # define ASMV
  5551. # undef OS_CODE
  5552. # define OS_CODE 0x05
  5553. # ifdef TOSFS
  5554. # define PATH_SEP2 '\\'
  5555. # define PATH_SEP3 ':'
  5556. # define MAX_PATH_LEN 128
  5557. # define NO_MULTIPLE_DOTS
  5558. # define MAX_EXT_CHARS 3
  5559. # define Z_SUFFIX "z"
  5560. # define NO_CHOWN
  5561. # define casemap(c) tolow(c)
  5562. # define NO_SYMLINK
  5563. # endif
  5564. #endif
  5565. #ifdef MACOS
  5566. # define PATH_SEP ':'
  5567. # define DYN_ALLOC
  5568. # define PROTO
  5569. # define NO_STDIN_FSTAT
  5570. # define NO_CHOWN
  5571. # define NO_UTIME
  5572. # define chmod(file, mode) (0)
  5573. # define OPEN(name, flags, mode) open(name, flags)
  5574. # undef OS_CODE
  5575. # define OS_CODE 0x07
  5576. # ifdef MPW
  5577. # define isatty(fd) ((fd) <= 2)
  5578. # endif
  5579. #endif
  5580. #ifdef __50SERIES
  5581. # define PATH_SEP '>'
  5582. # define STDC_HEADERS
  5583. # define NO_MEMORY_H
  5584. # define NO_UTIME_H
  5585. # define NO_UTIME
  5586. # define NO_CHOWN
  5587. # define NO_STDIN_FSTAT
  5588. # define NO_SIZE_CHECK
  5589. # define NO_SYMLINK
  5590. # define RECORD_IO 1
  5591. # define casemap(c) tolow(c)
  5592. # define put_char(c) put_byte((c) & 0x7F)
  5593. # define get_char(c) ascii2pascii(get_byte())
  5594. # undef OS_CODE
  5595. # define OS_CODE 0x0F
  5596. # ifdef SIGTERM
  5597. # undef SIGTERM
  5598. # endif
  5599. #endif
  5600. #if defined(pyr) && !defined(NOMEMCPY)
  5601. # define NOMEMCPY
  5602. #endif
  5603. #ifdef TOPS20
  5604. # undef OS_CODE
  5605. # define OS_CODE 0x0a
  5606. #endif
  5607. #ifndef unix
  5608. # define NO_ST_INO
  5609. #endif
  5610. #ifndef OS_CODE
  5611. # undef OS_CODE
  5612. # define OS_CODE 0x03
  5613. #endif
  5614. #ifndef PATH_SEP
  5615. # define PATH_SEP '/'
  5616. #endif
  5617. #ifndef casemap
  5618. # define casemap(c) (c)
  5619. #endif
  5620. #ifndef OPTIONS_VAR
  5621. # define OPTIONS_VAR "GZIP"
  5622. #endif
  5623. #ifndef Z_SUFFIX
  5624. # define Z_SUFFIX ".gz"
  5625. #endif
  5626. #ifdef MAX_EXT_CHARS
  5627. # define MAX_SUFFIX MAX_EXT_CHARS
  5628. #else
  5629. # define MAX_SUFFIX 30
  5630. #endif
  5631. #ifndef MIN_PART
  5632. # define MIN_PART 3
  5633. #endif
  5634. #ifndef EXPAND
  5635. # define EXPAND(argc,argv)
  5636. #endif
  5637. #ifndef RECORD_IO
  5638. # define RECORD_IO 0
  5639. #endif
  5640. #ifndef SET_BINARY_MODE
  5641. # define SET_BINARY_MODE(fd)
  5642. #endif
  5643. #ifndef OPEN
  5644. # define OPEN(name, flags, mode) open(name, flags, mode)
  5645. #endif
  5646. #ifndef get_char
  5647. # define get_char() get_byte()
  5648. #endif
  5649. #ifndef put_char
  5650. # define put_char(c) put_byte(c)
  5651. #endif
  5652. #ifndef O_BINARY
  5653. #define O_BINARY 0
  5654. #endif
  5655. #define OK 0
  5656. #define LZ1_ERROR 1
  5657. #define WARNING 2
  5658. #define STORED 0
  5659. #define COMPRESSED 1
  5660. #define PACKED 2
  5661. #define LZHED 3
  5662. #define DEFLATED 8
  5663. #define MAX_METHODS 9
  5664. #ifndef O_CREAT
  5665. #include <sys/file.h>
  5666. #ifndef O_CREAT
  5667. #define O_CREAT FCREAT
  5668. #endif
  5669. #ifndef O_EXCL
  5670. #define O_EXCL FEXCL
  5671. #endif
  5672. #endif
  5673. #ifndef S_IRUSR
  5674. #define S_IRUSR 0400
  5675. #endif
  5676. #ifndef S_IWUSR
  5677. #define S_IWUSR 0200
  5678. #endif
  5679. #define RW_USER (S_IRUSR | S_IWUSR)
  5680. #ifndef MAX_PATH_LEN
  5681. #define MAX_PATH_LEN 256
  5682. #endif
  5683. #ifndef SEEK_END
  5684. #define SEEK_END 2
  5685. #endif
  5686. #define PACK_MAGIC "\037\036"
  5687. #define GZIP_MAGIC "\037\213"
  5688. #define OLD_GZIP_MAGIC "\037\236"
  5689. #define LZH_MAGIC "\037\240"
  5690. #define PKZIP_MAGIC "\120\113\003\004"
  5691. #define ASCII_FLAG 0x01
  5692. #define CONTINUATION 0x02
  5693. #define EXTRA_FIELD 0x04
  5694. #define ORIG_NAME 0x08
  5695. #define COMMENT 0x10
  5696. #define ENCRYPTED 0x20
  5697. #define RESERVED 0xC0
  5698. #define UNKNOWN 0xffff
  5699. #define BINARY 0
  5700. #define ASCII 1
  5701. #ifndef WSIZE
  5702. #define WSIZE 0x8000
  5703. #endif
  5704. #ifndef INBUFSIZ
  5705. #ifdef SMALL_MEM
  5706. #define INBUFSIZ 0x2000
  5707. #else
  5708. #define INBUFSIZ 0x8000
  5709. #endif
  5710. #endif
  5711. #define INBUF_EXTRA 64
  5712. #ifndef OUTBUFSIZ
  5713. #ifdef SMALL_MEM
  5714. #define OUTBUFSIZ 8192
  5715. #else
  5716. #define OUTBUFSIZ 0x4000
  5717. #endif
  5718. #endif
  5719. #define OUTBUF_EXTRA 2048
  5720. #ifndef DIST_BUFSIZE
  5721. #ifdef SMALL_MEM
  5722. #define DIST_BUFSIZE 0x2000
  5723. #else
  5724. #define DIST_BUFSIZE 0x8000
  5725. #endif
  5726. #endif
  5727. #ifndef BITS
  5728. #define BITS 16
  5729. #endif
  5730. #define LZW_MAGIC "\037\235"
  5731. #define MIN_MATCH 3
  5732. #define MAX_MATCH 258
  5733. #define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
  5734. #define MAX_DIST (WSIZE-MIN_LOOKAHEAD)
  5735. #ifdef SMALL_MEM
  5736. #define HASH_BITS 13
  5737. #endif
  5738. #ifdef MEDIUM_MEM
  5739. #define HASH_BITS 14
  5740. #endif
  5741. #ifndef HASH_BITS
  5742. #define HASH_BITS 15
  5743. #endif
  5744. #define HASH_SIZE (unsigned)(1<<HASH_BITS)
  5745. #define HASH_MASK (HASH_SIZE-1)
  5746. #define WMASK (WSIZE-1)
  5747. #define H_SHIFT ((HASH_BITS+MIN_MATCH-1)/MIN_MATCH)
  5748. #ifndef TOO_FAR
  5749. #define TOO_FAR 4096
  5750. #endif
  5751. #define NIL 0
  5752. #define FAST 4
  5753. #define SLOW 2
  5754. #define REP_3_6 16
  5755. #define REPZ_3_10 17
  5756. #define REPZ_11_138 18
  5757. #define MAX_BITS 15
  5758. #define MAX_BL_BITS 7
  5759. #define D_CODES 30
  5760. #define BL_CODES 19
  5761. #define SMALLEST 1
  5762. #define LENGTH_CODES 29
  5763. #define LITERALS 256
  5764. #define END_BLOCK 256
  5765. #define L_CODES (LITERALS+1+LENGTH_CODES)
  5766. #ifndef LIT_BUFSIZE
  5767. #ifdef SMALL_MEM
  5768. #define LIT_BUFSIZE 0x2000
  5769. #else
  5770. #ifdef MEDIUM_MEM
  5771. #define LIT_BUFSIZE 0x4000
  5772. #else
  5773. #define LIT_BUFSIZE 0x8000
  5774. #endif
  5775. #endif
  5776. #endif
  5777. #define HEAP_SIZE (2*L_CODES+1)
  5778. #define STORED_BLOCK 0
  5779. #define STATIC_TREES 1
  5780. #define DYN_TREES 2
  5781. #define NO_FILE (-1)
  5782. #define BMAX 16
  5783. #define N_MAX 288
  5784. #define LOCSIG 0x04034b50L
  5785. #define LOCFLG 6
  5786. #define CRPFLG 1
  5787. #define EXTFLG 8
  5788. #define LOCHOW 8
  5789. #define LOCTIM 10
  5790. #define LOCCRC 14
  5791. #define LOCSIZ 18
  5792. #define LOCLEN 22
  5793. #define LOCFIL 26
  5794. #define LOCEXT 28
  5795. #define LOCHDR 30
  5796. #define EXTHDR 16
  5797. #define RAND_HEAD_LEN 12
  5798. #define BUFSIZE (8 * 2*sizeof(char))
  5799. #define translate_eol 0
  5800. #define FLUSH_BLOCK(eof) \
  5801. flush_block(gz1,gz1->block_start >= 0L ? (char*)&gz1->window[(unsigned)gz1->block_start] : \
  5802. (char*)NULL, (long)gz1->strstart - gz1->block_start, (eof))
  5803. #ifdef DYN_ALLOC
  5804. # define ALLOC(type, array, size) { \
  5805. array = (type*)fcalloc((size_t)(((size)+1L)/2), 2*sizeof(type)); \
  5806. if (array == NULL) error("insufficient memory"); \
  5807. }
  5808. # define FREE(array) {if (array != NULL) fcfree(array), array=NULL;}
  5809. #else
  5810. # define ALLOC(type, array, size)
  5811. # define FREE(array)
  5812. #endif
  5813. #define GZ1_MAX(a,b) (a >= b ? a : b)
  5814. #define tolow(c) (isupper(c) ? (c)-'A'+'a' : (c))
  5815. #define smaller(tree, n, m) \
  5816. (tree[n].fc.freq < tree[m].fc.freq || \
  5817. (tree[n].fc.freq == tree[m].fc.freq && gz1->depth[n] <= gz1->depth[m]))
  5818. #define send_code(c, tree) send_bits(gz1,tree[c].fc.code, tree[c].dl.len)
  5819. #define put_byte(c) {gz1->outbuf[gz1->outcnt++]=(uch)(c); if (gz1->outcnt==OUTBUFSIZ)\
  5820. flush_outbuf(gz1);}
  5821. #define put_short(w) \
  5822. { if (gz1->outcnt < OUTBUFSIZ-2) { \
  5823. gz1->outbuf[gz1->outcnt++] = (uch) ((w) & 0xff); \
  5824. gz1->outbuf[gz1->outcnt++] = (uch) ((ush)(w) >> 8); \
  5825. } else { \
  5826. put_byte((uch)((w) & 0xff)); \
  5827. put_byte((uch)((ush)(w) >> 8)); \
  5828. } \
  5829. }
  5830. #define put_long(n) { \
  5831. put_short((n) & 0xffff); \
  5832. put_short(((ulg)(n)) >> 16); \
  5833. }
  5834. #ifdef CRYPT
  5835. # define NEXTBYTE() \
  5836. (decrypt ? (cc = get_byte(), zdecode(cc), cc) : get_byte())
  5837. #else
  5838. # define NEXTBYTE() (uch)get_byte()
  5839. #endif
  5840. #define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE())<<k;k+=8;}}
  5841. #define DUMPBITS(n) {b>>=(n);k-=(n);}
  5842. #define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8))
  5843. #define LG(p) ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16))
  5844. #define put_ubyte(c) {gz1->window[gz1->outcnt++]=(uch)(c); if (gz1->outcnt==WSIZE)\
  5845. flush_window(gz1);}
  5846. #define WARN(msg) { if (gz1->exit_code == OK) gz1->exit_code = WARNING; }
  5847. #define get_byte() (gz1->inptr < gz1->insize ? gz1->inbuf[gz1->inptr++] : fill_inbuf(gz1,0))
  5848. #define try_byte() (gz1->inptr < gz1->insize ? gz1->inbuf[gz1->inptr++] : fill_inbuf(gz1,1))
  5849. #define d_code(dist) \
  5850. ((dist) < 256 ? gz1->dist_code[dist] : gz1->dist_code[256+((dist)>>7)])
  5851. typedef struct config {
  5852. ush good_length;
  5853. ush max_lazy;
  5854. ush nice_length;
  5855. ush max_chain;
  5856. } config;
  5857. config configuration_table[10] = {
  5858. {0, 0, 0, 0},
  5859. {4, 4, 8, 4},
  5860. {4, 5, 16, 8},
  5861. {4, 6, 32, 32},
  5862. {4, 4, 16, 16},
  5863. {8, 16, 32, 32},
  5864. {8, 16, 128, 128},
  5865. {8, 32, 128, 256},
  5866. {32, 128, 258, 1024},
  5867. {32, 258, 258, 4096}};
  5868. typedef struct ct_data {
  5869. union {
  5870. ush freq;
  5871. ush code;
  5872. } fc;
  5873. union {
  5874. ush dad;
  5875. ush len;
  5876. } dl;
  5877. } ct_data;
  5878. typedef struct tree_desc {
  5879. ct_data *dyn_tree;
  5880. ct_data *static_tree;
  5881. int *extra_bits;
  5882. int extra_base;
  5883. int elems;
  5884. int max_length;
  5885. int max_code;
  5886. } tree_desc;
  5887. struct huft {
  5888. uch e;
  5889. uch b;
  5890. union {
  5891. ush n;
  5892. struct huft *t;
  5893. } v;
  5894. };
  5895. uch bl_order[BL_CODES]
  5896. = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
  5897. int extra_lbits[LENGTH_CODES]
  5898. = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
  5899. int extra_dbits[D_CODES]
  5900. = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
  5901. int extra_blbits[BL_CODES]
  5902. = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
  5903. ulg crc_32_tab[] = {
  5904. 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
  5905. 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
  5906. 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
  5907. 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
  5908. 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
  5909. 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
  5910. 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
  5911. 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
  5912. 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
  5913. 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
  5914. 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
  5915. 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
  5916. 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
  5917. 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
  5918. 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
  5919. 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
  5920. 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
  5921. 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
  5922. 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
  5923. 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
  5924. 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
  5925. 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
  5926. 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
  5927. 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
  5928. 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
  5929. 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
  5930. 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
  5931. 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
  5932. 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
  5933. 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
  5934. 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
  5935. 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
  5936. 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
  5937. 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
  5938. 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
  5939. 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
  5940. 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
  5941. 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
  5942. 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
  5943. 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
  5944. 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
  5945. 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
  5946. 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
  5947. 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
  5948. 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
  5949. 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
  5950. 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
  5951. 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
  5952. 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
  5953. 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
  5954. 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
  5955. 0x2d02ef8dL
  5956. };
  5957. typedef struct _GZ1 {
  5958. long compression_format;
  5959. long versionid1;
  5960. int state;
  5961. int done;
  5962. int deflate1_initialized;
  5963. unsigned deflate1_hash_head;
  5964. unsigned deflate1_prev_match;
  5965. int deflate1_flush;
  5966. int deflate1_match_available;
  5967. unsigned deflate1_match_length;
  5968. char ifname[MAX_PATH_LEN];
  5969. char ofname[MAX_PATH_LEN];
  5970. struct stat istat;
  5971. gz1_file_t zfile;
  5972. int input_ismem;
  5973. char *input_ptr;
  5974. long input_bytesleft;
  5975. int output_ismem;
  5976. char *output_ptr;
  5977. uns output_maxlen;
  5978. int compr_level;
  5979. long time_stamp;
  5980. long ifile_size;
  5981. int ifd;
  5982. int ofd;
  5983. int part_nb;
  5984. int last_member;
  5985. int save_orig_name;
  5986. long header_bytes;
  5987. long bytes_in;
  5988. long bytes_out;
  5989. uns insize;
  5990. uns inptr;
  5991. uns outcnt;
  5992. uns ins_h;
  5993. long block_start;
  5994. uns good_match;
  5995. uni max_lazy_match;
  5996. uni prev_length;
  5997. uns max_chain_length;
  5998. uns strstart;
  5999. uns match_start;
  6000. int eofile;
  6001. uns lookahead;
  6002. ush *file_type;
  6003. int *file_method;
  6004. ulg opt_len;
  6005. ulg static_len;
  6006. ulg compressed_len;
  6007. ulg input_len;
  6008. uns last_flags;
  6009. uch flags;
  6010. uns last_lit;
  6011. uns last_dist;
  6012. uch flag_bit;
  6013. int heap_len;
  6014. int heap_max;
  6015. ulg bb;
  6016. uns bk;
  6017. ush bi_buf;
  6018. int bi_valid;
  6019. uns hufts;
  6020. int decrypt;
  6021. int ascii;
  6022. int msg_done;
  6023. int abortflag;
  6024. int decompress;
  6025. int do_lzw;
  6026. int to_stdout;
  6027. int force;
  6028. int verbose;
  6029. int quiet;
  6030. int list;
  6031. int test;
  6032. int ext_header;
  6033. int pkzip;
  6034. int method;
  6035. int level;
  6036. int no_time;
  6037. int no_name;
  6038. int exit_code;
  6039. int lbits;
  6040. int dbits;
  6041. ulg window_size;
  6042. ulg crc;
  6043. ulg adler;
  6044. uch dist_code[512];
  6045. uch length_code[MAX_MATCH-MIN_MATCH+1];
  6046. int heap[2*L_CODES+1];
  6047. uch depth[2*L_CODES+1];
  6048. int base_length[LENGTH_CODES];
  6049. int base_dist[D_CODES];
  6050. ush bl_count[MAX_BITS+1];
  6051. uch flag_buf[(LIT_BUFSIZE/8)];
  6052. #ifdef DYN_ALLOC
  6053. uch *inbuf;
  6054. uch *outbuf;
  6055. ush *d_buf;
  6056. uch *window;
  6057. #else
  6058. uch inbuf [INBUFSIZ +INBUF_EXTRA];
  6059. uch outbuf[OUTBUFSIZ+OUTBUF_EXTRA];
  6060. ush d_buf [DIST_BUFSIZE];
  6061. uch window[2L*WSIZE];
  6062. #endif
  6063. #ifdef FULL_SEARCH
  6064. #define nice_match MAX_MATCH
  6065. #else
  6066. int nice_match;
  6067. #endif
  6068. #ifdef CRYPT
  6069. uch cc;
  6070. #endif
  6071. ct_data static_ltree[L_CODES+2];
  6072. ct_data static_dtree[D_CODES];
  6073. ct_data dyn_dtree[(2*D_CODES+1)];
  6074. ct_data dyn_ltree[HEAP_SIZE];
  6075. ct_data bl_tree[2*BL_CODES+1];
  6076. tree_desc l_desc;
  6077. tree_desc d_desc;
  6078. tree_desc bl_desc;
  6079. #ifndef MAXSEG_64K
  6080. ush prev2[1L<<BITS];
  6081. #define prev gz1->prev2
  6082. #define head (gz1->prev2+WSIZE)
  6083. #else
  6084. ush * prev2;
  6085. ush * tab_prefix1;
  6086. #define prev gz1->prev2
  6087. #define head gz1->tab_prefix1
  6088. #endif
  6089. } GZ1;
  6090. typedef GZ1 *PGZ1;
  6091. int gz1_size = sizeof( GZ1 );
  6092. /* Declare some local function protypes... */
  6093. /* Any routine name that can/might conflict with */
  6094. /* other modules or object code should simply have */
  6095. /* the standard prefix 'gz1_' added to the front. */
  6096. /* This will only usually be any kind of problem at all */
  6097. /* if the code is being compiled directly into the parent */
  6098. /* instead of being built as a standalone DLL or DSO library. */
  6099. PGZ1 gz1_init ( void );
  6100. int gz1_cleanup ( PGZ1 gz1 );
  6101. ulg gz1_deflate ( PGZ1 gz1 );
  6102. ulg gz1_deflate_fast( PGZ1 gz1 );
  6103. /* The rest of the routines should not need the 'gz1_' prefix. */
  6104. /* No conflicts reported at this time. */
  6105. int inflate ( PGZ1 gz1 );
  6106. int inflate_dynamic( PGZ1 gz1 );
  6107. int inflate_stored ( PGZ1 gz1 );
  6108. int inflate_fixed ( PGZ1 gz1 );
  6109. void fill_window ( PGZ1 gz1 );
  6110. void flush_outbuf ( PGZ1 gz1 );
  6111. void flush_window ( PGZ1 gz1 );
  6112. void bi_windup ( PGZ1 gz1 );
  6113. void set_file_type ( PGZ1 gz1 );
  6114. void init_block ( PGZ1 gz1 );
  6115. int build_bl_tree ( PGZ1 gz1 );
  6116. void read_error ( PGZ1 gz1 );
  6117. void write_error ( PGZ1 gz1 );
  6118. int get_header ( PGZ1 gz1, int in );
  6119. int inflate_block ( PGZ1 gz1, int *e );
  6120. int fill_inbuf ( PGZ1 gz1, int eof_ok );
  6121. char *gz1_basename ( PGZ1 gz1, char *fname );
  6122. int longest_match ( PGZ1 gz1, unsigned cur_match );
  6123. void bi_init ( PGZ1 gz1, gz1_file_t zipfile );
  6124. int file_read ( PGZ1 gz1, char *buf, unsigned size );
  6125. void write_buf ( PGZ1 gz1, int fd, voidp buf, unsigned cnt );
  6126. void error( char *msg );
  6127. /* XXX - Precomputed zlib header. If you change the window size or
  6128. * compression level from the defaults, this will break badly. The
  6129. * algorithm to build this is fairly complex; you can find it in
  6130. * the file deflate.c from the zlib distribution.
  6131. */
  6132. #define ZLIB_HEADER "\170œ"
  6133. ulg adler32(ulg adler, uch *buf, unsigned len);
  6134. int zip(
  6135. PGZ1 gz1,
  6136. int in,
  6137. int out
  6138. );
  6139. ulg flush_block(
  6140. PGZ1 gz1,
  6141. char *buf,
  6142. ulg stored_len,
  6143. int eof
  6144. );
  6145. void copy_block(
  6146. PGZ1 gz1,
  6147. char *buf,
  6148. unsigned len,
  6149. int header
  6150. );
  6151. int ct_tally(
  6152. PGZ1 gz1,
  6153. int dist,
  6154. int lc
  6155. );
  6156. void send_bits(
  6157. PGZ1 gz1,
  6158. int value,
  6159. int length
  6160. );
  6161. void send_tree(
  6162. PGZ1 gz1,
  6163. ct_data *tree,
  6164. int max_code
  6165. );
  6166. void send_all_trees(
  6167. PGZ1 gz1,
  6168. int lcodes,
  6169. int dcodes,
  6170. int blcodes
  6171. );
  6172. void ct_init(
  6173. PGZ1 gz1,
  6174. ush *attr,
  6175. int *methodp
  6176. );
  6177. void lm_init(
  6178. PGZ1 gz1,
  6179. int pack_level,
  6180. ush *flags
  6181. );
  6182. void build_tree(
  6183. PGZ1 gz1,
  6184. tree_desc *desc
  6185. );
  6186. void compress_block(
  6187. PGZ1 gz1,
  6188. ct_data *ltree,
  6189. ct_data *dtree
  6190. );
  6191. void gen_bitlen(
  6192. PGZ1 gz1,
  6193. tree_desc *desc
  6194. );
  6195. void pqdownheap(
  6196. PGZ1 gz1,
  6197. ct_data *tree,
  6198. int k
  6199. );
  6200. int huft_build(
  6201. PGZ1 gz1,
  6202. unsigned *b,
  6203. unsigned n,
  6204. unsigned s,
  6205. ush *d,
  6206. ush *e,
  6207. struct huft **t,
  6208. int *m
  6209. );
  6210. ulg updcrc(
  6211. PGZ1 gz1,
  6212. uch *s,
  6213. unsigned n
  6214. );
  6215. int inflate_codes(
  6216. PGZ1 gz1,
  6217. struct huft *tl,
  6218. struct huft *td,
  6219. int bl,
  6220. int bd
  6221. );
  6222. void gen_codes(
  6223. PGZ1 gz1,
  6224. ct_data *tree,
  6225. int max_code
  6226. );
  6227. void scan_tree(
  6228. PGZ1 gz1,
  6229. ct_data *tree,
  6230. int max_code
  6231. );
  6232. unsigned bi_reverse(
  6233. PGZ1 gz1,
  6234. unsigned code,
  6235. int len
  6236. );
  6237. int huft_free(
  6238. PGZ1 gz1,
  6239. struct huft *t
  6240. );
  6241. PGZ1 gz1_init()
  6242. {
  6243. PGZ1 gz1=0;
  6244. gz1 = (PGZ1) malloc( gz1_size );
  6245. if ( !gz1 )
  6246. {
  6247. return 0;
  6248. }
  6249. memset( gz1, 0, gz1_size );
  6250. ALLOC(uch, gz1->inbuf, INBUFSIZ +INBUF_EXTRA);
  6251. if ( !gz1->inbuf )
  6252. {
  6253. free( gz1 );
  6254. return 0;
  6255. }
  6256. ALLOC(uch, gz1->outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
  6257. if ( !gz1->outbuf )
  6258. {
  6259. FREE( gz1->inbuf );
  6260. free( gz1 );
  6261. return 0;
  6262. }
  6263. ALLOC(ush, gz1->d_buf, DIST_BUFSIZE);
  6264. if ( !gz1->d_buf )
  6265. {
  6266. FREE( gz1->outbuf );
  6267. FREE( gz1->inbuf );
  6268. free( gz1 );
  6269. return 0;
  6270. }
  6271. ALLOC(uch, gz1->window, 2L*WSIZE);
  6272. if ( !gz1->window )
  6273. {
  6274. FREE( gz1->d_buf );
  6275. FREE( gz1->outbuf );
  6276. FREE( gz1->inbuf );
  6277. free( gz1 );
  6278. return 0;
  6279. }
  6280. #ifndef MAXSEG_64K
  6281. #else
  6282. ALLOC(ush, gz1->prev2, 1L<<(BITS-1) );
  6283. if ( !gz1->prev2 )
  6284. {
  6285. FREE( gz1->window );
  6286. FREE( gz1->d_buf );
  6287. FREE( gz1->outbuf );
  6288. FREE( gz1->inbuf );
  6289. free( gz1 );
  6290. return 0;
  6291. }
  6292. ALLOC(ush, gz1->tab_prefix1, 1L<<(BITS-1) );
  6293. if ( !gz1->tab_prefix1 )
  6294. {
  6295. FREE( gz1->prev2 );
  6296. FREE( gz1->window );
  6297. FREE( gz1->d_buf );
  6298. FREE( gz1->outbuf );
  6299. FREE( gz1->inbuf );
  6300. free( gz1 );
  6301. return 0;
  6302. }
  6303. #endif
  6304. gz1->method = DEFLATED;
  6305. gz1->level = 6;
  6306. gz1->no_time = -1;
  6307. gz1->no_name = -1;
  6308. gz1->exit_code = OK;
  6309. gz1->lbits = 9;
  6310. gz1->dbits = 6;
  6311. gz1->window_size = (ulg)2*WSIZE;
  6312. gz1->crc = (ulg)0xffffffffL;
  6313. gz1->d_desc.dyn_tree = (ct_data *) gz1->dyn_dtree;
  6314. gz1->d_desc.static_tree = (ct_data *) gz1->static_dtree;
  6315. gz1->d_desc.extra_bits = (int *) extra_dbits;
  6316. gz1->d_desc.extra_base = (int ) 0;
  6317. gz1->d_desc.elems = (int ) D_CODES;
  6318. gz1->d_desc.max_length = (int ) MAX_BITS;
  6319. gz1->d_desc.max_code = (int ) 0;
  6320. gz1->l_desc.dyn_tree = (ct_data *) gz1->dyn_ltree;
  6321. gz1->l_desc.static_tree = (ct_data *) gz1->static_ltree;
  6322. gz1->l_desc.extra_bits = (int *) extra_lbits;
  6323. gz1->l_desc.extra_base = (int ) LITERALS+1;
  6324. gz1->l_desc.elems = (int ) L_CODES;
  6325. gz1->l_desc.max_length = (int ) MAX_BITS;
  6326. gz1->l_desc.max_code = (int ) 0;
  6327. gz1->bl_desc.dyn_tree = (ct_data *) gz1->bl_tree;
  6328. gz1->bl_desc.static_tree = (ct_data *) 0;
  6329. gz1->bl_desc.extra_bits = (int *) extra_blbits;
  6330. gz1->bl_desc.extra_base = (int ) 0;
  6331. gz1->bl_desc.elems = (int ) BL_CODES;
  6332. gz1->bl_desc.max_length = (int ) MAX_BL_BITS;
  6333. gz1->bl_desc.max_code = (int ) 0;
  6334. return (PGZ1) gz1;
  6335. }
  6336. int gz1_cleanup( PGZ1 gz1 )
  6337. {
  6338. #ifndef MAXSEG_64K
  6339. #else
  6340. FREE( gz1->tab_prefix1 );
  6341. FREE( gz1->prev2 );
  6342. #endif
  6343. FREE( gz1->window );
  6344. FREE( gz1->d_buf );
  6345. FREE( gz1->outbuf );
  6346. FREE( gz1->inbuf );
  6347. free( gz1 );
  6348. gz1 = 0;
  6349. return 0;
  6350. }
  6351. int (*read_buf)(PGZ1 gz1, char *buf, unsigned size);
  6352. void error( char *msg )
  6353. {
  6354. msg = msg;
  6355. }
  6356. int (*work)( PGZ1 gz1, int infile, int outfile ) = 0;
  6357. #ifdef __BORLANDC__
  6358. #pragma argsused
  6359. #endif
  6360. int get_header( PGZ1 gz1, int in )
  6361. {
  6362. uch flags;
  6363. char magic[2];
  6364. ulg stamp;
  6365. unsigned len;
  6366. unsigned part;
  6367. if ( gz1->force && gz1->to_stdout )
  6368. {
  6369. magic[0] = (char)try_byte();
  6370. magic[1] = (char)try_byte();
  6371. }
  6372. else
  6373. {
  6374. magic[0] = (char)get_byte();
  6375. magic[1] = (char)get_byte();
  6376. }
  6377. gz1->method = -1;
  6378. gz1->header_bytes = 0;
  6379. gz1->last_member = RECORD_IO;
  6380. gz1->part_nb++;
  6381. if ( memcmp(magic, GZIP_MAGIC, 2 ) == 0 ||
  6382. memcmp(magic, OLD_GZIP_MAGIC, 2 ) == 0 )
  6383. {
  6384. gz1->method = (int)get_byte();
  6385. if ( gz1->method != DEFLATED )
  6386. {
  6387. gz1->exit_code = LZ1_ERROR;
  6388. return -1;
  6389. }
  6390. return -1;
  6391. if ((flags & ENCRYPTED) != 0)
  6392. {
  6393. gz1->exit_code = LZ1_ERROR;
  6394. return -1;
  6395. }
  6396. if ((flags & CONTINUATION) != 0)
  6397. {
  6398. gz1->exit_code = LZ1_ERROR;
  6399. if ( gz1->force <= 1) return -1;
  6400. }
  6401. if ((flags & RESERVED) != 0)
  6402. {
  6403. gz1->exit_code = LZ1_ERROR;
  6404. if ( gz1->force <= 1)
  6405. return -1;
  6406. }
  6407. stamp = (ulg)get_byte();
  6408. stamp |= ((ulg)get_byte()) << 8;
  6409. stamp |= ((ulg)get_byte()) << 16;
  6410. stamp |= ((ulg)get_byte()) << 24;
  6411. if ( stamp != 0 && !gz1->no_time )
  6412. {
  6413. gz1->time_stamp = stamp;
  6414. }
  6415. (void)get_byte();
  6416. (void)get_byte();
  6417. if ((flags & CONTINUATION) != 0)
  6418. {
  6419. part = (unsigned) get_byte();
  6420. part |= ((unsigned) get_byte())<<8;
  6421. }
  6422. if ((flags & EXTRA_FIELD) != 0)
  6423. {
  6424. len = (unsigned) get_byte();
  6425. len |= ((unsigned) get_byte())<<8;
  6426. while (len--) (void)get_byte();
  6427. }
  6428. if ((flags & COMMENT) != 0)
  6429. {
  6430. while (get_char() != 0) ;
  6431. }
  6432. if ( gz1->part_nb == 1 )
  6433. {
  6434. gz1->header_bytes = gz1->inptr + 2*sizeof(long);
  6435. }
  6436. }
  6437. return gz1->method;
  6438. }
  6439. int fill_inbuf( PGZ1 gz1, int eof_ok )
  6440. {
  6441. int len;
  6442. int bytes_to_copy;
  6443. gz1->insize = 0;
  6444. errno = 0;
  6445. do {
  6446. if ( gz1->input_ismem )
  6447. {
  6448. if ( gz1->input_bytesleft > 0 )
  6449. {
  6450. bytes_to_copy = INBUFSIZ - gz1->insize;
  6451. if ( bytes_to_copy > gz1->input_bytesleft )
  6452. {
  6453. bytes_to_copy = gz1->input_bytesleft;
  6454. }
  6455. memcpy(
  6456. (char*)gz1->inbuf+gz1->insize,
  6457. gz1->input_ptr,
  6458. bytes_to_copy
  6459. );
  6460. gz1->input_ptr += bytes_to_copy;
  6461. gz1->input_bytesleft -= bytes_to_copy;
  6462. len = bytes_to_copy;
  6463. }
  6464. else
  6465. {
  6466. len = 0;
  6467. }
  6468. }
  6469. else
  6470. {
  6471. len =
  6472. read(
  6473. gz1->ifd,
  6474. (char*)gz1->inbuf+gz1->insize,
  6475. INBUFSIZ-gz1->insize
  6476. );
  6477. }
  6478. if (len == 0 || len == EOF) break;
  6479. gz1->insize += len;
  6480. } while( gz1->insize < INBUFSIZ );
  6481. if ( gz1->insize == 0 )
  6482. {
  6483. if( eof_ok ) return EOF;
  6484. read_error( gz1 );
  6485. }
  6486. gz1->bytes_in += (ulg) gz1->insize;
  6487. gz1->inptr = 1;
  6488. return gz1->inbuf[0];
  6489. }
  6490. ulg updcrc(
  6491. PGZ1 gz1,
  6492. uch *s,
  6493. unsigned n
  6494. )
  6495. {
  6496. register ulg c;
  6497. if ( s == NULL )
  6498. {
  6499. c = 0xffffffffL;
  6500. }
  6501. else
  6502. {
  6503. c = gz1->crc;
  6504. if ( n )
  6505. {
  6506. do{
  6507. c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
  6508. } while( --n );
  6509. }
  6510. }
  6511. gz1->crc = c;
  6512. return( c ^ 0xffffffffL );
  6513. }
  6514. void read_error( PGZ1 gz1 )
  6515. {
  6516. gz1->abortflag = 1;
  6517. }
  6518. void mod_gzip_strlwr( char *s )
  6519. {
  6520. char *p1=s;
  6521. if ( s == 0 ) return;
  6522. while ( *p1 != 0 )
  6523. {
  6524. if ( *p1 > 96 ) *p1 = *p1 - 32;
  6525. p1++;
  6526. }
  6527. }
  6528. #ifdef __BORLANDC__
  6529. #pragma argsused
  6530. #endif
  6531. char *gz1_basename( PGZ1 gz1, char *fname )
  6532. {
  6533. char *p;
  6534. if ((p = strrchr(fname, PATH_SEP)) != NULL) fname = p+1;
  6535. #ifdef PATH_SEP2
  6536. if ((p = strrchr(fname, PATH_SEP2)) != NULL) fname = p+1;
  6537. #endif
  6538. #ifdef PATH_SEP3
  6539. if ((p = strrchr(fname, PATH_SEP3)) != NULL) fname = p+1;
  6540. #endif
  6541. #ifdef SUFFIX_SEP
  6542. if ((p = strrchr(fname, SUFFIX_SEP)) != NULL) *p = '\0';
  6543. #endif
  6544. if (casemap('A') == 'a') mod_gzip_strlwr(fname);
  6545. return fname;
  6546. }
  6547. void write_buf( PGZ1 gz1, int fd, voidp buf, unsigned cnt )
  6548. {
  6549. unsigned n;
  6550. if ( gz1->output_ismem )
  6551. {
  6552. if ( ( gz1->bytes_out + cnt ) < gz1->output_maxlen )
  6553. {
  6554. memcpy( gz1->output_ptr, buf, cnt );
  6555. gz1->output_ptr += cnt;
  6556. }
  6557. else
  6558. {
  6559. write_error( gz1 );
  6560. }
  6561. }
  6562. else
  6563. {
  6564. while ((n = write(fd, buf, cnt)) != cnt)
  6565. {
  6566. if (n == (unsigned)(-1))
  6567. {
  6568. write_error( gz1 );
  6569. }
  6570. cnt -= n;
  6571. buf = (voidp)((char*)buf+n);
  6572. }
  6573. }
  6574. }
  6575. void write_error( PGZ1 gz1 )
  6576. {
  6577. gz1->abortflag = 1;
  6578. }
  6579. #ifdef __TURBOC__
  6580. #ifndef BC55
  6581. static ush ptr_offset = 0;
  6582. void * fcalloc(
  6583. unsigned items,
  6584. unsigned size
  6585. )
  6586. {
  6587. void * buf = farmalloc((ulg)items*size + 16L);
  6588. if (buf == NULL) return NULL;
  6589. if (ptr_offset == 0)
  6590. {
  6591. ptr_offset = (ush)((uch*)buf-0);
  6592. }
  6593. else if (ptr_offset != (ush)((uch*)buf-0))
  6594. {
  6595. error("inconsistent ptr_offset");
  6596. }
  6597. *((ush*)&buf+1) += (ptr_offset + 15) >> 4;
  6598. *(ush*)&buf = 0;
  6599. return buf;
  6600. }
  6601. void fcfree( void *ptr )
  6602. {
  6603. *((ush*)&ptr+1) -= (ptr_offset + 15) >> 4;
  6604. *(ush*)&ptr = ptr_offset;
  6605. farfree(ptr);
  6606. }
  6607. #endif
  6608. #endif
  6609. int zip(
  6610. PGZ1 gz1,
  6611. int in,
  6612. int out
  6613. )
  6614. {
  6615. uch flags = 0;
  6616. ush attr = 0;
  6617. ush deflate_flags = 0;
  6618. gz1->ifd = in;
  6619. gz1->ofd = out;
  6620. gz1->outcnt = 0;
  6621. gz1->method = DEFLATED;
  6622. put_byte(GZIP_MAGIC[0]);
  6623. put_byte(GZIP_MAGIC[1]);
  6624. put_byte(DEFLATED);
  6625. if ( gz1->save_orig_name )
  6626. {
  6627. flags |= ORIG_NAME;
  6628. }
  6629. put_byte(flags);
  6630. put_long(gz1->time_stamp);
  6631. gz1->crc = -1;
  6632. updcrc( gz1, NULL, 0 );
  6633. bi_init( gz1, out );
  6634. ct_init( gz1, &attr, &gz1->method );
  6635. lm_init( gz1, gz1->level, &deflate_flags );
  6636. put_byte((uch)deflate_flags);
  6637. put_byte(OS_CODE);
  6638. if ( gz1->save_orig_name )
  6639. {
  6640. char *p = gz1_basename( gz1, gz1->ifname );
  6641. do {
  6642. put_char(*p);
  6643. } while (*p++);
  6644. }
  6645. gz1->header_bytes = (long)gz1->outcnt;
  6646. (void) gz1_deflate( gz1 );
  6647. put_long( gz1->crc );
  6648. put_long( gz1->bytes_in );
  6649. gz1->header_bytes += 2*sizeof(long);
  6650. flush_outbuf( gz1 );
  6651. return OK;
  6652. }
  6653. ulg gz1_deflate( PGZ1 gz1 )
  6654. {
  6655. unsigned hash_head;
  6656. unsigned prev_match;
  6657. int flush;
  6658. int match_available = 0;
  6659. register unsigned match_length = MIN_MATCH-1;
  6660. #ifdef DEBUG
  6661. long isize;
  6662. #endif
  6663. if (gz1->compr_level <= 3)
  6664. {
  6665. return gz1_deflate_fast(gz1);
  6666. }
  6667. while (gz1->lookahead != 0)
  6668. {
  6669. gz1->ins_h =
  6670. (((gz1->ins_h)<<H_SHIFT) ^ (gz1->window[gz1->strstart+MIN_MATCH-1])) & HASH_MASK;
  6671. prev[ gz1->strstart & WMASK ] = hash_head = head[ gz1->ins_h ];
  6672. head[ gz1->ins_h ] = gz1->strstart;
  6673. gz1->prev_length = match_length, prev_match = gz1->match_start;
  6674. match_length = MIN_MATCH-1;
  6675. if (hash_head != NIL && gz1->prev_length < gz1->max_lazy_match &&
  6676. gz1->strstart - hash_head <= MAX_DIST) {
  6677. match_length = longest_match( gz1, hash_head );
  6678. if (match_length > gz1->lookahead) match_length = gz1->lookahead;
  6679. if (match_length == MIN_MATCH && gz1->strstart-gz1->match_start > TOO_FAR){
  6680. match_length--;
  6681. }
  6682. }
  6683. if (gz1->prev_length >= MIN_MATCH && match_length <= gz1->prev_length) {
  6684. flush = ct_tally(gz1,gz1->strstart-1-prev_match, gz1->prev_length - MIN_MATCH);
  6685. gz1->lookahead -= ( gz1->prev_length - 1 );
  6686. gz1->prev_length -= 2;
  6687. do {
  6688. gz1->strstart++;
  6689. gz1->ins_h =
  6690. (((gz1->ins_h)<<H_SHIFT) ^ (gz1->window[ gz1->strstart + MIN_MATCH-1])) & HASH_MASK;
  6691. prev[ gz1->strstart & WMASK ] = hash_head = head[gz1->ins_h];
  6692. head[ gz1->ins_h ] = gz1->strstart;
  6693. } while (--gz1->prev_length != 0);
  6694. match_available = 0;
  6695. match_length = MIN_MATCH-1;
  6696. gz1->strstart++;
  6697. if (flush) FLUSH_BLOCK(0), gz1->block_start = gz1->strstart;
  6698. } else if (match_available) {
  6699. if (ct_tally( gz1, 0, gz1->window[gz1->strstart-1] )) {
  6700. FLUSH_BLOCK(0), gz1->block_start = gz1->strstart;
  6701. }
  6702. gz1->strstart++;
  6703. gz1->lookahead--;
  6704. } else {
  6705. match_available = 1;
  6706. gz1->strstart++;
  6707. gz1->lookahead--;
  6708. }
  6709. while (gz1->lookahead < MIN_LOOKAHEAD && !gz1->eofile) fill_window(gz1);
  6710. }
  6711. if (match_available) ct_tally( gz1, 0, gz1->window[gz1->strstart-1] );
  6712. return FLUSH_BLOCK(1);
  6713. return 0;
  6714. }
  6715. void flush_outbuf( PGZ1 gz1 )
  6716. {
  6717. if ( gz1->outcnt == 0 )
  6718. {
  6719. return;
  6720. }
  6721. write_buf( gz1, gz1->ofd, (char *)gz1->outbuf, gz1->outcnt );
  6722. gz1->bytes_out += (ulg)gz1->outcnt;
  6723. gz1->outcnt = 0;
  6724. }
  6725. void lm_init(
  6726. PGZ1 gz1,
  6727. int pack_level,
  6728. ush *flags
  6729. )
  6730. {
  6731. register unsigned j;
  6732. if ( pack_level < 1 || pack_level > 9 )
  6733. {
  6734. error("bad pack level");
  6735. }
  6736. gz1->compr_level = pack_level;
  6737. #if defined(MAXSEG_64K) && HASH_BITS == 15
  6738. for (j = 0; j < HASH_SIZE; j++) head[j] = NIL;
  6739. #else
  6740. memset( (char*)head, 0, (HASH_SIZE*sizeof(*head)) );
  6741. #endif
  6742. gz1->max_lazy_match = configuration_table[pack_level].max_lazy;
  6743. gz1->good_match = configuration_table[pack_level].good_length;
  6744. #ifndef FULL_SEARCH
  6745. gz1->nice_match = configuration_table[pack_level].nice_length;
  6746. #endif
  6747. gz1->max_chain_length = configuration_table[pack_level].max_chain;
  6748. if ( pack_level == 1 )
  6749. {
  6750. *flags |= FAST;
  6751. }
  6752. else if ( pack_level == 9 )
  6753. {
  6754. *flags |= SLOW;
  6755. }
  6756. gz1->strstart = 0;
  6757. gz1->block_start = 0L;
  6758. #ifdef ASMV
  6759. match_init();
  6760. #endif
  6761. gz1->lookahead = read_buf(gz1,(char*)gz1->window,
  6762. sizeof(int) <= 2 ? (unsigned)WSIZE : 2*WSIZE);
  6763. if (gz1->lookahead == 0 || gz1->lookahead == (unsigned)EOF)
  6764. {
  6765. gz1->eofile = 1, gz1->lookahead = 0;
  6766. return;
  6767. }
  6768. gz1->eofile = 0;
  6769. while (gz1->lookahead < MIN_LOOKAHEAD && !gz1->eofile)
  6770. {
  6771. fill_window(gz1);
  6772. }
  6773. gz1->ins_h = 0;
  6774. for ( j=0; j<MIN_MATCH-1; j++ )
  6775. {
  6776. gz1->ins_h =
  6777. (((gz1->ins_h)<<H_SHIFT) ^ (gz1->window[j])) & HASH_MASK;
  6778. }
  6779. }
  6780. void fill_window( PGZ1 gz1 )
  6781. {
  6782. register unsigned n, m;
  6783. unsigned more =
  6784. (unsigned)( gz1->window_size - (ulg)gz1->lookahead - (ulg)gz1->strstart );
  6785. if ( more == (unsigned)EOF)
  6786. {
  6787. more--;
  6788. }
  6789. else if ( gz1->strstart >= WSIZE+MAX_DIST )
  6790. {
  6791. memcpy((char*)gz1->window, (char*)gz1->window+WSIZE, (unsigned)WSIZE);
  6792. gz1->match_start -= WSIZE;
  6793. gz1->strstart -= WSIZE;
  6794. gz1->block_start -= (long) WSIZE;
  6795. for ( n = 0; n < HASH_SIZE; n++ )
  6796. {
  6797. m = head[n];
  6798. head[n] = (ush)(m >= WSIZE ? m-WSIZE : NIL);
  6799. }
  6800. for ( n = 0; n < WSIZE; n++ )
  6801. {
  6802. m = prev[n];
  6803. prev[n] = (ush)(m >= WSIZE ? m-WSIZE : NIL);
  6804. }
  6805. more += WSIZE;
  6806. }
  6807. if ( !gz1->eofile )
  6808. {
  6809. n = read_buf(gz1,(char*)gz1->window+gz1->strstart+gz1->lookahead, more);
  6810. if ( n == 0 || n == (unsigned)EOF )
  6811. {
  6812. gz1->eofile = 1;
  6813. }
  6814. else
  6815. {
  6816. gz1->lookahead += n;
  6817. }
  6818. }
  6819. }
  6820. ulg gz1_deflate_fast( PGZ1 gz1 )
  6821. {
  6822. unsigned hash_head;
  6823. int flush;
  6824. unsigned match_length = 0;
  6825. gz1->prev_length = MIN_MATCH-1;
  6826. while (gz1->lookahead != 0)
  6827. {
  6828. gz1->ins_h =
  6829. (((gz1->ins_h)<<H_SHIFT) ^ (gz1->window[ gz1->strstart + MIN_MATCH-1])) & HASH_MASK;
  6830. prev[ gz1->strstart & WMASK ] = hash_head = head[ gz1->ins_h ];
  6831. head[ gz1->ins_h ] = gz1->strstart;
  6832. if (hash_head != NIL && gz1->strstart - hash_head <= MAX_DIST) {
  6833. match_length = longest_match( gz1, hash_head );
  6834. if (match_length > gz1->lookahead) match_length = gz1->lookahead;
  6835. }
  6836. if (match_length >= MIN_MATCH) {
  6837. flush = ct_tally(gz1,gz1->strstart-gz1->match_start, match_length - MIN_MATCH);
  6838. gz1->lookahead -= match_length;
  6839. if (match_length <= gz1->max_lazy_match )
  6840. {
  6841. match_length--;
  6842. do {
  6843. gz1->strstart++;
  6844. gz1->ins_h =
  6845. (((gz1->ins_h)<<H_SHIFT) ^ (gz1->window[ gz1->strstart + MIN_MATCH-1])) & HASH_MASK;
  6846. prev[ gz1->strstart & WMASK ] = hash_head = head[ gz1->ins_h ];
  6847. head[ gz1->ins_h ] = gz1->strstart;
  6848. } while (--match_length != 0);
  6849. gz1->strstart++;
  6850. } else {
  6851. gz1->strstart += match_length;
  6852. match_length = 0;
  6853. gz1->ins_h = gz1->window[gz1->strstart];
  6854. gz1->ins_h =
  6855. (((gz1->ins_h)<<H_SHIFT) ^ (gz1->window[gz1->strstart+1])) & HASH_MASK;
  6856. #if MIN_MATCH != 3
  6857. Call UPDATE_HASH() MIN_MATCH-3 more times
  6858. #endif
  6859. }
  6860. } else {
  6861. flush = ct_tally(gz1, 0, gz1->window[gz1->strstart]);
  6862. gz1->lookahead--;
  6863. gz1->strstart++;
  6864. }
  6865. if (flush) FLUSH_BLOCK(0), gz1->block_start = gz1->strstart;
  6866. while (gz1->lookahead < MIN_LOOKAHEAD && !gz1->eofile) fill_window(gz1);
  6867. }
  6868. return FLUSH_BLOCK(1);
  6869. }
  6870. void ct_init(
  6871. PGZ1 gz1,
  6872. ush *attr,
  6873. int *methodp
  6874. )
  6875. {
  6876. #ifdef DD1
  6877. int i,ii;
  6878. #endif
  6879. int n;
  6880. int bits;
  6881. int length;
  6882. int code;
  6883. int dist;
  6884. gz1->file_type = attr;
  6885. gz1->file_method = methodp;
  6886. gz1->compressed_len = gz1->input_len = 0L;
  6887. if ( gz1->static_dtree[0].dl.len != 0 )
  6888. {
  6889. return;
  6890. }
  6891. length = 0;
  6892. for ( code = 0; code < LENGTH_CODES-1; code++ )
  6893. {
  6894. gz1->base_length[code] = length;
  6895. for ( n = 0; n < (1<<extra_lbits[code]); n++ )
  6896. {
  6897. gz1->length_code[length++] = (uch)code;
  6898. }
  6899. }
  6900. gz1->length_code[length-1] = (uch)code;
  6901. dist = 0;
  6902. for ( code = 0 ; code < 16; code++ )
  6903. {
  6904. gz1->base_dist[code] = dist;
  6905. for ( n = 0; n < (1<<extra_dbits[code]); n++ )
  6906. {
  6907. gz1->dist_code[dist++] = (uch)code;
  6908. }
  6909. }
  6910. dist >>= 7;
  6911. for ( ; code < D_CODES; code++ )
  6912. {
  6913. gz1->base_dist[code] = dist << 7;
  6914. for ( n = 0; n < (1<<(extra_dbits[code]-7)); n++ )
  6915. {
  6916. gz1->dist_code[256 + dist++] = (uch)code;
  6917. }
  6918. }
  6919. for ( bits = 0; bits <= MAX_BITS; bits++ )
  6920. {
  6921. gz1->bl_count[bits] = 0;
  6922. }
  6923. n = 0;
  6924. while (n <= 143) gz1->static_ltree[n++].dl.len = 8, gz1->bl_count[8]++;
  6925. while (n <= 255) gz1->static_ltree[n++].dl.len = 9, gz1->bl_count[9]++;
  6926. while (n <= 279) gz1->static_ltree[n++].dl.len = 7, gz1->bl_count[7]++;
  6927. while (n <= 287) gz1->static_ltree[n++].dl.len = 8, gz1->bl_count[8]++;
  6928. gen_codes(gz1,(ct_data *)gz1->static_ltree, L_CODES+1);
  6929. for ( n = 0; n < D_CODES; n++ )
  6930. {
  6931. gz1->static_dtree[n].dl.len = 5;
  6932. gz1->static_dtree[n].fc.code = bi_reverse( gz1, n, 5 );
  6933. }
  6934. init_block( gz1 );
  6935. }
  6936. ulg flush_block(
  6937. PGZ1 gz1,
  6938. char *buf,
  6939. ulg stored_len,
  6940. int eof
  6941. )
  6942. {
  6943. ulg opt_lenb;
  6944. ulg static_lenb;
  6945. int max_blindex;
  6946. gz1->flag_buf[gz1->last_flags] = gz1->flags;
  6947. if (*gz1->file_type == (ush)UNKNOWN) set_file_type(gz1);
  6948. build_tree( gz1, (tree_desc *)(&gz1->l_desc) );
  6949. build_tree( gz1, (tree_desc *)(&gz1->d_desc) );
  6950. max_blindex = build_bl_tree( gz1 );
  6951. opt_lenb = (gz1->opt_len+3+7)>>3;
  6952. static_lenb = (gz1->static_len+3+7)>>3;
  6953. gz1->input_len += stored_len;
  6954. if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
  6955. #ifdef FORCE_METHOD
  6956. if ( level == 1 && eof && gz1->compressed_len == 0L )
  6957. #else
  6958. if (stored_len <= opt_lenb && eof && gz1->compressed_len == 0L && 0 )
  6959. #endif
  6960. {
  6961. if (buf == (char*)0) error ("block vanished");
  6962. copy_block( gz1, buf, (unsigned)stored_len, 0 );
  6963. gz1->compressed_len = stored_len << 3;
  6964. *gz1->file_method = STORED;
  6965. #ifdef FORCE_METHOD
  6966. } else if (level == 2 && buf != (char*)0) {
  6967. #else
  6968. } else if (stored_len+4 <= opt_lenb && buf != (char*)0) {
  6969. #endif
  6970. send_bits(gz1,(STORED_BLOCK<<1)+eof, 3);
  6971. gz1->compressed_len = (gz1->compressed_len + 3 + 7) & ~7L;
  6972. gz1->compressed_len += (stored_len + 4) << 3;
  6973. copy_block(gz1, buf, (unsigned)stored_len, 1);
  6974. #ifdef FORCE_METHOD
  6975. } else if (level == 3) {
  6976. #else
  6977. } else if (static_lenb == opt_lenb) {
  6978. #endif
  6979. send_bits(gz1,(STATIC_TREES<<1)+eof, 3);
  6980. compress_block(
  6981. gz1,
  6982. (ct_data *)gz1->static_ltree,
  6983. (ct_data *)gz1->static_dtree
  6984. );
  6985. gz1->compressed_len += 3 + gz1->static_len;
  6986. }
  6987. else
  6988. {
  6989. send_bits(gz1,(DYN_TREES<<1)+eof, 3);
  6990. send_all_trees(
  6991. gz1,
  6992. gz1->l_desc.max_code+1,
  6993. gz1->d_desc.max_code+1,
  6994. max_blindex+1
  6995. );
  6996. compress_block(
  6997. gz1,
  6998. (ct_data *)gz1->dyn_ltree,
  6999. (ct_data *)gz1->dyn_dtree
  7000. );
  7001. gz1->compressed_len += 3 + gz1->opt_len;
  7002. }
  7003. init_block( gz1 );
  7004. if ( eof )
  7005. {
  7006. bi_windup( gz1 );
  7007. gz1->compressed_len += 7;
  7008. }
  7009. return gz1->compressed_len >> 3;
  7010. }
  7011. #ifdef __BORLANDC__
  7012. #pragma argsused
  7013. #endif
  7014. unsigned bi_reverse(
  7015. PGZ1 gz1,
  7016. unsigned code,
  7017. int len
  7018. )
  7019. {
  7020. register unsigned res = 0;
  7021. do {
  7022. res |= code & 1;
  7023. code >>= 1, res <<= 1;
  7024. } while (--len > 0);
  7025. return res >> 1;
  7026. }
  7027. void set_file_type( PGZ1 gz1 )
  7028. {
  7029. int n = 0;
  7030. unsigned ascii_freq = 0;
  7031. unsigned bin_freq = 0;
  7032. while (n < 7) bin_freq += gz1->dyn_ltree[n++].fc.freq;
  7033. while (n < 128) ascii_freq += gz1->dyn_ltree[n++].fc.freq;
  7034. while (n < LITERALS) bin_freq += gz1->dyn_ltree[n++].fc.freq;
  7035. *gz1->file_type = bin_freq > (ascii_freq >> 2) ? BINARY : ASCII;
  7036. }
  7037. void init_block( PGZ1 gz1 )
  7038. {
  7039. int n;
  7040. for (n = 0; n < L_CODES; n++) gz1->dyn_ltree[n].fc.freq = 0;
  7041. for (n = 0; n < D_CODES; n++) gz1->dyn_dtree[n].fc.freq = 0;
  7042. for (n = 0; n < BL_CODES; n++) gz1->bl_tree[n].fc.freq = 0;
  7043. gz1->dyn_ltree[END_BLOCK].fc.freq = 1;
  7044. gz1->opt_len = 0L;
  7045. gz1->static_len = 0L;
  7046. gz1->last_lit = 0;
  7047. gz1->last_dist = 0;
  7048. gz1->last_flags = 0;
  7049. gz1->flags = 0;
  7050. gz1->flag_bit = 1;
  7051. }
  7052. void bi_init( PGZ1 gz1, gz1_file_t zipfile )
  7053. {
  7054. gz1->zfile = zipfile;
  7055. gz1->bi_buf = 0;
  7056. gz1->bi_valid = 0;
  7057. if ( gz1->zfile != NO_FILE )
  7058. {
  7059. read_buf = file_read;
  7060. }
  7061. }
  7062. int ct_tally(
  7063. PGZ1 gz1,
  7064. int dist,
  7065. int lc
  7066. )
  7067. {
  7068. int dcode;
  7069. gz1->inbuf[gz1->last_lit++] = (uch)lc;
  7070. if ( dist == 0 )
  7071. {
  7072. gz1->dyn_ltree[lc].fc.freq++;
  7073. }
  7074. else
  7075. {
  7076. dist--;
  7077. gz1->dyn_ltree[gz1->length_code[lc]+LITERALS+1].fc.freq++;
  7078. gz1->dyn_dtree[d_code(dist)].fc.freq++;
  7079. gz1->d_buf[gz1->last_dist++] = (ush)dist;
  7080. gz1->flags |= gz1->flag_bit;
  7081. }
  7082. gz1->flag_bit <<= 1;
  7083. if ( (gz1->last_lit & 7) == 0 )
  7084. {
  7085. gz1->flag_buf[gz1->last_flags++] = gz1->flags;
  7086. gz1->flags = 0, gz1->flag_bit = 1;
  7087. }
  7088. if ( gz1->level > 2 && (gz1->last_lit & 0xfff) == 0)
  7089. {
  7090. ulg out_length = (ulg) ( gz1->last_lit * 8L );
  7091. ulg in_length = (ulg) ( gz1->strstart - gz1->block_start );
  7092. for ( dcode = 0; dcode < D_CODES; dcode++ )
  7093. {
  7094. out_length += (ulg) ((gz1->dyn_dtree[dcode].fc.freq)*(5L+extra_dbits[dcode]));
  7095. }
  7096. out_length >>= 3;
  7097. if ( gz1->last_dist < gz1->last_lit/2 && out_length < in_length/2 )
  7098. {
  7099. return 1;
  7100. }
  7101. }
  7102. return( gz1->last_lit == LIT_BUFSIZE-1 || gz1->last_dist == DIST_BUFSIZE );
  7103. }
  7104. void compress_block(
  7105. PGZ1 gz1,
  7106. ct_data *ltree,
  7107. ct_data *dtree
  7108. )
  7109. {
  7110. unsigned dist;
  7111. int lc;
  7112. unsigned lx = 0;
  7113. unsigned dx = 0;
  7114. unsigned fx = 0;
  7115. uch flag = 0;
  7116. unsigned code;
  7117. int extra;
  7118. if (gz1->last_lit != 0) do {
  7119. if ((lx & 7) == 0) flag = gz1->flag_buf[fx++];
  7120. lc = gz1->inbuf[lx++];
  7121. if ((flag & 1) == 0) {
  7122. send_code(lc, ltree);
  7123. } else {
  7124. code = gz1->length_code[lc];
  7125. send_code(code+LITERALS+1, ltree);
  7126. extra = extra_lbits[code];
  7127. if (extra != 0) {
  7128. lc -= gz1->base_length[code];
  7129. send_bits(gz1,lc, extra);
  7130. }
  7131. dist = gz1->d_buf[dx++];
  7132. code = d_code(dist);
  7133. send_code(code, dtree);
  7134. extra = extra_dbits[code];
  7135. if (extra != 0) {
  7136. dist -= gz1->base_dist[code];
  7137. send_bits(gz1,dist, extra);
  7138. }
  7139. }
  7140. flag >>= 1;
  7141. } while (lx < gz1->last_lit);
  7142. send_code(END_BLOCK, ltree);
  7143. }
  7144. #ifndef ASMV
  7145. int longest_match( PGZ1 gz1, unsigned cur_match )
  7146. {
  7147. unsigned chain_length = gz1->max_chain_length;
  7148. register uch *scan = gz1->window + gz1->strstart;
  7149. register uch *match;
  7150. register int len;
  7151. int best_len = gz1->prev_length;
  7152. unsigned limit = gz1->strstart > (unsigned)MAX_DIST ? gz1->strstart - (unsigned)MAX_DIST : NIL;
  7153. #if HASH_BITS < 8 || MAX_MATCH != 258
  7154. error: Code too clever
  7155. #endif
  7156. #ifdef UNALIGNED_OK
  7157. register uch *strend = gz1->window + gz1->strstart + MAX_MATCH - 1;
  7158. register ush scan_start = *(ush*)scan;
  7159. register ush scan_end = *(ush*)(scan+best_len-1);
  7160. #else
  7161. register uch *strend = gz1->window + gz1->strstart + MAX_MATCH;
  7162. register uch scan_end1 = scan[best_len-1];
  7163. register uch scan_end = scan[best_len];
  7164. #endif
  7165. if (gz1->prev_length >= gz1->good_match) {
  7166. chain_length >>= 2;
  7167. }
  7168. do {
  7169. match = gz1->window + cur_match;
  7170. #if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
  7171. if (*(ush*)(match+best_len-1) != scan_end ||
  7172. *(ush*)match != scan_start) continue;
  7173. scan++, match++;
  7174. do {
  7175. } while (*(ush*)(scan+=2) == *(ush*)(match+=2) &&
  7176. *(ush*)(scan+=2) == *(ush*)(match+=2) &&
  7177. *(ush*)(scan+=2) == *(ush*)(match+=2) &&
  7178. *(ush*)(scan+=2) == *(ush*)(match+=2) &&
  7179. scan < strend);
  7180. if (*scan == *match) scan++;
  7181. len = (MAX_MATCH - 1) - (int)(strend-scan);
  7182. scan = strend - (MAX_MATCH-1);
  7183. #else
  7184. if (match[best_len] != scan_end ||
  7185. match[best_len-1] != scan_end1 ||
  7186. *match != *scan ||
  7187. *++match != scan[1]) continue;
  7188. scan += 2, match++;
  7189. do {
  7190. } while (*++scan == *++match && *++scan == *++match &&
  7191. *++scan == *++match && *++scan == *++match &&
  7192. *++scan == *++match && *++scan == *++match &&
  7193. *++scan == *++match && *++scan == *++match &&
  7194. scan < strend);
  7195. len = MAX_MATCH - (int)(strend - scan);
  7196. scan = strend - MAX_MATCH;
  7197. #endif
  7198. if (len > best_len) {
  7199. gz1->match_start = cur_match;
  7200. best_len = len;
  7201. if (len >= gz1->nice_match) break;
  7202. #ifdef UNALIGNED_OK
  7203. scan_end = *(ush*)(scan+best_len-1);
  7204. #else
  7205. scan_end1 = scan[best_len-1];
  7206. scan_end = scan[best_len];
  7207. #endif
  7208. }
  7209. } while ((cur_match = prev[cur_match & WMASK]) > limit
  7210. && --chain_length != 0);
  7211. return best_len;
  7212. }
  7213. #endif
  7214. void send_bits(
  7215. PGZ1 gz1,
  7216. int value,
  7217. int length
  7218. )
  7219. {
  7220. if ( gz1->bi_valid > (int) BUFSIZE - length )
  7221. {
  7222. gz1->bi_buf |= (value << gz1->bi_valid);
  7223. put_short(gz1->bi_buf);
  7224. gz1->bi_buf = (ush)value >> (BUFSIZE - gz1->bi_valid);
  7225. gz1->bi_valid += length - BUFSIZE;
  7226. }
  7227. else
  7228. {
  7229. gz1->bi_buf |= value << gz1->bi_valid;
  7230. gz1->bi_valid += length;
  7231. }
  7232. }
  7233. void build_tree(
  7234. PGZ1 gz1,
  7235. tree_desc *desc
  7236. )
  7237. {
  7238. int elems = desc->elems;
  7239. ct_data *tree = desc->dyn_tree;
  7240. ct_data *stree = desc->static_tree;
  7241. int n;
  7242. int m;
  7243. int max_code = -1;
  7244. int node = elems;
  7245. int new1;
  7246. gz1->heap_len = 0, gz1->heap_max = HEAP_SIZE;
  7247. for (n = 0; n < elems; n++) {
  7248. if (tree[n].fc.freq != 0) {
  7249. gz1->heap[++gz1->heap_len] = max_code = n;
  7250. gz1->depth[n] = 0;
  7251. } else {
  7252. tree[n].dl.len = 0;
  7253. }
  7254. }
  7255. while (gz1->heap_len < 2) {
  7256. new1 = gz1->heap[++gz1->heap_len] = (max_code < 2 ? ++max_code : 0);
  7257. tree[new1].fc.freq = 1;
  7258. gz1->depth[new1] = 0;
  7259. gz1->opt_len--; if (stree) gz1->static_len -= stree[new1].dl.len;
  7260. }
  7261. desc->max_code = max_code;
  7262. for (n = gz1->heap_len/2; n >= 1; n--) pqdownheap(gz1, tree, n);
  7263. do {
  7264. n = gz1->heap[SMALLEST];
  7265. gz1->heap[SMALLEST] = gz1->heap[gz1->heap_len--];
  7266. pqdownheap(gz1, tree, SMALLEST);
  7267. m = gz1->heap[SMALLEST];
  7268. gz1->heap[--gz1->heap_max] = n;
  7269. gz1->heap[--gz1->heap_max] = m;
  7270. tree[node].fc.freq = tree[n].fc.freq + tree[m].fc.freq;
  7271. gz1->depth[node] = (uch) (GZ1_MAX(gz1->depth[n], gz1->depth[m]) + 1);
  7272. tree[n].dl.dad = tree[m].dl.dad = (ush)node;
  7273. gz1->heap[SMALLEST] = node++;
  7274. pqdownheap(gz1, tree, SMALLEST);
  7275. } while (gz1->heap_len >= 2);
  7276. gz1->heap[--gz1->heap_max] = gz1->heap[SMALLEST];
  7277. gen_bitlen(gz1,(tree_desc *)desc);
  7278. gen_codes(gz1,(ct_data *)tree, max_code);
  7279. }
  7280. int build_bl_tree( PGZ1 gz1 )
  7281. {
  7282. int max_blindex;
  7283. scan_tree( gz1, (ct_data *)gz1->dyn_ltree, gz1->l_desc.max_code );
  7284. scan_tree( gz1, (ct_data *)gz1->dyn_dtree, gz1->d_desc.max_code );
  7285. build_tree( gz1, (tree_desc *)(&gz1->bl_desc) );
  7286. for ( max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex-- )
  7287. {
  7288. if (gz1->bl_tree[bl_order[max_blindex]].dl.len != 0) break;
  7289. }
  7290. gz1->opt_len += 3*(max_blindex+1) + 5+5+4;
  7291. return max_blindex;
  7292. }
  7293. void gen_codes(
  7294. PGZ1 gz1,
  7295. ct_data *tree,
  7296. int max_code
  7297. )
  7298. {
  7299. ush next_code[MAX_BITS+1];
  7300. ush code = 0;
  7301. int bits;
  7302. int n;
  7303. for ( bits = 1; bits <= MAX_BITS; bits++ )
  7304. {
  7305. next_code[bits] = code = (code + gz1->bl_count[bits-1]) << 1;
  7306. }
  7307. for ( n = 0; n <= max_code; n++ )
  7308. {
  7309. int len = tree[n].dl.len;
  7310. if (len == 0) continue;
  7311. tree[n].fc.code = bi_reverse( gz1, next_code[len]++, len );
  7312. }
  7313. return;
  7314. }
  7315. void gen_bitlen(
  7316. PGZ1 gz1,
  7317. tree_desc *desc
  7318. )
  7319. {
  7320. ct_data *tree = desc->dyn_tree;
  7321. int *extra = desc->extra_bits;
  7322. int base = desc->extra_base;
  7323. int max_code = desc->max_code;
  7324. int max_length = desc->max_length;
  7325. ct_data *stree = desc->static_tree;
  7326. int h;
  7327. int n, m;
  7328. int bits;
  7329. int xbits;
  7330. ush f;
  7331. int overflow = 0;
  7332. for (bits = 0; bits <= MAX_BITS; bits++) gz1->bl_count[bits] = 0;
  7333. tree[gz1->heap[gz1->heap_max]].dl.len = 0;
  7334. for (h = gz1->heap_max+1; h < HEAP_SIZE; h++) {
  7335. n = gz1->heap[h];
  7336. bits = tree[tree[n].dl.dad].dl.len + 1;
  7337. if (bits > max_length) bits = max_length, overflow++;
  7338. tree[n].dl.len = (ush)bits;
  7339. if (n > max_code) continue;
  7340. gz1->bl_count[bits]++;
  7341. xbits = 0;
  7342. if (n >= base) xbits = extra[n-base];
  7343. f = tree[n].fc.freq;
  7344. gz1->opt_len += (ulg)f * (bits + xbits);
  7345. if (stree) gz1->static_len += (ulg)f * (stree[n].dl.len + xbits);
  7346. }
  7347. if (overflow == 0) return;
  7348. do {
  7349. bits = max_length-1;
  7350. while (gz1->bl_count[bits] == 0) bits--;
  7351. gz1->bl_count[bits]--;
  7352. gz1->bl_count[bits+1] += 2;
  7353. gz1->bl_count[max_length]--;
  7354. overflow -= 2;
  7355. } while (overflow > 0);
  7356. for (bits = max_length; bits != 0; bits--) {
  7357. n = gz1->bl_count[bits];
  7358. while (n != 0) {
  7359. m = gz1->heap[--h];
  7360. if (m > max_code) continue;
  7361. if (tree[m].dl.len != (unsigned) bits) {
  7362. gz1->opt_len += ((long)bits-(long)tree[m].dl.len)*(long)tree[m].fc.freq;
  7363. tree[m].dl.len = (ush)bits;
  7364. }
  7365. n--;
  7366. }
  7367. }
  7368. }
  7369. void copy_block(
  7370. PGZ1 gz1,
  7371. char *buf,
  7372. unsigned len,
  7373. int header
  7374. )
  7375. {
  7376. #ifdef CRYPT
  7377. int t;
  7378. #endif
  7379. bi_windup( gz1 );
  7380. if ( header )
  7381. {
  7382. put_short((ush)len);
  7383. put_short((ush)~len);
  7384. }
  7385. while( len-- )
  7386. {
  7387. #ifdef CRYPT
  7388. if (key) zencode(*buf, t);
  7389. #endif
  7390. put_byte(*buf++);
  7391. }
  7392. }
  7393. int file_read( PGZ1 gz1, char *buf, unsigned size )
  7394. {
  7395. unsigned len = 0;
  7396. unsigned bytes_to_copy = 0;
  7397. if ( gz1->input_ismem )
  7398. {
  7399. if ( gz1->input_bytesleft > 0 )
  7400. {
  7401. bytes_to_copy = size;
  7402. if ( bytes_to_copy > (unsigned) gz1->input_bytesleft )
  7403. {
  7404. bytes_to_copy = (unsigned) gz1->input_bytesleft;
  7405. }
  7406. memcpy( buf, gz1->input_ptr, bytes_to_copy );
  7407. gz1->input_ptr += bytes_to_copy;
  7408. gz1->input_bytesleft -= bytes_to_copy;
  7409. len = bytes_to_copy;
  7410. }
  7411. else
  7412. {
  7413. len = 0;
  7414. }
  7415. }
  7416. else
  7417. {
  7418. len = read( gz1->ifd, buf, size );
  7419. }
  7420. if ( len == (unsigned)(-1) || len == 0 )
  7421. {
  7422. gz1->crc = gz1->crc ^ 0xffffffffL;
  7423. /* XXX - Do we need to do something with Adler CRC's here?
  7424. * I don't think so--they don't seem to need postprocessing. */
  7425. return (int)len;
  7426. }
  7427. if (gz1->compression_format != DEFLATE_FORMAT)
  7428. {
  7429. updcrc( gz1, (uch*)buf, len );
  7430. }
  7431. else
  7432. {
  7433. gz1->adler = adler32(gz1->adler, (uch*)buf, len);
  7434. }
  7435. gz1->bytes_in += (ulg)len;
  7436. return (int)len;
  7437. }
  7438. void bi_windup( PGZ1 gz1 )
  7439. {
  7440. if ( gz1->bi_valid > 8 )
  7441. {
  7442. put_short(gz1->bi_buf);
  7443. }
  7444. else if ( gz1->bi_valid > 0 )
  7445. {
  7446. put_byte(gz1->bi_buf);
  7447. }
  7448. gz1->bi_buf = 0;
  7449. gz1->bi_valid = 0;
  7450. }
  7451. void send_all_trees(
  7452. PGZ1 gz1,
  7453. int lcodes,
  7454. int dcodes,
  7455. int blcodes
  7456. )
  7457. {
  7458. int rank;
  7459. send_bits(gz1,lcodes-257, 5);
  7460. send_bits(gz1,dcodes-1, 5);
  7461. send_bits(gz1,blcodes-4, 4);
  7462. for ( rank = 0; rank < blcodes; rank++ )
  7463. {
  7464. send_bits(gz1,gz1->bl_tree[bl_order[rank]].dl.len, 3 );
  7465. }
  7466. send_tree(gz1,(ct_data *)gz1->dyn_ltree, lcodes-1);
  7467. send_tree(gz1,(ct_data *)gz1->dyn_dtree, dcodes-1);
  7468. }
  7469. void send_tree(
  7470. PGZ1 gz1,
  7471. ct_data *tree,
  7472. int max_code
  7473. )
  7474. {
  7475. int n;
  7476. int prevlen = -1;
  7477. int curlen;
  7478. int nextlen = tree[0].dl.len;
  7479. int count = 0;
  7480. int max_count = 7;
  7481. int min_count = 4;
  7482. if (nextlen == 0) max_count = 138, min_count = 3;
  7483. for ( n = 0; n <= max_code; n++ )
  7484. {
  7485. curlen = nextlen;
  7486. nextlen = tree[n+1].dl.len;
  7487. if (++count < max_count && curlen == nextlen)
  7488. {
  7489. continue;
  7490. }
  7491. else if (count < min_count)
  7492. {
  7493. do { send_code(curlen, gz1->bl_tree); } while (--count != 0);
  7494. }
  7495. else if (curlen != 0)
  7496. {
  7497. if ( curlen != prevlen )
  7498. {
  7499. send_code(curlen, gz1->bl_tree); count--;
  7500. }
  7501. send_code( REP_3_6, gz1->bl_tree ); send_bits(gz1,count-3, 2);
  7502. }
  7503. else if (count <= 10)
  7504. {
  7505. send_code(REPZ_3_10, gz1->bl_tree); send_bits(gz1,count-3, 3);
  7506. }
  7507. else
  7508. {
  7509. send_code(REPZ_11_138, gz1->bl_tree); send_bits(gz1,count-11, 7);
  7510. }
  7511. count = 0;
  7512. prevlen = curlen;
  7513. if (nextlen == 0)
  7514. {
  7515. max_count = 138, min_count = 3;
  7516. }
  7517. else if (curlen == nextlen)
  7518. {
  7519. max_count = 6, min_count = 3;
  7520. }
  7521. else
  7522. {
  7523. max_count = 7, min_count = 4;
  7524. }
  7525. }
  7526. }
  7527. void scan_tree(
  7528. PGZ1 gz1,
  7529. ct_data *tree,
  7530. int max_code
  7531. )
  7532. {
  7533. int n;
  7534. int prevlen = -1;
  7535. int curlen;
  7536. int nextlen = tree[0].dl.len;
  7537. int count = 0;
  7538. int max_count = 7;
  7539. int min_count = 4;
  7540. if (nextlen == 0) max_count = 138, min_count = 3;
  7541. tree[max_code+1].dl.len = (ush)0xffff;
  7542. for ( n = 0; n <= max_code; n++ )
  7543. {
  7544. curlen = nextlen;
  7545. nextlen = tree[n+1].dl.len;
  7546. if ( ++count < max_count && curlen == nextlen )
  7547. {
  7548. continue;
  7549. }
  7550. else if ( count < min_count )
  7551. {
  7552. gz1->bl_tree[curlen].fc.freq += count;
  7553. }
  7554. else if ( curlen != 0 )
  7555. {
  7556. if ( curlen != prevlen ) gz1->bl_tree[curlen].fc.freq++;
  7557. gz1->bl_tree[REP_3_6].fc.freq++;
  7558. }
  7559. else if ( count <= 10 )
  7560. {
  7561. gz1->bl_tree[REPZ_3_10].fc.freq++;
  7562. }
  7563. else
  7564. {
  7565. gz1->bl_tree[REPZ_11_138].fc.freq++;
  7566. }
  7567. count = 0;
  7568. prevlen = curlen;
  7569. if ( nextlen == 0 )
  7570. {
  7571. max_count = 138;
  7572. min_count = 3;
  7573. }
  7574. else if (curlen == nextlen)
  7575. {
  7576. max_count = 6;
  7577. min_count = 3;
  7578. }
  7579. else
  7580. {
  7581. max_count = 7;
  7582. min_count = 4;
  7583. }
  7584. }
  7585. }
  7586. void pqdownheap(
  7587. PGZ1 gz1,
  7588. ct_data *tree,
  7589. int k
  7590. )
  7591. {
  7592. int v = gz1->heap[k];
  7593. int j = k << 1;
  7594. while( j <= gz1->heap_len )
  7595. {
  7596. if (j < gz1->heap_len && smaller(tree, gz1->heap[j+1], gz1->heap[j])) j++;
  7597. if (smaller(tree, v, gz1->heap[j])) break;
  7598. gz1->heap[k] = gz1->heap[j]; k = j;
  7599. j <<= 1;
  7600. }
  7601. gz1->heap[k] = v;
  7602. }
  7603. #define GZS_ZIP1 1
  7604. #define GZS_ZIP2 2
  7605. #define GZS_DEFLATE1 3
  7606. #define GZS_DEFLATE2 4
  7607. int gzs_fsp ( PGZ1 gz1 );
  7608. int gzs_zip1 ( PGZ1 gz1 );
  7609. int gzs_zip2 ( PGZ1 gz1 );
  7610. int gzs_deflate1( PGZ1 gz1 );
  7611. int gzs_deflate2( PGZ1 gz1 );
  7612. int gzp_main( GZP_CONTROL *gzp )
  7613. {
  7614. PGZ1 gz1 = 0;
  7615. int rc = 0;
  7616. int final_exit_code = 0;
  7617. int ofile_flags = O_RDWR | O_CREAT | O_TRUNC | O_BINARY;
  7618. gzp->result_code = 0;
  7619. gzp->bytes_out = 0;
  7620. gz1 = (PGZ1) gz1_init();
  7621. if ( gz1 == 0 )
  7622. {
  7623. return 0;
  7624. }
  7625. gz1->decompress = gzp->decompress;
  7626. gz1->compression_format = gzp->compression_format;
  7627. strcpy( gz1->ifname, gzp->input_filename );
  7628. strcpy( gz1->ofname, gzp->output_filename );
  7629. gz1->input_ismem = gzp->input_ismem;
  7630. gz1->input_ptr = gzp->input_ismem_ibuf;
  7631. gz1->input_bytesleft = gzp->input_ismem_ibuflen;
  7632. gz1->output_ismem = gzp->output_ismem;
  7633. gz1->output_ptr = gzp->output_ismem_obuf;
  7634. gz1->output_maxlen = gzp->output_ismem_obuflen;
  7635. if ( gz1->no_time < 0 ) gz1->no_time = gz1->decompress;
  7636. if ( gz1->no_name < 0 ) gz1->no_name = gz1->decompress;
  7637. work = zip;
  7638. if ( !gz1->input_ismem )
  7639. {
  7640. errno = 0;
  7641. rc = stat( gz1->ifname, &gz1->istat );
  7642. if ( rc != 0 )
  7643. {
  7644. gz1_cleanup( gz1 );
  7645. return 0;
  7646. }
  7647. gz1->ifile_size = gz1->istat.st_size;
  7648. gz1->ifd =
  7649. OPEN(
  7650. gz1->ifname,
  7651. gz1->ascii && !gz1->decompress ? O_RDONLY : O_RDONLY | O_BINARY,
  7652. RW_USER
  7653. );
  7654. if ( gz1->ifd == -1 )
  7655. {
  7656. gz1_cleanup( gz1 );
  7657. return 0;
  7658. }
  7659. }
  7660. if ( !gz1->output_ismem )
  7661. {
  7662. if ( gz1->ascii && gz1->decompress )
  7663. {
  7664. ofile_flags &= ~O_BINARY;
  7665. }
  7666. gz1->ofd = OPEN( gz1->ofname, ofile_flags, RW_USER );
  7667. if ( gz1->ofd == -1 )
  7668. {
  7669. if ( gz1->ifd )
  7670. {
  7671. close( gz1->ifd );
  7672. gz1->ifd = 0;
  7673. }
  7674. gz1_cleanup( gz1 );
  7675. return 0;
  7676. }
  7677. }
  7678. gz1->outcnt = 0;
  7679. gz1->insize = 0;
  7680. gz1->inptr = 0;
  7681. gz1->bytes_in = 0L;
  7682. gz1->bytes_out = 0L;
  7683. gz1->part_nb = 0;
  7684. if ( gz1->decompress )
  7685. {
  7686. gz1->method = get_header( gz1, gz1->ifd );
  7687. if ( gz1->method < 0 )
  7688. {
  7689. if ( gz1->ifd )
  7690. {
  7691. close( gz1->ifd );
  7692. gz1->ifd = 0;
  7693. }
  7694. if ( gz1->ofd )
  7695. {
  7696. close( gz1->ofd );
  7697. gz1->ofd = 0;
  7698. }
  7699. return 0;
  7700. }
  7701. }
  7702. gz1->save_orig_name = 0;
  7703. gz1->state = GZS_ZIP1;
  7704. for (;;)
  7705. {
  7706. gzs_fsp( gz1 );
  7707. if ( gz1->done == 1 ) break;
  7708. }
  7709. if ( gz1->ifd )
  7710. {
  7711. close( gz1->ifd );
  7712. gz1->ifd = 0;
  7713. }
  7714. if ( gz1->ofd )
  7715. {
  7716. close( gz1->ofd );
  7717. gz1->ofd = 0;
  7718. }
  7719. gzp->result_code = gz1->exit_code;
  7720. gzp->bytes_out = gz1->bytes_out;
  7721. final_exit_code = (int) gz1->exit_code;
  7722. gz1_cleanup( gz1 );
  7723. return final_exit_code;
  7724. }
  7725. int gzs_fsp( PGZ1 gz1 )
  7726. {
  7727. int rc=0;
  7728. switch( gz1->state )
  7729. {
  7730. case GZS_ZIP1:
  7731. rc = gzs_zip1( gz1 );
  7732. break;
  7733. case GZS_ZIP2:
  7734. rc = gzs_zip2( gz1 );
  7735. break;
  7736. case GZS_DEFLATE1:
  7737. rc = gzs_deflate1( gz1 );
  7738. break;
  7739. case GZS_DEFLATE2:
  7740. rc = gzs_deflate2( gz1 );
  7741. break;
  7742. default:
  7743. gz1->done = 1;
  7744. break;
  7745. }
  7746. return( rc );
  7747. }
  7748. int gzs_zip1( PGZ1 gz1 )
  7749. {
  7750. uch flags = 0;
  7751. ush attr = 0;
  7752. ush deflate_flags = 0;
  7753. gz1->outcnt = 0;
  7754. gz1->method = DEFLATED;
  7755. if (gz1->compression_format != DEFLATE_FORMAT)
  7756. {
  7757. put_byte(GZIP_MAGIC[0]);
  7758. put_byte(GZIP_MAGIC[1]);
  7759. put_byte(DEFLATED);
  7760. }
  7761. else
  7762. {
  7763. /* Yes, I know RFC 1951 doesn't mention any header at the start of
  7764. * a deflated document, but zlib absolutely requires one. And since nearly
  7765. * all "deflate" implementations use zlib, we need to play along with this
  7766. * brain damage. */
  7767. put_byte(ZLIB_HEADER[0]);
  7768. put_byte(ZLIB_HEADER[1]);
  7769. }
  7770. if ( gz1->save_orig_name )
  7771. {
  7772. flags |= ORIG_NAME;
  7773. }
  7774. if (gz1->compression_format != DEFLATE_FORMAT)
  7775. {
  7776. put_byte(flags);
  7777. put_long(gz1->time_stamp);
  7778. gz1->crc = -1;
  7779. updcrc( gz1, NULL, 0 );
  7780. }
  7781. else
  7782. {
  7783. /* Deflate compression uses an Adler32 CRC, not a CRC32. */
  7784. gz1->adler = 1L;
  7785. }
  7786. gz1->state = GZS_ZIP2;
  7787. return 0;
  7788. }
  7789. int gzs_zip2( PGZ1 gz1 )
  7790. {
  7791. uch flags = 0;
  7792. ush attr = 0;
  7793. ush deflate_flags = 0;
  7794. bi_init( gz1, gz1->ofd );
  7795. ct_init( gz1, &attr, &gz1->method );
  7796. lm_init( gz1, gz1->level, &deflate_flags );
  7797. if (gz1->compression_format != DEFLATE_FORMAT)
  7798. {
  7799. put_byte((uch)deflate_flags);
  7800. put_byte(OS_CODE);
  7801. if ( gz1->save_orig_name )
  7802. {
  7803. char *p = gz1_basename( gz1, gz1->ifname );
  7804. do {
  7805. put_char(*p);
  7806. } while (*p++);
  7807. }
  7808. }
  7809. gz1->header_bytes = (long)gz1->outcnt;
  7810. gz1->state = GZS_DEFLATE1;
  7811. return 0;
  7812. }
  7813. int gzs_deflate1( PGZ1 gz1 )
  7814. {
  7815. if ( !gz1->deflate1_initialized )
  7816. {
  7817. gz1->deflate1_match_available = 0;
  7818. gz1->deflate1_match_length = MIN_MATCH-1;
  7819. gz1->deflate1_initialized = 1;
  7820. }
  7821. if ( gz1->compr_level <= 3 )
  7822. {
  7823. gz1->done = 1;
  7824. return 0;
  7825. }
  7826. if ( gz1->lookahead == 0 )
  7827. {
  7828. if ( gz1->deflate1_match_available )
  7829. {
  7830. ct_tally( gz1, 0, gz1->window[gz1->strstart-1] );
  7831. }
  7832. gz1->state = GZS_DEFLATE2;
  7833. return (int) FLUSH_BLOCK(1);
  7834. }
  7835. #ifdef STAY_HERE_FOR_A_CERTAIN_AMOUNT_OF_ITERATIONS
  7836. while( iterations < max_iterations_per_yield )
  7837. {
  7838. #endif
  7839. gz1->ins_h =
  7840. (((gz1->ins_h)<<H_SHIFT) ^ (gz1->window[gz1->strstart+MIN_MATCH-1])) & HASH_MASK;
  7841. prev[ gz1->strstart & WMASK ] = gz1->deflate1_hash_head = head[ gz1->ins_h ];
  7842. head[ gz1->ins_h ] = gz1->strstart;
  7843. gz1->prev_length = gz1->deflate1_match_length, gz1->deflate1_prev_match = gz1->match_start;
  7844. gz1->deflate1_match_length = MIN_MATCH-1;
  7845. if ( gz1->deflate1_hash_head != NIL && gz1->prev_length < gz1->max_lazy_match &&
  7846. gz1->strstart - gz1->deflate1_hash_head <= MAX_DIST)
  7847. {
  7848. gz1->deflate1_match_length = longest_match( gz1, gz1->deflate1_hash_head );
  7849. if ( gz1->deflate1_match_length > gz1->lookahead )
  7850. {
  7851. gz1->deflate1_match_length = gz1->lookahead;
  7852. }
  7853. if (gz1->deflate1_match_length == MIN_MATCH && gz1->strstart-gz1->match_start > TOO_FAR)
  7854. {
  7855. gz1->deflate1_match_length--;
  7856. }
  7857. }
  7858. if ( gz1->prev_length >= MIN_MATCH && gz1->deflate1_match_length <= gz1->prev_length )
  7859. {
  7860. gz1->deflate1_flush =
  7861. ct_tally(gz1,gz1->strstart-1-gz1->deflate1_prev_match, gz1->prev_length - MIN_MATCH);
  7862. gz1->lookahead -= ( gz1->prev_length - 1 );
  7863. gz1->prev_length -= 2;
  7864. do {
  7865. gz1->strstart++;
  7866. gz1->ins_h =
  7867. (((gz1->ins_h)<<H_SHIFT) ^ (gz1->window[ gz1->strstart + MIN_MATCH-1])) & HASH_MASK;
  7868. prev[ gz1->strstart & WMASK ] = gz1->deflate1_hash_head = head[gz1->ins_h];
  7869. head[ gz1->ins_h ] = gz1->strstart;
  7870. } while (--gz1->prev_length != 0);
  7871. gz1->deflate1_match_available = 0;
  7872. gz1->deflate1_match_length = MIN_MATCH-1;
  7873. gz1->strstart++;
  7874. if (gz1->deflate1_flush) FLUSH_BLOCK(0), gz1->block_start = gz1->strstart;
  7875. }
  7876. else
  7877. {
  7878. if ( gz1->deflate1_match_available )
  7879. {
  7880. if ( ct_tally( gz1, 0, gz1->window[gz1->strstart-1] ) )
  7881. {
  7882. FLUSH_BLOCK(0), gz1->block_start = gz1->strstart;
  7883. }
  7884. gz1->strstart++;
  7885. gz1->lookahead--;
  7886. }
  7887. else
  7888. {
  7889. gz1->deflate1_match_available = 1;
  7890. gz1->strstart++;
  7891. gz1->lookahead--;
  7892. }
  7893. while (gz1->lookahead < MIN_LOOKAHEAD && !gz1->eofile )
  7894. {
  7895. fill_window(gz1);
  7896. }
  7897. }
  7898. return 0;
  7899. }
  7900. int gzs_deflate2( PGZ1 gz1 )
  7901. {
  7902. #if !defined(NO_SIZE_CHECK) && !defined(RECORD_IO)
  7903. if (gz1->ifile_size != -1L && gz1->isize != (ulg)gz1->ifile_size)
  7904. {
  7905. }
  7906. #endif
  7907. if (gz1->compression_format != DEFLATE_FORMAT)
  7908. {
  7909. put_long( gz1->crc );
  7910. put_long( gz1->bytes_in );
  7911. gz1->header_bytes += 2*sizeof(long);
  7912. }
  7913. else
  7914. {
  7915. /* Append an Adler32 CRC to our deflated data.
  7916. * Yes, I know RFC 1951 doesn't mention any CRC at the end of a
  7917. * deflated document, but zlib absolutely requires one. And since nearly
  7918. * all "deflate" implementations use zlib, we need to play along with this
  7919. * brain damage. */
  7920. put_byte( (gz1->adler >> 24) );
  7921. put_byte( (gz1->adler >> 16) & 0xFF );
  7922. put_byte( (gz1->adler >> 8) & 0xFF );
  7923. put_byte( (gz1->adler ) & 0xFF );
  7924. gz1->header_bytes += 4*sizeof(uch);
  7925. }
  7926. flush_outbuf( gz1 );
  7927. gz1->done = 1;
  7928. return OK;
  7929. }
  7930. /* =========================================================================
  7931. adler32 -- compute the Adler-32 checksum of a data stream
  7932. Copyright (C) 1995-1998 Mark Adler
  7933. This software is provided 'as-is', without any express or implied
  7934. warranty. In no event will the authors be held liable for any damages
  7935. arising from the use of this software.
  7936. Permission is granted to anyone to use this software for any purpose,
  7937. including commercial applications, and to alter it and redistribute it
  7938. freely, subject to the following restrictions:
  7939. 1. The origin of this software must not be misrepresented; you must not
  7940. claim that you wrote the original software. If you use this software
  7941. in a product, an acknowledgment in the product documentation would be
  7942. appreciated but is not required.
  7943. 2. Altered source versions must be plainly marked as such, and must not be
  7944. misrepresented as being the original software.
  7945. 3. This notice may not be removed or altered from any source distribution.
  7946. Modified by Eric Kidd <eric.kidd@pobox.com> to play nicely with mod_gzip.
  7947. */
  7948. #define BASE 65521L /* largest prime smaller than 65536 */
  7949. #define NMAX 5552
  7950. /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
  7951. #define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
  7952. #define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
  7953. #define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
  7954. #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
  7955. #define DO16(buf) DO8(buf,0); DO8(buf,8);
  7956. ulg adler32(ulg adler, uch *buf, unsigned len)
  7957. {
  7958. unsigned long s1 = adler & 0xffff;
  7959. unsigned long s2 = (adler >> 16) & 0xffff;
  7960. int k;
  7961. if (buf == NULL) return 1L;
  7962. while (len > 0) {
  7963. k = len < NMAX ? len : NMAX;
  7964. len -= k;
  7965. while (k >= 16) {
  7966. DO16(buf);
  7967. buf += 16;
  7968. k -= 16;
  7969. }
  7970. if (k != 0) do {
  7971. s1 += *buf++;
  7972. s2 += s1;
  7973. } while (--k);
  7974. s1 %= BASE;
  7975. s2 %= BASE;
  7976. }
  7977. return (s2 << 16) | s1;
  7978. }
  7979. /* END OF FILE */