phar_object.c 163 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472
  1. /*
  2. +----------------------------------------------------------------------+
  3. | phar php single-file executable PHP extension |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 2005-2018 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt. |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Gregory Beaver <cellog@php.net> |
  16. | Marcus Boerger <helly@php.net> |
  17. +----------------------------------------------------------------------+
  18. */
  19. #include "phar_internal.h"
  20. #include "func_interceptors.h"
  21. static zend_class_entry *phar_ce_archive;
  22. static zend_class_entry *phar_ce_data;
  23. static zend_class_entry *phar_ce_PharException;
  24. static zend_class_entry *phar_ce_entry;
  25. static int phar_file_type(HashTable *mimes, char *file, char **mime_type) /* {{{ */
  26. {
  27. char *ext;
  28. phar_mime_type *mime;
  29. ext = strrchr(file, '.');
  30. if (!ext) {
  31. *mime_type = "text/plain";
  32. /* no file extension = assume text/plain */
  33. return PHAR_MIME_OTHER;
  34. }
  35. ++ext;
  36. if (NULL == (mime = zend_hash_str_find_ptr(mimes, ext, strlen(ext)))) {
  37. *mime_type = "application/octet-stream";
  38. return PHAR_MIME_OTHER;
  39. }
  40. *mime_type = mime->mime;
  41. return mime->type;
  42. }
  43. /* }}} */
  44. static void phar_mung_server_vars(char *fname, char *entry, size_t entry_len, char *basename, size_t request_uri_len) /* {{{ */
  45. {
  46. HashTable *_SERVER;
  47. zval *stuff;
  48. char *path_info;
  49. size_t basename_len = strlen(basename);
  50. size_t code;
  51. zval temp;
  52. /* "tweak" $_SERVER variables requested in earlier call to Phar::mungServer() */
  53. if (Z_TYPE(PG(http_globals)[TRACK_VARS_SERVER]) == IS_UNDEF) {
  54. return;
  55. }
  56. _SERVER = Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]);
  57. /* PATH_INFO and PATH_TRANSLATED should always be munged */
  58. if (NULL != (stuff = zend_hash_str_find(_SERVER, "PATH_INFO", sizeof("PATH_INFO")-1))) {
  59. path_info = Z_STRVAL_P(stuff);
  60. code = Z_STRLEN_P(stuff);
  61. if (code > (size_t)entry_len && !memcmp(path_info, entry, entry_len)) {
  62. ZVAL_STR(&temp, Z_STR_P(stuff));
  63. ZVAL_STRINGL(stuff, path_info + entry_len, request_uri_len);
  64. zend_hash_str_update(_SERVER, "PHAR_PATH_INFO", sizeof("PHAR_PATH_INFO")-1, &temp);
  65. }
  66. }
  67. if (NULL != (stuff = zend_hash_str_find(_SERVER, "PATH_TRANSLATED", sizeof("PATH_TRANSLATED")-1))) {
  68. zend_string *str = strpprintf(4096, "phar://%s%s", fname, entry);
  69. ZVAL_STR(&temp, Z_STR_P(stuff));
  70. ZVAL_NEW_STR(stuff, str);
  71. zend_hash_str_update(_SERVER, "PHAR_PATH_TRANSLATED", sizeof("PHAR_PATH_TRANSLATED")-1, &temp);
  72. }
  73. if (!PHAR_G(phar_SERVER_mung_list)) {
  74. return;
  75. }
  76. if (PHAR_G(phar_SERVER_mung_list) & PHAR_MUNG_REQUEST_URI) {
  77. if (NULL != (stuff = zend_hash_str_find(_SERVER, "REQUEST_URI", sizeof("REQUEST_URI")-1))) {
  78. path_info = Z_STRVAL_P(stuff);
  79. code = Z_STRLEN_P(stuff);
  80. if (code > basename_len && !memcmp(path_info, basename, basename_len)) {
  81. ZVAL_STR(&temp, Z_STR_P(stuff));
  82. ZVAL_STRINGL(stuff, path_info + basename_len, code - basename_len);
  83. zend_hash_str_update(_SERVER, "PHAR_REQUEST_URI", sizeof("PHAR_REQUEST_URI")-1, &temp);
  84. }
  85. }
  86. }
  87. if (PHAR_G(phar_SERVER_mung_list) & PHAR_MUNG_PHP_SELF) {
  88. if (NULL != (stuff = zend_hash_str_find(_SERVER, "PHP_SELF", sizeof("PHP_SELF")-1))) {
  89. path_info = Z_STRVAL_P(stuff);
  90. code = Z_STRLEN_P(stuff);
  91. if (code > basename_len && !memcmp(path_info, basename, basename_len)) {
  92. ZVAL_STR(&temp, Z_STR_P(stuff));
  93. ZVAL_STRINGL(stuff, path_info + basename_len, code - basename_len);
  94. zend_hash_str_update(_SERVER, "PHAR_PHP_SELF", sizeof("PHAR_PHP_SELF")-1, &temp);
  95. }
  96. }
  97. }
  98. if (PHAR_G(phar_SERVER_mung_list) & PHAR_MUNG_SCRIPT_NAME) {
  99. if (NULL != (stuff = zend_hash_str_find(_SERVER, "SCRIPT_NAME", sizeof("SCRIPT_NAME")-1))) {
  100. ZVAL_STR(&temp, Z_STR_P(stuff));
  101. ZVAL_STRINGL(stuff, entry, entry_len);
  102. zend_hash_str_update(_SERVER, "PHAR_SCRIPT_NAME", sizeof("PHAR_SCRIPT_NAME")-1, &temp);
  103. }
  104. }
  105. if (PHAR_G(phar_SERVER_mung_list) & PHAR_MUNG_SCRIPT_FILENAME) {
  106. if (NULL != (stuff = zend_hash_str_find(_SERVER, "SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME")-1))) {
  107. zend_string *str = strpprintf(4096, "phar://%s%s", fname, entry);
  108. ZVAL_STR(&temp, Z_STR_P(stuff));
  109. ZVAL_NEW_STR(stuff, str);
  110. zend_hash_str_update(_SERVER, "PHAR_SCRIPT_FILENAME", sizeof("PHAR_SCRIPT_FILENAME")-1, &temp);
  111. }
  112. }
  113. }
  114. /* }}} */
  115. static int phar_file_action(phar_archive_data *phar, phar_entry_info *info, char *mime_type, int code, char *entry, size_t entry_len, char *arch, char *basename, char *ru, size_t ru_len) /* {{{ */
  116. {
  117. char *name = NULL, buf[8192];
  118. const char *cwd;
  119. zend_syntax_highlighter_ini syntax_highlighter_ini;
  120. sapi_header_line ctr = {0};
  121. size_t got;
  122. zval dummy;
  123. size_t name_len;
  124. zend_file_handle file_handle;
  125. zend_op_array *new_op_array;
  126. zval result;
  127. php_stream *fp;
  128. zend_off_t position;
  129. switch (code) {
  130. case PHAR_MIME_PHPS:
  131. efree(basename);
  132. /* highlight source */
  133. if (entry[0] == '/') {
  134. spprintf(&name, 4096, "phar://%s%s", arch, entry);
  135. } else {
  136. spprintf(&name, 4096, "phar://%s/%s", arch, entry);
  137. }
  138. php_get_highlight_struct(&syntax_highlighter_ini);
  139. highlight_file(name, &syntax_highlighter_ini);
  140. efree(name);
  141. #ifdef PHP_WIN32
  142. efree(arch);
  143. #endif
  144. zend_bailout();
  145. case PHAR_MIME_OTHER:
  146. /* send headers, output file contents */
  147. efree(basename);
  148. ctr.line_len = spprintf(&(ctr.line), 0, "Content-type: %s", mime_type);
  149. sapi_header_op(SAPI_HEADER_REPLACE, &ctr);
  150. efree(ctr.line);
  151. ctr.line_len = spprintf(&(ctr.line), 0, "Content-length: %u", info->uncompressed_filesize);
  152. sapi_header_op(SAPI_HEADER_REPLACE, &ctr);
  153. efree(ctr.line);
  154. if (FAILURE == sapi_send_headers()) {
  155. zend_bailout();
  156. }
  157. /* prepare to output */
  158. fp = phar_get_efp(info, 1);
  159. if (!fp) {
  160. char *error;
  161. if (!phar_open_jit(phar, info, &error)) {
  162. if (error) {
  163. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  164. efree(error);
  165. }
  166. return -1;
  167. }
  168. fp = phar_get_efp(info, 1);
  169. }
  170. position = 0;
  171. phar_seek_efp(info, 0, SEEK_SET, 0, 1);
  172. do {
  173. got = php_stream_read(fp, buf, MIN(8192, info->uncompressed_filesize - position));
  174. if (got > 0) {
  175. PHPWRITE(buf, got);
  176. position += got;
  177. if (position == (zend_off_t) info->uncompressed_filesize) {
  178. break;
  179. }
  180. }
  181. } while (1);
  182. zend_bailout();
  183. case PHAR_MIME_PHP:
  184. if (basename) {
  185. phar_mung_server_vars(arch, entry, entry_len, basename, ru_len);
  186. efree(basename);
  187. }
  188. if (entry[0] == '/') {
  189. name_len = spprintf(&name, 4096, "phar://%s%s", arch, entry);
  190. } else {
  191. name_len = spprintf(&name, 4096, "phar://%s/%s", arch, entry);
  192. }
  193. file_handle.type = ZEND_HANDLE_FILENAME;
  194. file_handle.handle.fd = 0;
  195. file_handle.filename = name;
  196. file_handle.opened_path = NULL;
  197. file_handle.free_filename = 0;
  198. PHAR_G(cwd) = NULL;
  199. PHAR_G(cwd_len) = 0;
  200. ZVAL_NULL(&dummy);
  201. if (zend_hash_str_add(&EG(included_files), name, name_len, &dummy) != NULL) {
  202. if ((cwd = zend_memrchr(entry, '/', entry_len))) {
  203. PHAR_G(cwd_init) = 1;
  204. if (entry == cwd) {
  205. /* root directory */
  206. PHAR_G(cwd_len) = 0;
  207. PHAR_G(cwd) = NULL;
  208. } else if (entry[0] == '/') {
  209. PHAR_G(cwd_len) = (cwd - (entry + 1));
  210. PHAR_G(cwd) = estrndup(entry + 1, PHAR_G(cwd_len));
  211. } else {
  212. PHAR_G(cwd_len) = (cwd - entry);
  213. PHAR_G(cwd) = estrndup(entry, PHAR_G(cwd_len));
  214. }
  215. }
  216. new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE);
  217. if (!new_op_array) {
  218. zend_hash_str_del(&EG(included_files), name, name_len);
  219. }
  220. zend_destroy_file_handle(&file_handle);
  221. } else {
  222. efree(name);
  223. new_op_array = NULL;
  224. }
  225. #ifdef PHP_WIN32
  226. efree(arch);
  227. #endif
  228. if (new_op_array) {
  229. ZVAL_UNDEF(&result);
  230. zend_try {
  231. zend_execute(new_op_array, &result);
  232. if (PHAR_G(cwd)) {
  233. efree(PHAR_G(cwd));
  234. PHAR_G(cwd) = NULL;
  235. PHAR_G(cwd_len) = 0;
  236. }
  237. PHAR_G(cwd_init) = 0;
  238. efree(name);
  239. destroy_op_array(new_op_array);
  240. efree(new_op_array);
  241. zval_ptr_dtor(&result);
  242. } zend_catch {
  243. if (PHAR_G(cwd)) {
  244. efree(PHAR_G(cwd));
  245. PHAR_G(cwd) = NULL;
  246. PHAR_G(cwd_len) = 0;
  247. }
  248. PHAR_G(cwd_init) = 0;
  249. efree(name);
  250. } zend_end_try();
  251. zend_bailout();
  252. }
  253. return PHAR_MIME_PHP;
  254. }
  255. return -1;
  256. }
  257. /* }}} */
  258. static void phar_do_403(char *entry, size_t entry_len) /* {{{ */
  259. {
  260. sapi_header_line ctr = {0};
  261. ctr.response_code = 403;
  262. ctr.line_len = sizeof("HTTP/1.0 403 Access Denied")-1;
  263. ctr.line = "HTTP/1.0 403 Access Denied";
  264. sapi_header_op(SAPI_HEADER_REPLACE, &ctr);
  265. sapi_send_headers();
  266. PHPWRITE("<html>\n <head>\n <title>Access Denied</title>\n </head>\n <body>\n <h1>403 - File ", sizeof("<html>\n <head>\n <title>Access Denied</title>\n </head>\n <body>\n <h1>403 - File ") - 1);
  267. PHPWRITE("Access Denied</h1>\n </body>\n</html>", sizeof("Access Denied</h1>\n </body>\n</html>") - 1);
  268. }
  269. /* }}} */
  270. static void phar_do_404(phar_archive_data *phar, char *fname, size_t fname_len, char *f404, size_t f404_len, char *entry, size_t entry_len) /* {{{ */
  271. {
  272. sapi_header_line ctr = {0};
  273. phar_entry_info *info;
  274. if (phar && f404_len) {
  275. info = phar_get_entry_info(phar, f404, f404_len, NULL, 1);
  276. if (info) {
  277. phar_file_action(phar, info, "text/html", PHAR_MIME_PHP, f404, f404_len, fname, NULL, NULL, 0);
  278. return;
  279. }
  280. }
  281. ctr.response_code = 404;
  282. ctr.line_len = sizeof("HTTP/1.0 404 Not Found")-1;
  283. ctr.line = "HTTP/1.0 404 Not Found";
  284. sapi_header_op(SAPI_HEADER_REPLACE, &ctr);
  285. sapi_send_headers();
  286. PHPWRITE("<html>\n <head>\n <title>File Not Found</title>\n </head>\n <body>\n <h1>404 - File ", sizeof("<html>\n <head>\n <title>File Not Found</title>\n </head>\n <body>\n <h1>404 - File ") - 1);
  287. PHPWRITE("Not Found</h1>\n </body>\n</html>", sizeof("Not Found</h1>\n </body>\n</html>") - 1);
  288. }
  289. /* }}} */
  290. /* post-process REQUEST_URI and retrieve the actual request URI. This is for
  291. cases like http://localhost/blah.phar/path/to/file.php/extra/stuff
  292. which calls "blah.phar" file "path/to/file.php" with PATH_INFO "/extra/stuff" */
  293. static void phar_postprocess_ru_web(char *fname, size_t fname_len, char **entry, size_t *entry_len, char **ru, size_t *ru_len) /* {{{ */
  294. {
  295. char *e = *entry + 1, *u = NULL, *u1 = NULL, *saveu = NULL;
  296. size_t e_len = *entry_len - 1, u_len = 0;
  297. phar_archive_data *pphar;
  298. /* we already know we can retrieve the phar if we reach here */
  299. pphar = zend_hash_str_find_ptr(&(PHAR_G(phar_fname_map)), fname, fname_len);
  300. if (!pphar && PHAR_G(manifest_cached)) {
  301. pphar = zend_hash_str_find_ptr(&cached_phars, fname, fname_len);
  302. }
  303. do {
  304. if (zend_hash_str_exists(&(pphar->manifest), e, e_len)) {
  305. if (u) {
  306. u[0] = '/';
  307. *ru = estrndup(u, u_len+1);
  308. ++u_len;
  309. u[0] = '\0';
  310. } else {
  311. *ru = NULL;
  312. }
  313. *ru_len = u_len;
  314. *entry_len = e_len + 1;
  315. return;
  316. }
  317. if (u) {
  318. u1 = strrchr(e, '/');
  319. u[0] = '/';
  320. saveu = u;
  321. e_len += u_len + 1;
  322. u = u1;
  323. if (!u) {
  324. return;
  325. }
  326. } else {
  327. u = strrchr(e, '/');
  328. if (!u) {
  329. if (saveu) {
  330. saveu[0] = '/';
  331. }
  332. return;
  333. }
  334. }
  335. u[0] = '\0';
  336. u_len = strlen(u + 1);
  337. e_len -= u_len + 1;
  338. } while (1);
  339. }
  340. /* }}} */
  341. /* {{{ proto void Phar::running([bool retphar = true])
  342. * return the name of the currently running phar archive. If the optional parameter
  343. * is set to true, return the phar:// URL to the currently running phar
  344. */
  345. PHP_METHOD(Phar, running)
  346. {
  347. char *fname, *arch, *entry;
  348. size_t fname_len, arch_len, entry_len;
  349. zend_bool retphar = 1;
  350. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &retphar) == FAILURE) {
  351. return;
  352. }
  353. fname = (char*)zend_get_executed_filename();
  354. fname_len = strlen(fname);
  355. if (fname_len > 7 && !memcmp(fname, "phar://", 7) && SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
  356. efree(entry);
  357. if (retphar) {
  358. RETVAL_STRINGL(fname, arch_len + 7);
  359. efree(arch);
  360. return;
  361. } else {
  362. // TODO: avoid reallocation ???
  363. RETVAL_STRINGL(arch, arch_len);
  364. efree(arch);
  365. return;
  366. }
  367. }
  368. RETURN_EMPTY_STRING();
  369. }
  370. /* }}} */
  371. /* {{{ proto void Phar::mount(string pharpath, string externalfile)
  372. * mount an external file or path to a location within the phar. This maps
  373. * an external file or directory to a location within the phar archive, allowing
  374. * reference to an external location as if it were within the phar archive. This
  375. * is useful for writable temp files like databases
  376. */
  377. PHP_METHOD(Phar, mount)
  378. {
  379. char *fname, *arch = NULL, *entry = NULL, *path, *actual;
  380. size_t fname_len, arch_len, entry_len;
  381. size_t path_len, actual_len;
  382. phar_archive_data *pphar;
  383. if (zend_parse_parameters(ZEND_NUM_ARGS(), "pp", &path, &path_len, &actual, &actual_len) == FAILURE) {
  384. return;
  385. }
  386. fname = (char*)zend_get_executed_filename();
  387. fname_len = strlen(fname);
  388. #ifdef PHP_WIN32
  389. phar_unixify_path_separators(fname, fname_len);
  390. #endif
  391. if (fname_len > 7 && !memcmp(fname, "phar://", 7) && SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
  392. efree(entry);
  393. entry = NULL;
  394. if (path_len > 7 && !memcmp(path, "phar://", 7)) {
  395. zend_throw_exception_ex(phar_ce_PharException, 0, "Can only mount internal paths within a phar archive, use a relative path instead of \"%s\"", path);
  396. efree(arch);
  397. return;
  398. }
  399. carry_on2:
  400. if (NULL == (pphar = zend_hash_str_find_ptr(&(PHAR_G(phar_fname_map)), arch, arch_len))) {
  401. if (PHAR_G(manifest_cached) && NULL != (pphar = zend_hash_str_find_ptr(&cached_phars, arch, arch_len))) {
  402. if (SUCCESS == phar_copy_on_write(&pphar)) {
  403. goto carry_on;
  404. }
  405. }
  406. zend_throw_exception_ex(phar_ce_PharException, 0, "%s is not a phar archive, cannot mount", arch);
  407. if (arch) {
  408. efree(arch);
  409. }
  410. return;
  411. }
  412. carry_on:
  413. if (SUCCESS != phar_mount_entry(pphar, actual, actual_len, path, path_len)) {
  414. zend_throw_exception_ex(phar_ce_PharException, 0, "Mounting of %s to %s within phar %s failed", path, actual, arch);
  415. if (path && path == entry) {
  416. efree(entry);
  417. }
  418. if (arch) {
  419. efree(arch);
  420. }
  421. return;
  422. }
  423. if (entry && path && path == entry) {
  424. efree(entry);
  425. }
  426. if (arch) {
  427. efree(arch);
  428. }
  429. return;
  430. } else if (HT_FLAGS(&PHAR_G(phar_fname_map)) && NULL != (pphar = zend_hash_str_find_ptr(&(PHAR_G(phar_fname_map)), fname, fname_len))) {
  431. goto carry_on;
  432. } else if (PHAR_G(manifest_cached) && NULL != (pphar = zend_hash_str_find_ptr(&cached_phars, fname, fname_len))) {
  433. if (SUCCESS == phar_copy_on_write(&pphar)) {
  434. goto carry_on;
  435. }
  436. goto carry_on;
  437. } else if (SUCCESS == phar_split_fname(path, path_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
  438. path = entry;
  439. path_len = entry_len;
  440. goto carry_on2;
  441. }
  442. zend_throw_exception_ex(phar_ce_PharException, 0, "Mounting of %s to %s failed", path, actual);
  443. }
  444. /* }}} */
  445. /* {{{ proto void Phar::webPhar([string alias, [string index, [string f404, [array mimetypes, [callback rewrites]]]]])
  446. * mapPhar for web-based phars. Reads the currently executed file (a phar)
  447. * and registers its manifest. When executed in the CLI or CGI command-line sapi,
  448. * this works exactly like mapPhar(). When executed by a web-based sapi, this
  449. * reads $_SERVER['REQUEST_URI'] (the actual original value) and parses out the
  450. * intended internal file.
  451. */
  452. PHP_METHOD(Phar, webPhar)
  453. {
  454. zval *mimeoverride = NULL, *rewrite = NULL;
  455. char *alias = NULL, *error, *index_php = NULL, *f404 = NULL, *ru = NULL;
  456. size_t alias_len = 0, f404_len = 0, free_pathinfo = 0;
  457. size_t ru_len = 0;
  458. char *fname, *path_info, *mime_type = NULL, *entry, *pt;
  459. const char *basename;
  460. size_t fname_len, index_php_len = 0;
  461. size_t entry_len;
  462. int code, not_cgi;
  463. phar_archive_data *phar = NULL;
  464. phar_entry_info *info = NULL;
  465. size_t sapi_mod_name_len = strlen(sapi_module.name);
  466. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s!s!saz", &alias, &alias_len, &index_php, &index_php_len, &f404, &f404_len, &mimeoverride, &rewrite) == FAILURE) {
  467. return;
  468. }
  469. phar_request_initialize();
  470. fname = (char*)zend_get_executed_filename();
  471. fname_len = strlen(fname);
  472. if (phar_open_executed_filename(alias, alias_len, &error) != SUCCESS) {
  473. if (error) {
  474. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  475. efree(error);
  476. }
  477. return;
  478. }
  479. /* retrieve requested file within phar */
  480. if (!(SG(request_info).request_method
  481. && SG(request_info).request_uri
  482. && (!strcmp(SG(request_info).request_method, "GET")
  483. || !strcmp(SG(request_info).request_method, "POST")
  484. || !strcmp(SG(request_info).request_method, "DELETE")
  485. || !strcmp(SG(request_info).request_method, "HEAD")
  486. || !strcmp(SG(request_info).request_method, "OPTIONS")
  487. || !strcmp(SG(request_info).request_method, "PATCH")
  488. || !strcmp(SG(request_info).request_method, "PUT")
  489. )
  490. )
  491. ) {
  492. return;
  493. }
  494. #ifdef PHP_WIN32
  495. fname = estrndup(fname, fname_len);
  496. phar_unixify_path_separators(fname, fname_len);
  497. #endif
  498. basename = zend_memrchr(fname, '/', fname_len);
  499. if (!basename) {
  500. basename = fname;
  501. } else {
  502. ++basename;
  503. }
  504. if ((sapi_mod_name_len == sizeof("cgi-fcgi") - 1 && !strncmp(sapi_module.name, "cgi-fcgi", sizeof("cgi-fcgi") - 1))
  505. || (sapi_mod_name_len == sizeof("fpm-fcgi") - 1 && !strncmp(sapi_module.name, "fpm-fcgi", sizeof("fpm-fcgi") - 1))
  506. || (sapi_mod_name_len == sizeof("cgi") - 1 && !strncmp(sapi_module.name, "cgi", sizeof("cgi") - 1))) {
  507. if (Z_TYPE(PG(http_globals)[TRACK_VARS_SERVER]) != IS_UNDEF) {
  508. HashTable *_server = Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]);
  509. zval *z_script_name, *z_path_info;
  510. if (NULL == (z_script_name = zend_hash_str_find(_server, "SCRIPT_NAME", sizeof("SCRIPT_NAME")-1)) ||
  511. IS_STRING != Z_TYPE_P(z_script_name) ||
  512. !strstr(Z_STRVAL_P(z_script_name), basename)) {
  513. return;
  514. }
  515. if (NULL != (z_path_info = zend_hash_str_find(_server, "PATH_INFO", sizeof("PATH_INFO")-1)) &&
  516. IS_STRING == Z_TYPE_P(z_path_info)) {
  517. entry_len = Z_STRLEN_P(z_path_info);
  518. entry = estrndup(Z_STRVAL_P(z_path_info), entry_len);
  519. path_info = emalloc(Z_STRLEN_P(z_script_name) + entry_len + 1);
  520. memcpy(path_info, Z_STRVAL_P(z_script_name), Z_STRLEN_P(z_script_name));
  521. memcpy(path_info + Z_STRLEN_P(z_script_name), entry, entry_len + 1);
  522. free_pathinfo = 1;
  523. } else {
  524. entry_len = 0;
  525. entry = estrndup("", 0);
  526. path_info = Z_STRVAL_P(z_script_name);
  527. }
  528. pt = estrndup(Z_STRVAL_P(z_script_name), Z_STRLEN_P(z_script_name));
  529. } else {
  530. char *testit;
  531. testit = sapi_getenv("SCRIPT_NAME", sizeof("SCRIPT_NAME")-1);
  532. if (!(pt = strstr(testit, basename))) {
  533. efree(testit);
  534. return;
  535. }
  536. path_info = sapi_getenv("PATH_INFO", sizeof("PATH_INFO")-1);
  537. if (path_info) {
  538. entry = path_info;
  539. entry_len = strlen(entry);
  540. spprintf(&path_info, 0, "%s%s", testit, path_info);
  541. free_pathinfo = 1;
  542. } else {
  543. path_info = testit;
  544. free_pathinfo = 1;
  545. entry = estrndup("", 0);
  546. entry_len = 0;
  547. }
  548. pt = estrndup(testit, (pt - testit) + (fname_len - (basename - fname)));
  549. }
  550. not_cgi = 0;
  551. } else {
  552. path_info = SG(request_info).request_uri;
  553. if (!(pt = strstr(path_info, basename))) {
  554. /* this can happen with rewrite rules - and we have no idea what to do then, so return */
  555. return;
  556. }
  557. entry_len = strlen(path_info);
  558. entry_len -= (pt - path_info) + (fname_len - (basename - fname));
  559. entry = estrndup(pt + (fname_len - (basename - fname)), entry_len);
  560. pt = estrndup(path_info, (pt - path_info) + (fname_len - (basename - fname)));
  561. not_cgi = 1;
  562. }
  563. if (rewrite) {
  564. zend_fcall_info fci;
  565. zend_fcall_info_cache fcc;
  566. zval params, retval;
  567. ZVAL_STRINGL(&params, entry, entry_len);
  568. if (FAILURE == zend_fcall_info_init(rewrite, 0, &fci, &fcc, NULL, NULL)) {
  569. zend_throw_exception_ex(phar_ce_PharException, 0, "phar error: invalid rewrite callback");
  570. if (free_pathinfo) {
  571. efree(path_info);
  572. }
  573. efree(pt);
  574. return;
  575. }
  576. fci.param_count = 1;
  577. fci.params = &params;
  578. Z_ADDREF(params);
  579. fci.retval = &retval;
  580. if (FAILURE == zend_call_function(&fci, &fcc)) {
  581. if (!EG(exception)) {
  582. zend_throw_exception_ex(phar_ce_PharException, 0, "phar error: failed to call rewrite callback");
  583. }
  584. if (free_pathinfo) {
  585. efree(path_info);
  586. }
  587. efree(pt);
  588. return;
  589. }
  590. if (Z_TYPE_P(fci.retval) == IS_UNDEF || Z_TYPE(retval) == IS_UNDEF) {
  591. if (free_pathinfo) {
  592. efree(path_info);
  593. }
  594. zend_throw_exception_ex(phar_ce_PharException, 0, "phar error: rewrite callback must return a string or false");
  595. efree(pt);
  596. return;
  597. }
  598. switch (Z_TYPE(retval)) {
  599. case IS_STRING:
  600. efree(entry);
  601. entry = estrndup(Z_STRVAL_P(fci.retval), Z_STRLEN_P(fci.retval));
  602. entry_len = Z_STRLEN_P(fci.retval);
  603. break;
  604. case IS_TRUE:
  605. case IS_FALSE:
  606. phar_do_403(entry, entry_len);
  607. if (free_pathinfo) {
  608. efree(path_info);
  609. }
  610. efree(pt);
  611. zend_bailout();
  612. return;
  613. default:
  614. if (free_pathinfo) {
  615. efree(path_info);
  616. }
  617. efree(pt);
  618. zend_throw_exception_ex(phar_ce_PharException, 0, "phar error: rewrite callback must return a string or false");
  619. return;
  620. }
  621. }
  622. if (entry_len) {
  623. phar_postprocess_ru_web(fname, fname_len, &entry, &entry_len, &ru, &ru_len);
  624. }
  625. if (!entry_len || (entry_len == 1 && entry[0] == '/')) {
  626. efree(entry);
  627. /* direct request */
  628. if (index_php_len) {
  629. entry = index_php;
  630. entry_len = index_php_len;
  631. if (entry[0] != '/') {
  632. spprintf(&entry, 0, "/%s", index_php);
  633. ++entry_len;
  634. }
  635. } else {
  636. /* assume "index.php" is starting point */
  637. entry = estrndup("/index.php", sizeof("/index.php"));
  638. entry_len = sizeof("/index.php")-1;
  639. }
  640. if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, NULL) ||
  641. (info = phar_get_entry_info(phar, entry, entry_len, NULL, 0)) == NULL) {
  642. phar_do_404(phar, fname, fname_len, f404, f404_len, entry, entry_len);
  643. if (free_pathinfo) {
  644. efree(path_info);
  645. }
  646. zend_bailout();
  647. } else {
  648. char *tmp = NULL, sa = '\0';
  649. sapi_header_line ctr = {0};
  650. ctr.response_code = 301;
  651. ctr.line_len = sizeof("HTTP/1.1 301 Moved Permanently")-1;
  652. ctr.line = "HTTP/1.1 301 Moved Permanently";
  653. sapi_header_op(SAPI_HEADER_REPLACE, &ctr);
  654. if (not_cgi) {
  655. tmp = strstr(path_info, basename) + fname_len;
  656. sa = *tmp;
  657. *tmp = '\0';
  658. }
  659. ctr.response_code = 0;
  660. if (path_info[strlen(path_info)-1] == '/') {
  661. ctr.line_len = spprintf(&(ctr.line), 4096, "Location: %s%s", path_info, entry + 1);
  662. } else {
  663. ctr.line_len = spprintf(&(ctr.line), 4096, "Location: %s%s", path_info, entry);
  664. }
  665. if (not_cgi) {
  666. *tmp = sa;
  667. }
  668. if (free_pathinfo) {
  669. efree(path_info);
  670. }
  671. sapi_header_op(SAPI_HEADER_REPLACE, &ctr);
  672. sapi_send_headers();
  673. efree(ctr.line);
  674. zend_bailout();
  675. }
  676. }
  677. if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, NULL) ||
  678. (info = phar_get_entry_info(phar, entry, entry_len, NULL, 0)) == NULL) {
  679. phar_do_404(phar, fname, fname_len, f404, f404_len, entry, entry_len);
  680. #ifdef PHP_WIN32
  681. efree(fname);
  682. #endif
  683. zend_bailout();
  684. }
  685. if (mimeoverride && zend_hash_num_elements(Z_ARRVAL_P(mimeoverride))) {
  686. const char *ext = zend_memrchr(entry, '.', entry_len);
  687. zval *val;
  688. if (ext) {
  689. ++ext;
  690. if (NULL != (val = zend_hash_str_find(Z_ARRVAL_P(mimeoverride), ext, strlen(ext)))) {
  691. switch (Z_TYPE_P(val)) {
  692. case IS_LONG:
  693. if (Z_LVAL_P(val) == PHAR_MIME_PHP || Z_LVAL_P(val) == PHAR_MIME_PHPS) {
  694. mime_type = "";
  695. code = Z_LVAL_P(val);
  696. } else {
  697. zend_throw_exception_ex(phar_ce_PharException, 0, "Unknown mime type specifier used, only Phar::PHP, Phar::PHPS and a mime type string are allowed");
  698. if (free_pathinfo) {
  699. efree(path_info);
  700. }
  701. efree(pt);
  702. efree(entry);
  703. #ifdef PHP_WIN32
  704. efree(fname);
  705. #endif
  706. RETURN_FALSE;
  707. }
  708. break;
  709. case IS_STRING:
  710. mime_type = Z_STRVAL_P(val);
  711. code = PHAR_MIME_OTHER;
  712. break;
  713. default:
  714. zend_throw_exception_ex(phar_ce_PharException, 0, "Unknown mime type specifier used (not a string or int), only Phar::PHP, Phar::PHPS and a mime type string are allowed");
  715. if (free_pathinfo) {
  716. efree(path_info);
  717. }
  718. efree(pt);
  719. efree(entry);
  720. #ifdef PHP_WIN32
  721. efree(fname);
  722. #endif
  723. RETURN_FALSE;
  724. }
  725. }
  726. }
  727. }
  728. if (!mime_type) {
  729. code = phar_file_type(&PHAR_G(mime_types), entry, &mime_type);
  730. }
  731. phar_file_action(phar, info, mime_type, code, entry, entry_len, fname, pt, ru, ru_len);
  732. }
  733. /* }}} */
  734. /* {{{ proto void Phar::mungServer(array munglist)
  735. * Defines a list of up to 4 $_SERVER variables that should be modified for execution
  736. * to mask the presence of the phar archive. This should be used in conjunction with
  737. * Phar::webPhar(), and has no effect otherwise
  738. * SCRIPT_NAME, PHP_SELF, REQUEST_URI and SCRIPT_FILENAME
  739. */
  740. PHP_METHOD(Phar, mungServer)
  741. {
  742. zval *mungvalues, *data;
  743. if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &mungvalues) == FAILURE) {
  744. return;
  745. }
  746. if (!zend_hash_num_elements(Z_ARRVAL_P(mungvalues))) {
  747. zend_throw_exception_ex(phar_ce_PharException, 0, "No values passed to Phar::mungServer(), expecting an array of any of these strings: PHP_SELF, REQUEST_URI, SCRIPT_FILENAME, SCRIPT_NAME");
  748. return;
  749. }
  750. if (zend_hash_num_elements(Z_ARRVAL_P(mungvalues)) > 4) {
  751. zend_throw_exception_ex(phar_ce_PharException, 0, "Too many values passed to Phar::mungServer(), expecting an array of any of these strings: PHP_SELF, REQUEST_URI, SCRIPT_FILENAME, SCRIPT_NAME");
  752. return;
  753. }
  754. phar_request_initialize();
  755. ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(mungvalues), data) {
  756. if (Z_TYPE_P(data) != IS_STRING) {
  757. zend_throw_exception_ex(phar_ce_PharException, 0, "Non-string value passed to Phar::mungServer(), expecting an array of any of these strings: PHP_SELF, REQUEST_URI, SCRIPT_FILENAME, SCRIPT_NAME");
  758. return;
  759. }
  760. if (Z_STRLEN_P(data) == sizeof("PHP_SELF")-1 && !strncmp(Z_STRVAL_P(data), "PHP_SELF", sizeof("PHP_SELF")-1)) {
  761. PHAR_G(phar_SERVER_mung_list) |= PHAR_MUNG_PHP_SELF;
  762. }
  763. if (Z_STRLEN_P(data) == sizeof("REQUEST_URI")-1) {
  764. if (!strncmp(Z_STRVAL_P(data), "REQUEST_URI", sizeof("REQUEST_URI")-1)) {
  765. PHAR_G(phar_SERVER_mung_list) |= PHAR_MUNG_REQUEST_URI;
  766. }
  767. if (!strncmp(Z_STRVAL_P(data), "SCRIPT_NAME", sizeof("SCRIPT_NAME")-1)) {
  768. PHAR_G(phar_SERVER_mung_list) |= PHAR_MUNG_SCRIPT_NAME;
  769. }
  770. }
  771. if (Z_STRLEN_P(data) == sizeof("SCRIPT_FILENAME")-1 && !strncmp(Z_STRVAL_P(data), "SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME")-1)) {
  772. PHAR_G(phar_SERVER_mung_list) |= PHAR_MUNG_SCRIPT_FILENAME;
  773. }
  774. } ZEND_HASH_FOREACH_END();
  775. }
  776. /* }}} */
  777. /* {{{ proto void Phar::interceptFileFuncs()
  778. * instructs phar to intercept fopen, file_get_contents, opendir, and all of the stat-related functions
  779. * and return stat on files within the phar for relative paths
  780. *
  781. * Once called, this cannot be reversed, and continue until the end of the request.
  782. *
  783. * This allows legacy scripts to be pharred unmodified
  784. */
  785. PHP_METHOD(Phar, interceptFileFuncs)
  786. {
  787. if (zend_parse_parameters_none() == FAILURE) {
  788. return;
  789. }
  790. phar_intercept_functions();
  791. }
  792. /* }}} */
  793. /* {{{ proto array Phar::createDefaultStub([string indexfile[, string webindexfile]])
  794. * Return a stub that can be used to run a phar-based archive without the phar extension
  795. * indexfile is the CLI startup filename, which defaults to "index.php", webindexfile
  796. * is the web startup filename, and also defaults to "index.php"
  797. */
  798. PHP_METHOD(Phar, createDefaultStub)
  799. {
  800. char *index = NULL, *webindex = NULL, *error;
  801. zend_string *stub;
  802. size_t index_len = 0, webindex_len = 0;
  803. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|pp", &index, &index_len, &webindex, &webindex_len) == FAILURE) {
  804. return;
  805. }
  806. stub = phar_create_default_stub(index, webindex, &error);
  807. if (error) {
  808. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  809. efree(error);
  810. return;
  811. }
  812. RETURN_NEW_STR(stub);
  813. }
  814. /* }}} */
  815. /* {{{ proto mixed Phar::mapPhar([string alias, [int dataoffset]])
  816. * Reads the currently executed file (a phar) and registers its manifest */
  817. PHP_METHOD(Phar, mapPhar)
  818. {
  819. char *alias = NULL, *error;
  820. size_t alias_len = 0;
  821. zend_long dataoffset = 0;
  822. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s!l", &alias, &alias_len, &dataoffset) == FAILURE) {
  823. return;
  824. }
  825. phar_request_initialize();
  826. RETVAL_BOOL(phar_open_executed_filename(alias, alias_len, &error) == SUCCESS);
  827. if (error) {
  828. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  829. efree(error);
  830. }
  831. } /* }}} */
  832. /* {{{ proto mixed Phar::loadPhar(string filename [, string alias])
  833. * Loads any phar archive with an alias */
  834. PHP_METHOD(Phar, loadPhar)
  835. {
  836. char *fname, *alias = NULL, *error;
  837. size_t fname_len, alias_len = 0;
  838. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|s!", &fname, &fname_len, &alias, &alias_len) == FAILURE) {
  839. return;
  840. }
  841. phar_request_initialize();
  842. RETVAL_BOOL(phar_open_from_filename(fname, fname_len, alias, alias_len, REPORT_ERRORS, NULL, &error) == SUCCESS);
  843. if (error) {
  844. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  845. efree(error);
  846. }
  847. } /* }}} */
  848. /* {{{ proto string Phar::apiVersion()
  849. * Returns the api version */
  850. PHP_METHOD(Phar, apiVersion)
  851. {
  852. if (zend_parse_parameters_none() == FAILURE) {
  853. return;
  854. }
  855. RETURN_STRINGL(PHP_PHAR_API_VERSION, sizeof(PHP_PHAR_API_VERSION)-1);
  856. }
  857. /* }}}*/
  858. /* {{{ proto bool Phar::canCompress([int method])
  859. * Returns whether phar extension supports compression using zlib/bzip2 */
  860. PHP_METHOD(Phar, canCompress)
  861. {
  862. zend_long method = 0;
  863. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &method) == FAILURE) {
  864. return;
  865. }
  866. phar_request_initialize();
  867. switch (method) {
  868. case PHAR_ENT_COMPRESSED_GZ:
  869. if (PHAR_G(has_zlib)) {
  870. RETURN_TRUE;
  871. } else {
  872. RETURN_FALSE;
  873. }
  874. case PHAR_ENT_COMPRESSED_BZ2:
  875. if (PHAR_G(has_bz2)) {
  876. RETURN_TRUE;
  877. } else {
  878. RETURN_FALSE;
  879. }
  880. default:
  881. if (PHAR_G(has_zlib) || PHAR_G(has_bz2)) {
  882. RETURN_TRUE;
  883. } else {
  884. RETURN_FALSE;
  885. }
  886. }
  887. }
  888. /* }}} */
  889. /* {{{ proto bool Phar::canWrite()
  890. * Returns whether phar extension supports writing and creating phars */
  891. PHP_METHOD(Phar, canWrite)
  892. {
  893. if (zend_parse_parameters_none() == FAILURE) {
  894. return;
  895. }
  896. RETURN_BOOL(!PHAR_G(readonly));
  897. }
  898. /* }}} */
  899. /* {{{ proto bool Phar::isValidPharFilename(string filename[, bool executable = true])
  900. * Returns whether the given filename is a valid phar filename */
  901. PHP_METHOD(Phar, isValidPharFilename)
  902. {
  903. char *fname;
  904. const char *ext_str;
  905. size_t fname_len;
  906. size_t ext_len;
  907. int is_executable;
  908. zend_bool executable = 1;
  909. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|b", &fname, &fname_len, &executable) == FAILURE) {
  910. return;
  911. }
  912. is_executable = executable;
  913. RETVAL_BOOL(phar_detect_phar_fname_ext(fname, fname_len, &ext_str, &ext_len, is_executable, 2, 1) == SUCCESS);
  914. }
  915. /* }}} */
  916. /**
  917. * from spl_directory
  918. */
  919. static void phar_spl_foreign_dtor(spl_filesystem_object *object) /* {{{ */
  920. {
  921. phar_archive_data *phar = (phar_archive_data *) object->oth;
  922. if (!phar->is_persistent) {
  923. phar_archive_delref(phar);
  924. }
  925. object->oth = NULL;
  926. }
  927. /* }}} */
  928. /**
  929. * from spl_directory
  930. */
  931. static void phar_spl_foreign_clone(spl_filesystem_object *src, spl_filesystem_object *dst) /* {{{ */
  932. {
  933. phar_archive_data *phar_data = (phar_archive_data *) dst->oth;
  934. if (!phar_data->is_persistent) {
  935. ++(phar_data->refcount);
  936. }
  937. }
  938. /* }}} */
  939. static const spl_other_handler phar_spl_foreign_handler = {
  940. phar_spl_foreign_dtor,
  941. phar_spl_foreign_clone
  942. };
  943. /* {{{ proto Phar::__construct(string fname [, int flags [, string alias]])
  944. * Construct a Phar archive object
  945. *
  946. * proto PharData::__construct(string fname [[, int flags [, string alias]], int file format = Phar::TAR])
  947. * Construct a PharData archive object
  948. *
  949. * This function is used as the constructor for both the Phar and PharData
  950. * classes, hence the two prototypes above.
  951. */
  952. PHP_METHOD(Phar, __construct)
  953. {
  954. char *fname, *alias = NULL, *error, *arch = NULL, *entry = NULL, *save_fname;
  955. size_t fname_len, alias_len = 0;
  956. size_t arch_len, entry_len;
  957. zend_bool is_data;
  958. zend_long flags = SPL_FILE_DIR_SKIPDOTS|SPL_FILE_DIR_UNIXPATHS;
  959. zend_long format = 0;
  960. phar_archive_object *phar_obj;
  961. phar_archive_data *phar_data;
  962. zval *zobj = getThis(), arg1, arg2;
  963. phar_obj = (phar_archive_object*)((char*)Z_OBJ_P(zobj) - Z_OBJ_P(zobj)->handlers->offset);
  964. is_data = instanceof_function(Z_OBJCE_P(zobj), phar_ce_data);
  965. if (is_data) {
  966. if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "p|ls!l", &fname, &fname_len, &flags, &alias, &alias_len, &format) == FAILURE) {
  967. return;
  968. }
  969. } else {
  970. if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "p|ls!", &fname, &fname_len, &flags, &alias, &alias_len) == FAILURE) {
  971. return;
  972. }
  973. }
  974. if (phar_obj->archive) {
  975. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot call constructor twice");
  976. return;
  977. }
  978. save_fname = fname;
  979. if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, !is_data, 2)) {
  980. /* use arch (the basename for the archive) for fname instead of fname */
  981. /* this allows support for RecursiveDirectoryIterator of subdirectories */
  982. #ifdef PHP_WIN32
  983. phar_unixify_path_separators(arch, arch_len);
  984. #endif
  985. fname = arch;
  986. fname_len = arch_len;
  987. #ifdef PHP_WIN32
  988. } else {
  989. arch = estrndup(fname, fname_len);
  990. arch_len = fname_len;
  991. fname = arch;
  992. phar_unixify_path_separators(arch, arch_len);
  993. #endif
  994. }
  995. if (phar_open_or_create_filename(fname, fname_len, alias, alias_len, is_data, REPORT_ERRORS, &phar_data, &error) == FAILURE) {
  996. if (fname == arch && fname != save_fname) {
  997. efree(arch);
  998. fname = save_fname;
  999. }
  1000. if (entry) {
  1001. efree(entry);
  1002. }
  1003. if (error) {
  1004. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  1005. "%s", error);
  1006. efree(error);
  1007. } else {
  1008. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  1009. "Phar creation or opening failed");
  1010. }
  1011. return;
  1012. }
  1013. if (is_data && phar_data->is_tar && phar_data->is_brandnew && format == PHAR_FORMAT_ZIP) {
  1014. phar_data->is_zip = 1;
  1015. phar_data->is_tar = 0;
  1016. }
  1017. if (fname == arch) {
  1018. efree(arch);
  1019. fname = save_fname;
  1020. }
  1021. if ((is_data && !phar_data->is_data) || (!is_data && phar_data->is_data)) {
  1022. if (is_data) {
  1023. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  1024. "PharData class can only be used for non-executable tar and zip archives");
  1025. } else {
  1026. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  1027. "Phar class can only be used for executable tar and zip archives");
  1028. }
  1029. efree(entry);
  1030. return;
  1031. }
  1032. is_data = phar_data->is_data;
  1033. if (!phar_data->is_persistent) {
  1034. ++(phar_data->refcount);
  1035. }
  1036. phar_obj->archive = phar_data;
  1037. phar_obj->spl.oth_handler = &phar_spl_foreign_handler;
  1038. if (entry) {
  1039. fname_len = spprintf(&fname, 0, "phar://%s%s", phar_data->fname, entry);
  1040. efree(entry);
  1041. } else {
  1042. fname_len = spprintf(&fname, 0, "phar://%s", phar_data->fname);
  1043. }
  1044. ZVAL_STRINGL(&arg1, fname, fname_len);
  1045. ZVAL_LONG(&arg2, flags);
  1046. zend_call_method_with_2_params(zobj, Z_OBJCE_P(zobj),
  1047. &spl_ce_RecursiveDirectoryIterator->constructor, "__construct", NULL, &arg1, &arg2);
  1048. zval_ptr_dtor(&arg1);
  1049. if (!phar_data->is_persistent) {
  1050. phar_obj->archive->is_data = is_data;
  1051. } else if (!EG(exception)) {
  1052. /* register this guy so we can modify if necessary */
  1053. zend_hash_str_add_ptr(&PHAR_G(phar_persist_map), (const char *) phar_obj->archive, sizeof(phar_obj->archive), phar_obj);
  1054. }
  1055. phar_obj->spl.info_class = phar_ce_entry;
  1056. efree(fname);
  1057. }
  1058. /* }}} */
  1059. /* {{{ proto array Phar::getSupportedSignatures()
  1060. * Return array of supported signature types
  1061. */
  1062. PHP_METHOD(Phar, getSupportedSignatures)
  1063. {
  1064. if (zend_parse_parameters_none() == FAILURE) {
  1065. return;
  1066. }
  1067. array_init(return_value);
  1068. add_next_index_stringl(return_value, "MD5", 3);
  1069. add_next_index_stringl(return_value, "SHA-1", 5);
  1070. #ifdef PHAR_HASH_OK
  1071. add_next_index_stringl(return_value, "SHA-256", 7);
  1072. add_next_index_stringl(return_value, "SHA-512", 7);
  1073. #endif
  1074. #if PHAR_HAVE_OPENSSL
  1075. add_next_index_stringl(return_value, "OpenSSL", 7);
  1076. #else
  1077. if (zend_hash_str_exists(&module_registry, "openssl", sizeof("openssl")-1)) {
  1078. add_next_index_stringl(return_value, "OpenSSL", 7);
  1079. }
  1080. #endif
  1081. }
  1082. /* }}} */
  1083. /* {{{ proto array Phar::getSupportedCompression()
  1084. * Return array of supported comparession algorithms
  1085. */
  1086. PHP_METHOD(Phar, getSupportedCompression)
  1087. {
  1088. if (zend_parse_parameters_none() == FAILURE) {
  1089. return;
  1090. }
  1091. array_init(return_value);
  1092. phar_request_initialize();
  1093. if (PHAR_G(has_zlib)) {
  1094. add_next_index_stringl(return_value, "GZ", 2);
  1095. }
  1096. if (PHAR_G(has_bz2)) {
  1097. add_next_index_stringl(return_value, "BZIP2", 5);
  1098. }
  1099. }
  1100. /* }}} */
  1101. /* {{{ proto array Phar::unlinkArchive(string archive)
  1102. * Completely remove a phar archive from memory and disk
  1103. */
  1104. PHP_METHOD(Phar, unlinkArchive)
  1105. {
  1106. char *fname, *error, *zname, *arch, *entry;
  1107. size_t fname_len;
  1108. size_t zname_len, arch_len, entry_len;
  1109. phar_archive_data *phar;
  1110. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &fname, &fname_len) == FAILURE) {
  1111. RETURN_FALSE;
  1112. }
  1113. if (!fname_len) {
  1114. zend_throw_exception_ex(phar_ce_PharException, 0, "Unknown phar archive \"\"");
  1115. return;
  1116. }
  1117. if (FAILURE == phar_open_from_filename(fname, fname_len, NULL, 0, REPORT_ERRORS, &phar, &error)) {
  1118. if (error) {
  1119. zend_throw_exception_ex(phar_ce_PharException, 0, "Unknown phar archive \"%s\": %s", fname, error);
  1120. efree(error);
  1121. } else {
  1122. zend_throw_exception_ex(phar_ce_PharException, 0, "Unknown phar archive \"%s\"", fname);
  1123. }
  1124. return;
  1125. }
  1126. zname = (char*)zend_get_executed_filename();
  1127. zname_len = strlen(zname);
  1128. if (zname_len > 7 && !memcmp(zname, "phar://", 7) && SUCCESS == phar_split_fname(zname, zname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
  1129. if ((size_t)arch_len == fname_len && !memcmp(arch, fname, arch_len)) {
  1130. zend_throw_exception_ex(phar_ce_PharException, 0, "phar archive \"%s\" cannot be unlinked from within itself", fname);
  1131. efree(arch);
  1132. efree(entry);
  1133. return;
  1134. }
  1135. efree(arch);
  1136. efree(entry);
  1137. }
  1138. if (phar->is_persistent) {
  1139. zend_throw_exception_ex(phar_ce_PharException, 0, "phar archive \"%s\" is in phar.cache_list, cannot unlinkArchive()", fname);
  1140. return;
  1141. }
  1142. if (phar->refcount) {
  1143. zend_throw_exception_ex(phar_ce_PharException, 0, "phar archive \"%s\" has open file handles or objects. fclose() all file handles, and unset() all objects prior to calling unlinkArchive()", fname);
  1144. return;
  1145. }
  1146. fname = estrndup(phar->fname, phar->fname_len);
  1147. /* invalidate phar cache */
  1148. PHAR_G(last_phar) = NULL;
  1149. PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;
  1150. phar_archive_delref(phar);
  1151. unlink(fname);
  1152. efree(fname);
  1153. RETURN_TRUE;
  1154. }
  1155. /* }}} */
  1156. #define PHAR_ARCHIVE_OBJECT() \
  1157. zval *zobj = getThis(); \
  1158. phar_archive_object *phar_obj = (phar_archive_object*)((char*)Z_OBJ_P(zobj) - Z_OBJ_P(zobj)->handlers->offset); \
  1159. if (!phar_obj->archive) { \
  1160. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
  1161. "Cannot call method on an uninitialized Phar object"); \
  1162. return; \
  1163. }
  1164. /* {{{ proto Phar::__destruct()
  1165. * if persistent, remove from the cache
  1166. */
  1167. PHP_METHOD(Phar, __destruct)
  1168. {
  1169. zval *zobj = getThis();
  1170. phar_archive_object *phar_obj = (phar_archive_object*)((char*)Z_OBJ_P(zobj) - Z_OBJ_P(zobj)->handlers->offset);
  1171. if (phar_obj->archive && phar_obj->archive->is_persistent) {
  1172. zend_hash_str_del(&PHAR_G(phar_persist_map), (const char *) phar_obj->archive, sizeof(phar_obj->archive));
  1173. }
  1174. }
  1175. /* }}} */
  1176. struct _phar_t {
  1177. phar_archive_object *p;
  1178. zend_class_entry *c;
  1179. char *b;
  1180. zval *ret;
  1181. php_stream *fp;
  1182. uint32_t l;
  1183. int count;
  1184. };
  1185. static int phar_build(zend_object_iterator *iter, void *puser) /* {{{ */
  1186. {
  1187. zval *value;
  1188. zend_bool close_fp = 1;
  1189. struct _phar_t *p_obj = (struct _phar_t*) puser;
  1190. size_t str_key_len, base_len = p_obj->l;
  1191. phar_entry_data *data;
  1192. php_stream *fp;
  1193. size_t fname_len;
  1194. size_t contents_len;
  1195. char *fname, *error = NULL, *base = p_obj->b, *save = NULL, *temp = NULL;
  1196. zend_string *opened;
  1197. char *str_key;
  1198. zend_class_entry *ce = p_obj->c;
  1199. phar_archive_object *phar_obj = p_obj->p;
  1200. php_stream_statbuf ssb;
  1201. value = iter->funcs->get_current_data(iter);
  1202. if (EG(exception)) {
  1203. return ZEND_HASH_APPLY_STOP;
  1204. }
  1205. if (!value) {
  1206. /* failure in get_current_data */
  1207. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %s returned no value", ZSTR_VAL(ce->name));
  1208. return ZEND_HASH_APPLY_STOP;
  1209. }
  1210. switch (Z_TYPE_P(value)) {
  1211. case IS_STRING:
  1212. break;
  1213. case IS_RESOURCE:
  1214. php_stream_from_zval_no_verify(fp, value);
  1215. if (!fp) {
  1216. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Iterator %s returned an invalid stream handle", ZSTR_VAL(ce->name));
  1217. return ZEND_HASH_APPLY_STOP;
  1218. }
  1219. if (iter->funcs->get_current_key) {
  1220. zval key;
  1221. iter->funcs->get_current_key(iter, &key);
  1222. if (EG(exception)) {
  1223. return ZEND_HASH_APPLY_STOP;
  1224. }
  1225. if (Z_TYPE(key) != IS_STRING) {
  1226. zval_ptr_dtor(&key);
  1227. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %s returned an invalid key (must return a string)", ZSTR_VAL(ce->name));
  1228. return ZEND_HASH_APPLY_STOP;
  1229. }
  1230. str_key_len = Z_STRLEN(key);
  1231. str_key = estrndup(Z_STRVAL(key), str_key_len);
  1232. save = str_key;
  1233. zval_ptr_dtor_str(&key);
  1234. } else {
  1235. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %s returned an invalid key (must return a string)", ZSTR_VAL(ce->name));
  1236. return ZEND_HASH_APPLY_STOP;
  1237. }
  1238. close_fp = 0;
  1239. opened = zend_string_init("[stream]", sizeof("[stream]") - 1, 0);
  1240. goto after_open_fp;
  1241. case IS_OBJECT:
  1242. if (instanceof_function(Z_OBJCE_P(value), spl_ce_SplFileInfo)) {
  1243. char *test = NULL;
  1244. zval dummy;
  1245. spl_filesystem_object *intern = (spl_filesystem_object*)((char*)Z_OBJ_P(value) - Z_OBJ_P(value)->handlers->offset);
  1246. if (!base_len) {
  1247. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Iterator %s returns an SplFileInfo object, so base directory must be specified", ZSTR_VAL(ce->name));
  1248. return ZEND_HASH_APPLY_STOP;
  1249. }
  1250. switch (intern->type) {
  1251. case SPL_FS_DIR:
  1252. test = spl_filesystem_object_get_path(intern, NULL);
  1253. fname_len = spprintf(&fname, 0, "%s%c%s", test, DEFAULT_SLASH, intern->u.dir.entry.d_name);
  1254. php_stat(fname, fname_len, FS_IS_DIR, &dummy);
  1255. if (Z_TYPE(dummy) == IS_TRUE) {
  1256. /* ignore directories */
  1257. efree(fname);
  1258. return ZEND_HASH_APPLY_KEEP;
  1259. }
  1260. test = expand_filepath(fname, NULL);
  1261. efree(fname);
  1262. if (test) {
  1263. fname = test;
  1264. fname_len = strlen(fname);
  1265. } else {
  1266. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Could not resolve file path");
  1267. return ZEND_HASH_APPLY_STOP;
  1268. }
  1269. save = fname;
  1270. goto phar_spl_fileinfo;
  1271. case SPL_FS_INFO:
  1272. case SPL_FS_FILE:
  1273. fname = expand_filepath(intern->file_name, NULL);
  1274. if (!fname) {
  1275. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Could not resolve file path");
  1276. return ZEND_HASH_APPLY_STOP;
  1277. }
  1278. fname_len = strlen(fname);
  1279. save = fname;
  1280. goto phar_spl_fileinfo;
  1281. }
  1282. }
  1283. /* fall-through */
  1284. default:
  1285. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %s returned an invalid value (must return a string)", ZSTR_VAL(ce->name));
  1286. return ZEND_HASH_APPLY_STOP;
  1287. }
  1288. fname = Z_STRVAL_P(value);
  1289. fname_len = Z_STRLEN_P(value);
  1290. phar_spl_fileinfo:
  1291. if (base_len) {
  1292. temp = expand_filepath(base, NULL);
  1293. if (!temp) {
  1294. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Could not resolve file path");
  1295. if (save) {
  1296. efree(save);
  1297. }
  1298. return ZEND_HASH_APPLY_STOP;
  1299. }
  1300. base = temp;
  1301. base_len = strlen(base);
  1302. if (strstr(fname, base)) {
  1303. str_key_len = fname_len - base_len;
  1304. if (str_key_len <= 0) {
  1305. if (save) {
  1306. efree(save);
  1307. efree(temp);
  1308. }
  1309. return ZEND_HASH_APPLY_KEEP;
  1310. }
  1311. str_key = fname + base_len;
  1312. if (*str_key == '/' || *str_key == '\\') {
  1313. str_key++;
  1314. str_key_len--;
  1315. }
  1316. } else {
  1317. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %s returned a path \"%s\" that is not in the base directory \"%s\"", ZSTR_VAL(ce->name), fname, base);
  1318. if (save) {
  1319. efree(save);
  1320. efree(temp);
  1321. }
  1322. return ZEND_HASH_APPLY_STOP;
  1323. }
  1324. } else {
  1325. if (iter->funcs->get_current_key) {
  1326. zval key;
  1327. iter->funcs->get_current_key(iter, &key);
  1328. if (EG(exception)) {
  1329. return ZEND_HASH_APPLY_STOP;
  1330. }
  1331. if (Z_TYPE(key) != IS_STRING) {
  1332. zval_ptr_dtor(&key);
  1333. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %s returned an invalid key (must return a string)", ZSTR_VAL(ce->name));
  1334. return ZEND_HASH_APPLY_STOP;
  1335. }
  1336. str_key_len = Z_STRLEN(key);
  1337. str_key = estrndup(Z_STRVAL(key), str_key_len);
  1338. save = str_key;
  1339. zval_ptr_dtor_str(&key);
  1340. } else {
  1341. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %s returned an invalid key (must return a string)", ZSTR_VAL(ce->name));
  1342. return ZEND_HASH_APPLY_STOP;
  1343. }
  1344. }
  1345. if (php_check_open_basedir(fname)) {
  1346. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %s returned a path \"%s\" that open_basedir prevents opening", ZSTR_VAL(ce->name), fname);
  1347. if (save) {
  1348. efree(save);
  1349. }
  1350. if (temp) {
  1351. efree(temp);
  1352. }
  1353. return ZEND_HASH_APPLY_STOP;
  1354. }
  1355. /* try to open source file, then create internal phar file and copy contents */
  1356. fp = php_stream_open_wrapper(fname, "rb", STREAM_MUST_SEEK|0, &opened);
  1357. if (!fp) {
  1358. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %s returned a file that could not be opened \"%s\"", ZSTR_VAL(ce->name), fname);
  1359. if (save) {
  1360. efree(save);
  1361. }
  1362. if (temp) {
  1363. efree(temp);
  1364. }
  1365. return ZEND_HASH_APPLY_STOP;
  1366. }
  1367. after_open_fp:
  1368. if (str_key_len >= sizeof(".phar")-1 && !memcmp(str_key, ".phar", sizeof(".phar")-1)) {
  1369. /* silently skip any files that would be added to the magic .phar directory */
  1370. if (save) {
  1371. efree(save);
  1372. }
  1373. if (temp) {
  1374. efree(temp);
  1375. }
  1376. if (opened) {
  1377. zend_string_release_ex(opened, 0);
  1378. }
  1379. if (close_fp) {
  1380. php_stream_close(fp);
  1381. }
  1382. return ZEND_HASH_APPLY_KEEP;
  1383. }
  1384. if (!(data = phar_get_or_create_entry_data(phar_obj->archive->fname, phar_obj->archive->fname_len, str_key, str_key_len, "w+b", 0, &error, 1))) {
  1385. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Entry %s cannot be created: %s", str_key, error);
  1386. efree(error);
  1387. if (save) {
  1388. efree(save);
  1389. }
  1390. if (opened) {
  1391. zend_string_release_ex(opened, 0);
  1392. }
  1393. if (temp) {
  1394. efree(temp);
  1395. }
  1396. if (close_fp) {
  1397. php_stream_close(fp);
  1398. }
  1399. return ZEND_HASH_APPLY_STOP;
  1400. } else {
  1401. if (error) {
  1402. efree(error);
  1403. }
  1404. /* convert to PHAR_UFP */
  1405. if (data->internal_file->fp_type == PHAR_MOD) {
  1406. php_stream_close(data->internal_file->fp);
  1407. }
  1408. data->internal_file->fp = NULL;
  1409. data->internal_file->fp_type = PHAR_UFP;
  1410. data->internal_file->offset_abs = data->internal_file->offset = php_stream_tell(p_obj->fp);
  1411. data->fp = NULL;
  1412. php_stream_copy_to_stream_ex(fp, p_obj->fp, PHP_STREAM_COPY_ALL, &contents_len);
  1413. data->internal_file->uncompressed_filesize = data->internal_file->compressed_filesize =
  1414. php_stream_tell(p_obj->fp) - data->internal_file->offset;
  1415. if (php_stream_stat(fp, &ssb) != -1) {
  1416. data->internal_file->flags = ssb.sb.st_mode & PHAR_ENT_PERM_MASK ;
  1417. } else {
  1418. #ifndef _WIN32
  1419. mode_t mask;
  1420. mask = umask(0);
  1421. umask(mask);
  1422. data->internal_file->flags &= ~mask;
  1423. #endif
  1424. }
  1425. }
  1426. if (close_fp) {
  1427. php_stream_close(fp);
  1428. }
  1429. add_assoc_str(p_obj->ret, str_key, opened);
  1430. if (save) {
  1431. efree(save);
  1432. }
  1433. if (temp) {
  1434. efree(temp);
  1435. }
  1436. data->internal_file->compressed_filesize = data->internal_file->uncompressed_filesize = contents_len;
  1437. phar_entry_delref(data);
  1438. return ZEND_HASH_APPLY_KEEP;
  1439. }
  1440. /* }}} */
  1441. /* {{{ proto array Phar::buildFromDirectory(string base_dir[, string regex])
  1442. * Construct a phar archive from an existing directory, recursively.
  1443. * Optional second parameter is a regular expression for filtering directory contents.
  1444. *
  1445. * Return value is an array mapping phar index to actual files added.
  1446. */
  1447. PHP_METHOD(Phar, buildFromDirectory)
  1448. {
  1449. char *dir, *error, *regex = NULL;
  1450. size_t dir_len, regex_len = 0;
  1451. zend_bool apply_reg = 0;
  1452. zval arg, arg2, iter, iteriter, regexiter;
  1453. struct _phar_t pass;
  1454. PHAR_ARCHIVE_OBJECT();
  1455. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  1456. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  1457. "Cannot write to archive - write operations restricted by INI setting");
  1458. return;
  1459. }
  1460. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|s", &dir, &dir_len, &regex, &regex_len) == FAILURE) {
  1461. RETURN_FALSE;
  1462. }
  1463. if (ZEND_SIZE_T_UINT_OVFL(dir_len)) {
  1464. RETURN_FALSE;
  1465. }
  1466. if (SUCCESS != object_init_ex(&iter, spl_ce_RecursiveDirectoryIterator)) {
  1467. zval_ptr_dtor(&iter);
  1468. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Unable to instantiate directory iterator for %s", phar_obj->archive->fname);
  1469. RETURN_FALSE;
  1470. }
  1471. ZVAL_STRINGL(&arg, dir, dir_len);
  1472. ZVAL_LONG(&arg2, SPL_FILE_DIR_SKIPDOTS|SPL_FILE_DIR_UNIXPATHS);
  1473. zend_call_method_with_2_params(&iter, spl_ce_RecursiveDirectoryIterator,
  1474. &spl_ce_RecursiveDirectoryIterator->constructor, "__construct", NULL, &arg, &arg2);
  1475. zval_ptr_dtor(&arg);
  1476. if (EG(exception)) {
  1477. zval_ptr_dtor(&iter);
  1478. RETURN_FALSE;
  1479. }
  1480. if (SUCCESS != object_init_ex(&iteriter, spl_ce_RecursiveIteratorIterator)) {
  1481. zval_ptr_dtor(&iter);
  1482. zval_ptr_dtor(&iteriter);
  1483. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Unable to instantiate directory iterator for %s", phar_obj->archive->fname);
  1484. RETURN_FALSE;
  1485. }
  1486. zend_call_method_with_1_params(&iteriter, spl_ce_RecursiveIteratorIterator,
  1487. &spl_ce_RecursiveIteratorIterator->constructor, "__construct", NULL, &iter);
  1488. if (EG(exception)) {
  1489. zval_ptr_dtor(&iter);
  1490. zval_ptr_dtor(&iteriter);
  1491. RETURN_FALSE;
  1492. }
  1493. zval_ptr_dtor(&iter);
  1494. if (regex_len > 0) {
  1495. apply_reg = 1;
  1496. if (SUCCESS != object_init_ex(&regexiter, spl_ce_RegexIterator)) {
  1497. zval_ptr_dtor(&iteriter);
  1498. zval_ptr_dtor(&regexiter);
  1499. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Unable to instantiate regex iterator for %s", phar_obj->archive->fname);
  1500. RETURN_FALSE;
  1501. }
  1502. ZVAL_STRINGL(&arg2, regex, regex_len);
  1503. zend_call_method_with_2_params(&regexiter, spl_ce_RegexIterator,
  1504. &spl_ce_RegexIterator->constructor, "__construct", NULL, &iteriter, &arg2);
  1505. zval_ptr_dtor(&arg2);
  1506. }
  1507. array_init(return_value);
  1508. pass.c = apply_reg ? Z_OBJCE(regexiter) : Z_OBJCE(iteriter);
  1509. pass.p = phar_obj;
  1510. pass.b = dir;
  1511. pass.l = (uint32_t)dir_len;
  1512. pass.count = 0;
  1513. pass.ret = return_value;
  1514. pass.fp = php_stream_fopen_tmpfile();
  1515. if (pass.fp == NULL) {
  1516. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" unable to create temporary file", phar_obj->archive->fname);
  1517. return;
  1518. }
  1519. if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
  1520. zval_ptr_dtor(&iteriter);
  1521. if (apply_reg) {
  1522. zval_ptr_dtor(&regexiter);
  1523. }
  1524. php_stream_close(pass.fp);
  1525. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
  1526. return;
  1527. }
  1528. if (SUCCESS == spl_iterator_apply((apply_reg ? &regexiter : &iteriter), (spl_iterator_apply_func_t) phar_build, (void *) &pass)) {
  1529. zval_ptr_dtor(&iteriter);
  1530. if (apply_reg) {
  1531. zval_ptr_dtor(&regexiter);
  1532. }
  1533. phar_obj->archive->ufp = pass.fp;
  1534. phar_flush(phar_obj->archive, 0, 0, 0, &error);
  1535. if (error) {
  1536. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  1537. efree(error);
  1538. }
  1539. } else {
  1540. zval_ptr_dtor(&iteriter);
  1541. if (apply_reg) {
  1542. zval_ptr_dtor(&regexiter);
  1543. }
  1544. php_stream_close(pass.fp);
  1545. }
  1546. }
  1547. /* }}} */
  1548. /* {{{ proto array Phar::buildFromIterator(Iterator iter[, string base_directory])
  1549. * Construct a phar archive from an iterator. The iterator must return a series of strings
  1550. * that are full paths to files that should be added to the phar. The iterator key should
  1551. * be the path that the file will have within the phar archive.
  1552. *
  1553. * If base directory is specified, then the key will be ignored, and instead the portion of
  1554. * the current value minus the base directory will be used
  1555. *
  1556. * Returned is an array mapping phar index to actual file added
  1557. */
  1558. PHP_METHOD(Phar, buildFromIterator)
  1559. {
  1560. zval *obj;
  1561. char *error;
  1562. size_t base_len = 0;
  1563. char *base = NULL;
  1564. struct _phar_t pass;
  1565. PHAR_ARCHIVE_OBJECT();
  1566. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  1567. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  1568. "Cannot write out phar archive, phar is read-only");
  1569. return;
  1570. }
  1571. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|s", &obj, zend_ce_traversable, &base, &base_len) == FAILURE) {
  1572. RETURN_FALSE;
  1573. }
  1574. if (ZEND_SIZE_T_UINT_OVFL(base_len)) {
  1575. RETURN_FALSE;
  1576. }
  1577. if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
  1578. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
  1579. return;
  1580. }
  1581. array_init(return_value);
  1582. pass.c = Z_OBJCE_P(obj);
  1583. pass.p = phar_obj;
  1584. pass.b = base;
  1585. pass.l = (uint32_t)base_len;
  1586. pass.ret = return_value;
  1587. pass.count = 0;
  1588. pass.fp = php_stream_fopen_tmpfile();
  1589. if (pass.fp == NULL) {
  1590. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\": unable to create temporary file", phar_obj->archive->fname);
  1591. return;
  1592. }
  1593. if (SUCCESS == spl_iterator_apply(obj, (spl_iterator_apply_func_t) phar_build, (void *) &pass)) {
  1594. phar_obj->archive->ufp = pass.fp;
  1595. phar_flush(phar_obj->archive, 0, 0, 0, &error);
  1596. if (error) {
  1597. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  1598. efree(error);
  1599. }
  1600. } else {
  1601. php_stream_close(pass.fp);
  1602. }
  1603. }
  1604. /* }}} */
  1605. /* {{{ proto int Phar::count()
  1606. * Returns the number of entries in the Phar archive
  1607. */
  1608. PHP_METHOD(Phar, count)
  1609. {
  1610. /* mode can be ignored, maximum depth is 1 */
  1611. zend_long mode;
  1612. PHAR_ARCHIVE_OBJECT();
  1613. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &mode) == FAILURE) {
  1614. RETURN_FALSE;
  1615. }
  1616. RETURN_LONG(zend_hash_num_elements(&phar_obj->archive->manifest));
  1617. }
  1618. /* }}} */
  1619. /* {{{ proto bool Phar::isFileFormat(int format)
  1620. * Returns true if the phar archive is based on the tar/zip/phar file format depending
  1621. * on whether Phar::TAR, Phar::ZIP or Phar::PHAR was passed in
  1622. */
  1623. PHP_METHOD(Phar, isFileFormat)
  1624. {
  1625. zend_long type;
  1626. PHAR_ARCHIVE_OBJECT();
  1627. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &type) == FAILURE) {
  1628. RETURN_FALSE;
  1629. }
  1630. switch (type) {
  1631. case PHAR_FORMAT_TAR:
  1632. RETURN_BOOL(phar_obj->archive->is_tar);
  1633. case PHAR_FORMAT_ZIP:
  1634. RETURN_BOOL(phar_obj->archive->is_zip);
  1635. case PHAR_FORMAT_PHAR:
  1636. RETURN_BOOL(!phar_obj->archive->is_tar && !phar_obj->archive->is_zip);
  1637. default:
  1638. zend_throw_exception_ex(phar_ce_PharException, 0, "Unknown file format specified");
  1639. }
  1640. }
  1641. /* }}} */
  1642. static int phar_copy_file_contents(phar_entry_info *entry, php_stream *fp) /* {{{ */
  1643. {
  1644. char *error;
  1645. zend_off_t offset;
  1646. phar_entry_info *link;
  1647. if (FAILURE == phar_open_entry_fp(entry, &error, 1)) {
  1648. if (error) {
  1649. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  1650. "Cannot convert phar archive \"%s\", unable to open entry \"%s\" contents: %s", entry->phar->fname, entry->filename, error);
  1651. efree(error);
  1652. } else {
  1653. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  1654. "Cannot convert phar archive \"%s\", unable to open entry \"%s\" contents", entry->phar->fname, entry->filename);
  1655. }
  1656. return FAILURE;
  1657. }
  1658. /* copy old contents in entirety */
  1659. phar_seek_efp(entry, 0, SEEK_SET, 0, 1);
  1660. offset = php_stream_tell(fp);
  1661. link = phar_get_link_source(entry);
  1662. if (!link) {
  1663. link = entry;
  1664. }
  1665. if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(link, 0), fp, link->uncompressed_filesize, NULL)) {
  1666. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  1667. "Cannot convert phar archive \"%s\", unable to copy entry \"%s\" contents", entry->phar->fname, entry->filename);
  1668. return FAILURE;
  1669. }
  1670. if (entry->fp_type == PHAR_MOD) {
  1671. /* save for potential restore on error */
  1672. entry->cfp = entry->fp;
  1673. entry->fp = NULL;
  1674. }
  1675. /* set new location of file contents */
  1676. entry->fp_type = PHAR_FP;
  1677. entry->offset = offset;
  1678. return SUCCESS;
  1679. }
  1680. /* }}} */
  1681. static zend_object *phar_rename_archive(phar_archive_data **sphar, char *ext) /* {{{ */
  1682. {
  1683. const char *oldname = NULL;
  1684. phar_archive_data *phar = *sphar;
  1685. char *oldpath = NULL;
  1686. char *basename = NULL, *basepath = NULL;
  1687. char *newname = NULL, *newpath = NULL;
  1688. zval ret, arg1;
  1689. zend_class_entry *ce;
  1690. char *error = NULL;
  1691. const char *pcr_error;
  1692. size_t ext_len = ext ? strlen(ext) : 0;
  1693. size_t new_len, oldname_len, phar_ext_len;
  1694. phar_archive_data *pphar = NULL;
  1695. php_stream_statbuf ssb;
  1696. int phar_ext_list_len, i = 0;
  1697. char *ext_pos = NULL;
  1698. /* Array of PHAR extensions, Must be in order, starting with longest
  1699. * ending with the shortest. */
  1700. char *phar_ext_list[] = {
  1701. ".phar.tar.bz2",
  1702. ".phar.tar.gz",
  1703. ".phar.php",
  1704. ".phar.bz2",
  1705. ".phar.zip",
  1706. ".phar.tar",
  1707. ".phar.gz",
  1708. ".tar.bz2",
  1709. ".tar.gz",
  1710. ".phar",
  1711. ".tar",
  1712. ".zip"
  1713. };
  1714. if (!ext) {
  1715. if (phar->is_zip) {
  1716. if (phar->is_data) {
  1717. ext = "zip";
  1718. } else {
  1719. ext = "phar.zip";
  1720. }
  1721. } else if (phar->is_tar) {
  1722. switch (phar->flags) {
  1723. case PHAR_FILE_COMPRESSED_GZ:
  1724. if (phar->is_data) {
  1725. ext = "tar.gz";
  1726. } else {
  1727. ext = "phar.tar.gz";
  1728. }
  1729. break;
  1730. case PHAR_FILE_COMPRESSED_BZ2:
  1731. if (phar->is_data) {
  1732. ext = "tar.bz2";
  1733. } else {
  1734. ext = "phar.tar.bz2";
  1735. }
  1736. break;
  1737. default:
  1738. if (phar->is_data) {
  1739. ext = "tar";
  1740. } else {
  1741. ext = "phar.tar";
  1742. }
  1743. }
  1744. } else {
  1745. switch (phar->flags) {
  1746. case PHAR_FILE_COMPRESSED_GZ:
  1747. ext = "phar.gz";
  1748. break;
  1749. case PHAR_FILE_COMPRESSED_BZ2:
  1750. ext = "phar.bz2";
  1751. break;
  1752. default:
  1753. ext = "phar";
  1754. }
  1755. }
  1756. } else if (phar_path_check(&ext, &ext_len, &pcr_error) > pcr_is_ok) {
  1757. if (phar->is_data) {
  1758. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "data phar converted from \"%s\" has invalid extension %s", phar->fname, ext);
  1759. } else {
  1760. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "phar converted from \"%s\" has invalid extension %s", phar->fname, ext);
  1761. }
  1762. return NULL;
  1763. }
  1764. oldpath = estrndup(phar->fname, phar->fname_len);
  1765. if ((oldname = zend_memrchr(phar->fname, '/', phar->fname_len))) {
  1766. ++oldname;
  1767. } else {
  1768. oldname = phar->fname;
  1769. }
  1770. oldname_len = strlen(oldname);
  1771. /* Copy the old name to create base for the new name */
  1772. basename = estrndup(oldname, oldname_len);
  1773. phar_ext_list_len = sizeof(phar_ext_list)/sizeof(phar_ext_list[0]);
  1774. /* Remove possible PHAR extensions */
  1775. /* phar_ext_list must be in order of longest extension to shortest */
  1776. for (i=0; i < phar_ext_list_len; i++) {
  1777. phar_ext_len = strlen(phar_ext_list[i]);
  1778. if (phar_ext_len && oldname_len > phar_ext_len) {
  1779. /* Check if the basename strings ends with the extension */
  1780. if (memcmp(phar_ext_list[i], basename + (oldname_len - phar_ext_len), phar_ext_len) == 0) {
  1781. ext_pos = basename + (oldname_len - phar_ext_len);
  1782. ext_pos[0] = '\0';
  1783. break;
  1784. }
  1785. }
  1786. ext_pos = NULL;
  1787. }
  1788. /* If no default PHAR extension found remove the last extension */
  1789. if (!ext_pos) {
  1790. ext_pos = strrchr(basename, '.');
  1791. if (ext_pos) {
  1792. ext_pos[0] = '\0';
  1793. }
  1794. }
  1795. ext_pos = NULL;
  1796. if (ext[0] == '.') {
  1797. ++ext;
  1798. }
  1799. /* Append extension to the basename */
  1800. spprintf(&newname, 0, "%s.%s", basename, ext);
  1801. efree(basename);
  1802. basepath = estrndup(oldpath, (strlen(oldpath) - oldname_len));
  1803. new_len = spprintf(&newpath, 0, "%s%s", basepath, newname);
  1804. phar->fname_len = new_len;
  1805. phar->fname = newpath;
  1806. phar->ext = newpath + phar->fname_len - strlen(ext) - 1;
  1807. efree(basepath);
  1808. efree(newname);
  1809. if (PHAR_G(manifest_cached) && NULL != (pphar = zend_hash_str_find_ptr(&cached_phars, newpath, phar->fname_len))) {
  1810. efree(oldpath);
  1811. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Unable to add newly converted phar \"%s\" to the list of phars, new phar name is in phar.cache_list", phar->fname);
  1812. return NULL;
  1813. }
  1814. if (NULL != (pphar = zend_hash_str_find_ptr(&(PHAR_G(phar_fname_map)), newpath, phar->fname_len))) {
  1815. if (pphar->fname_len == phar->fname_len && !memcmp(pphar->fname, phar->fname, phar->fname_len)) {
  1816. if (!zend_hash_num_elements(&phar->manifest)) {
  1817. pphar->is_tar = phar->is_tar;
  1818. pphar->is_zip = phar->is_zip;
  1819. pphar->is_data = phar->is_data;
  1820. pphar->flags = phar->flags;
  1821. pphar->fp = phar->fp;
  1822. phar->fp = NULL;
  1823. phar_destroy_phar_data(phar);
  1824. *sphar = NULL;
  1825. phar = pphar;
  1826. phar->refcount++;
  1827. newpath = oldpath;
  1828. goto its_ok;
  1829. }
  1830. }
  1831. efree(oldpath);
  1832. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Unable to add newly converted phar \"%s\" to the list of phars, a phar with that name already exists", phar->fname);
  1833. return NULL;
  1834. }
  1835. its_ok:
  1836. if (SUCCESS == php_stream_stat_path(newpath, &ssb)) {
  1837. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "phar \"%s\" exists and must be unlinked prior to conversion", newpath);
  1838. efree(oldpath);
  1839. return NULL;
  1840. }
  1841. if (!phar->is_data) {
  1842. if (SUCCESS != phar_detect_phar_fname_ext(newpath, phar->fname_len, (const char **) &(phar->ext), &ext_len, 1, 1, 1)) {
  1843. efree(oldpath);
  1844. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "phar \"%s\" has invalid extension %s", phar->fname, ext);
  1845. return NULL;
  1846. }
  1847. phar->ext_len = ext_len;
  1848. if (phar->alias) {
  1849. if (phar->is_temporary_alias) {
  1850. phar->alias = NULL;
  1851. phar->alias_len = 0;
  1852. } else {
  1853. phar->alias = estrndup(newpath, strlen(newpath));
  1854. phar->alias_len = strlen(newpath);
  1855. phar->is_temporary_alias = 1;
  1856. zend_hash_str_update_ptr(&(PHAR_G(phar_alias_map)), newpath, phar->fname_len, phar);
  1857. }
  1858. }
  1859. } else {
  1860. if (SUCCESS != phar_detect_phar_fname_ext(newpath, phar->fname_len, (const char **) &(phar->ext), &ext_len, 0, 1, 1)) {
  1861. efree(oldpath);
  1862. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "data phar \"%s\" has invalid extension %s", phar->fname, ext);
  1863. return NULL;
  1864. }
  1865. phar->ext_len = ext_len;
  1866. phar->alias = NULL;
  1867. phar->alias_len = 0;
  1868. }
  1869. if ((!pphar || phar == pphar) && NULL == zend_hash_str_update_ptr(&(PHAR_G(phar_fname_map)), newpath, phar->fname_len, phar)) {
  1870. efree(oldpath);
  1871. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Unable to add newly converted phar \"%s\" to the list of phars", phar->fname);
  1872. return NULL;
  1873. }
  1874. phar_flush(phar, 0, 0, 1, &error);
  1875. if (error) {
  1876. zend_hash_str_del(&(PHAR_G(phar_fname_map)), newpath, phar->fname_len);
  1877. *sphar = NULL;
  1878. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "%s", error);
  1879. efree(error);
  1880. efree(oldpath);
  1881. return NULL;
  1882. }
  1883. efree(oldpath);
  1884. if (phar->is_data) {
  1885. ce = phar_ce_data;
  1886. } else {
  1887. ce = phar_ce_archive;
  1888. }
  1889. ZVAL_NULL(&ret);
  1890. if (SUCCESS != object_init_ex(&ret, ce)) {
  1891. zval_ptr_dtor(&ret);
  1892. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Unable to instantiate phar object when converting archive \"%s\"", phar->fname);
  1893. return NULL;
  1894. }
  1895. ZVAL_STRINGL(&arg1, phar->fname, phar->fname_len);
  1896. zend_call_method_with_1_params(&ret, ce, &ce->constructor, "__construct", NULL, &arg1);
  1897. zval_ptr_dtor(&arg1);
  1898. return Z_OBJ(ret);
  1899. }
  1900. /* }}} */
  1901. static zend_object *phar_convert_to_other(phar_archive_data *source, int convert, char *ext, uint32_t flags) /* {{{ */
  1902. {
  1903. phar_archive_data *phar;
  1904. phar_entry_info *entry, newentry;
  1905. zend_object *ret;
  1906. /* invalidate phar cache */
  1907. PHAR_G(last_phar) = NULL;
  1908. PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;
  1909. phar = (phar_archive_data *) ecalloc(1, sizeof(phar_archive_data));
  1910. /* set whole-archive compression and type from parameter */
  1911. phar->flags = flags;
  1912. phar->is_data = source->is_data;
  1913. switch (convert) {
  1914. case PHAR_FORMAT_TAR:
  1915. phar->is_tar = 1;
  1916. break;
  1917. case PHAR_FORMAT_ZIP:
  1918. phar->is_zip = 1;
  1919. break;
  1920. default:
  1921. phar->is_data = 0;
  1922. break;
  1923. }
  1924. zend_hash_init(&(phar->manifest), sizeof(phar_entry_info),
  1925. zend_get_hash_value, destroy_phar_manifest_entry, 0);
  1926. zend_hash_init(&phar->mounted_dirs, sizeof(char *),
  1927. zend_get_hash_value, NULL, 0);
  1928. zend_hash_init(&phar->virtual_dirs, sizeof(char *),
  1929. zend_get_hash_value, NULL, 0);
  1930. phar->fp = php_stream_fopen_tmpfile();
  1931. if (phar->fp == NULL) {
  1932. zend_throw_exception_ex(phar_ce_PharException, 0, "unable to create temporary file");
  1933. return NULL;
  1934. }
  1935. phar->fname = source->fname;
  1936. phar->fname_len = source->fname_len;
  1937. phar->is_temporary_alias = source->is_temporary_alias;
  1938. phar->alias = source->alias;
  1939. if (Z_TYPE(source->metadata) != IS_UNDEF) {
  1940. ZVAL_DUP(&phar->metadata, &source->metadata);
  1941. phar->metadata_len = 0;
  1942. }
  1943. /* first copy each file's uncompressed contents to a temporary file and set per-file flags */
  1944. ZEND_HASH_FOREACH_PTR(&source->manifest, entry) {
  1945. newentry = *entry;
  1946. if (newentry.link) {
  1947. newentry.link = estrdup(newentry.link);
  1948. goto no_copy;
  1949. }
  1950. if (newentry.tmp) {
  1951. newentry.tmp = estrdup(newentry.tmp);
  1952. goto no_copy;
  1953. }
  1954. newentry.metadata_str.s = NULL;
  1955. if (FAILURE == phar_copy_file_contents(&newentry, phar->fp)) {
  1956. zend_hash_destroy(&(phar->manifest));
  1957. php_stream_close(phar->fp);
  1958. efree(phar);
  1959. /* exception already thrown */
  1960. return NULL;
  1961. }
  1962. no_copy:
  1963. newentry.filename = estrndup(newentry.filename, newentry.filename_len);
  1964. if (Z_TYPE(newentry.metadata) != IS_UNDEF) {
  1965. zval_copy_ctor(&newentry.metadata);
  1966. newentry.metadata_str.s = NULL;
  1967. }
  1968. newentry.is_zip = phar->is_zip;
  1969. newentry.is_tar = phar->is_tar;
  1970. if (newentry.is_tar) {
  1971. newentry.tar_type = (entry->is_dir ? TAR_DIR : TAR_FILE);
  1972. }
  1973. newentry.is_modified = 1;
  1974. newentry.phar = phar;
  1975. newentry.old_flags = newentry.flags & ~PHAR_ENT_COMPRESSION_MASK; /* remove compression from old_flags */
  1976. phar_set_inode(&newentry);
  1977. zend_hash_str_add_mem(&(phar->manifest), newentry.filename, newentry.filename_len, (void*)&newentry, sizeof(phar_entry_info));
  1978. phar_add_virtual_dirs(phar, newentry.filename, newentry.filename_len);
  1979. } ZEND_HASH_FOREACH_END();
  1980. if ((ret = phar_rename_archive(&phar, ext))) {
  1981. return ret;
  1982. } else {
  1983. if(phar != NULL) {
  1984. zend_hash_destroy(&(phar->manifest));
  1985. zend_hash_destroy(&(phar->mounted_dirs));
  1986. zend_hash_destroy(&(phar->virtual_dirs));
  1987. if (phar->fp) {
  1988. php_stream_close(phar->fp);
  1989. }
  1990. efree(phar->fname);
  1991. efree(phar);
  1992. }
  1993. return NULL;
  1994. }
  1995. }
  1996. /* }}} */
  1997. /* {{{ proto object Phar::convertToExecutable([int format[, int compression [, string file_ext]]])
  1998. * Convert a phar.tar or phar.zip archive to the phar file format. The
  1999. * optional parameter allows the user to determine the new
  2000. * filename extension (default is phar).
  2001. */
  2002. PHP_METHOD(Phar, convertToExecutable)
  2003. {
  2004. char *ext = NULL;
  2005. int is_data;
  2006. size_t ext_len = 0;
  2007. uint32_t flags;
  2008. zend_object *ret;
  2009. /* a number that is not 0, 1 or 2 (Which is also Greg's birthday, so there) */
  2010. zend_long format = 9021976, method = 9021976;
  2011. PHAR_ARCHIVE_OBJECT();
  2012. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|lls", &format, &method, &ext, &ext_len) == FAILURE) {
  2013. return;
  2014. }
  2015. if (PHAR_G(readonly)) {
  2016. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2017. "Cannot write out executable phar archive, phar is read-only");
  2018. return;
  2019. }
  2020. switch (format) {
  2021. case 9021976:
  2022. case PHAR_FORMAT_SAME: /* null is converted to 0 */
  2023. /* by default, use the existing format */
  2024. if (phar_obj->archive->is_tar) {
  2025. format = PHAR_FORMAT_TAR;
  2026. } else if (phar_obj->archive->is_zip) {
  2027. format = PHAR_FORMAT_ZIP;
  2028. } else {
  2029. format = PHAR_FORMAT_PHAR;
  2030. }
  2031. break;
  2032. case PHAR_FORMAT_PHAR:
  2033. case PHAR_FORMAT_TAR:
  2034. case PHAR_FORMAT_ZIP:
  2035. break;
  2036. default:
  2037. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2038. "Unknown file format specified, please pass one of Phar::PHAR, Phar::TAR or Phar::ZIP");
  2039. return;
  2040. }
  2041. switch (method) {
  2042. case 9021976:
  2043. flags = phar_obj->archive->flags & PHAR_FILE_COMPRESSION_MASK;
  2044. break;
  2045. case 0:
  2046. flags = PHAR_FILE_COMPRESSED_NONE;
  2047. break;
  2048. case PHAR_ENT_COMPRESSED_GZ:
  2049. if (format == PHAR_FORMAT_ZIP) {
  2050. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2051. "Cannot compress entire archive with gzip, zip archives do not support whole-archive compression");
  2052. return;
  2053. }
  2054. if (!PHAR_G(has_zlib)) {
  2055. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2056. "Cannot compress entire archive with gzip, enable ext/zlib in php.ini");
  2057. return;
  2058. }
  2059. flags = PHAR_FILE_COMPRESSED_GZ;
  2060. break;
  2061. case PHAR_ENT_COMPRESSED_BZ2:
  2062. if (format == PHAR_FORMAT_ZIP) {
  2063. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2064. "Cannot compress entire archive with bz2, zip archives do not support whole-archive compression");
  2065. return;
  2066. }
  2067. if (!PHAR_G(has_bz2)) {
  2068. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2069. "Cannot compress entire archive with bz2, enable ext/bz2 in php.ini");
  2070. return;
  2071. }
  2072. flags = PHAR_FILE_COMPRESSED_BZ2;
  2073. break;
  2074. default:
  2075. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2076. "Unknown compression specified, please pass one of Phar::GZ or Phar::BZ2");
  2077. return;
  2078. }
  2079. is_data = phar_obj->archive->is_data;
  2080. phar_obj->archive->is_data = 0;
  2081. ret = phar_convert_to_other(phar_obj->archive, format, ext, flags);
  2082. phar_obj->archive->is_data = is_data;
  2083. if (ret) {
  2084. ZVAL_OBJ(return_value, ret);
  2085. } else {
  2086. RETURN_NULL();
  2087. }
  2088. }
  2089. /* }}} */
  2090. /* {{{ proto object Phar::convertToData([int format[, int compression [, string file_ext]]])
  2091. * Convert an archive to a non-executable .tar or .zip.
  2092. * The optional parameter allows the user to determine the new
  2093. * filename extension (default is .zip or .tar).
  2094. */
  2095. PHP_METHOD(Phar, convertToData)
  2096. {
  2097. char *ext = NULL;
  2098. int is_data;
  2099. size_t ext_len = 0;
  2100. uint32_t flags;
  2101. zend_object *ret;
  2102. /* a number that is not 0, 1 or 2 (Which is also Greg's birthday so there) */
  2103. zend_long format = 9021976, method = 9021976;
  2104. PHAR_ARCHIVE_OBJECT();
  2105. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|lls", &format, &method, &ext, &ext_len) == FAILURE) {
  2106. return;
  2107. }
  2108. switch (format) {
  2109. case 9021976:
  2110. case PHAR_FORMAT_SAME: /* null is converted to 0 */
  2111. /* by default, use the existing format */
  2112. if (phar_obj->archive->is_tar) {
  2113. format = PHAR_FORMAT_TAR;
  2114. } else if (phar_obj->archive->is_zip) {
  2115. format = PHAR_FORMAT_ZIP;
  2116. } else {
  2117. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2118. "Cannot write out data phar archive, use Phar::TAR or Phar::ZIP");
  2119. return;
  2120. }
  2121. break;
  2122. case PHAR_FORMAT_PHAR:
  2123. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2124. "Cannot write out data phar archive, use Phar::TAR or Phar::ZIP");
  2125. return;
  2126. case PHAR_FORMAT_TAR:
  2127. case PHAR_FORMAT_ZIP:
  2128. break;
  2129. default:
  2130. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2131. "Unknown file format specified, please pass one of Phar::TAR or Phar::ZIP");
  2132. return;
  2133. }
  2134. switch (method) {
  2135. case 9021976:
  2136. flags = phar_obj->archive->flags & PHAR_FILE_COMPRESSION_MASK;
  2137. break;
  2138. case 0:
  2139. flags = PHAR_FILE_COMPRESSED_NONE;
  2140. break;
  2141. case PHAR_ENT_COMPRESSED_GZ:
  2142. if (format == PHAR_FORMAT_ZIP) {
  2143. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2144. "Cannot compress entire archive with gzip, zip archives do not support whole-archive compression");
  2145. return;
  2146. }
  2147. if (!PHAR_G(has_zlib)) {
  2148. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2149. "Cannot compress entire archive with gzip, enable ext/zlib in php.ini");
  2150. return;
  2151. }
  2152. flags = PHAR_FILE_COMPRESSED_GZ;
  2153. break;
  2154. case PHAR_ENT_COMPRESSED_BZ2:
  2155. if (format == PHAR_FORMAT_ZIP) {
  2156. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2157. "Cannot compress entire archive with bz2, zip archives do not support whole-archive compression");
  2158. return;
  2159. }
  2160. if (!PHAR_G(has_bz2)) {
  2161. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2162. "Cannot compress entire archive with bz2, enable ext/bz2 in php.ini");
  2163. return;
  2164. }
  2165. flags = PHAR_FILE_COMPRESSED_BZ2;
  2166. break;
  2167. default:
  2168. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2169. "Unknown compression specified, please pass one of Phar::GZ or Phar::BZ2");
  2170. return;
  2171. }
  2172. is_data = phar_obj->archive->is_data;
  2173. phar_obj->archive->is_data = 1;
  2174. ret = phar_convert_to_other(phar_obj->archive, (int)format, ext, flags);
  2175. phar_obj->archive->is_data = is_data;
  2176. if (ret) {
  2177. ZVAL_OBJ(return_value, ret);
  2178. } else {
  2179. RETURN_NULL();
  2180. }
  2181. }
  2182. /* }}} */
  2183. /* {{{ proto int|false Phar::isCompressed()
  2184. * Returns Phar::GZ or PHAR::BZ2 if the entire archive is compressed
  2185. * (.tar.gz/tar.bz2 and so on), or FALSE otherwise.
  2186. */
  2187. PHP_METHOD(Phar, isCompressed)
  2188. {
  2189. PHAR_ARCHIVE_OBJECT();
  2190. if (zend_parse_parameters_none() == FAILURE) {
  2191. return;
  2192. }
  2193. if (phar_obj->archive->flags & PHAR_FILE_COMPRESSED_GZ) {
  2194. RETURN_LONG(PHAR_ENT_COMPRESSED_GZ);
  2195. }
  2196. if (phar_obj->archive->flags & PHAR_FILE_COMPRESSED_BZ2) {
  2197. RETURN_LONG(PHAR_ENT_COMPRESSED_BZ2);
  2198. }
  2199. RETURN_FALSE;
  2200. }
  2201. /* }}} */
  2202. /* {{{ proto bool Phar::isWritable()
  2203. * Returns true if phar.readonly=0 or phar is a PharData AND the actual file is writable.
  2204. */
  2205. PHP_METHOD(Phar, isWritable)
  2206. {
  2207. php_stream_statbuf ssb;
  2208. PHAR_ARCHIVE_OBJECT();
  2209. if (zend_parse_parameters_none() == FAILURE) {
  2210. return;
  2211. }
  2212. if (!phar_obj->archive->is_writeable) {
  2213. RETURN_FALSE;
  2214. }
  2215. if (SUCCESS != php_stream_stat_path(phar_obj->archive->fname, &ssb)) {
  2216. if (phar_obj->archive->is_brandnew) {
  2217. /* assume it works if the file doesn't exist yet */
  2218. RETURN_TRUE;
  2219. }
  2220. RETURN_FALSE;
  2221. }
  2222. RETURN_BOOL((ssb.sb.st_mode & (S_IWOTH | S_IWGRP | S_IWUSR)) != 0);
  2223. }
  2224. /* }}} */
  2225. /* {{{ proto bool Phar::delete(string entry)
  2226. * Deletes a named file within the archive.
  2227. */
  2228. PHP_METHOD(Phar, delete)
  2229. {
  2230. char *fname;
  2231. size_t fname_len;
  2232. char *error;
  2233. phar_entry_info *entry;
  2234. PHAR_ARCHIVE_OBJECT();
  2235. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  2236. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2237. "Cannot write out phar archive, phar is read-only");
  2238. return;
  2239. }
  2240. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &fname, &fname_len) == FAILURE) {
  2241. RETURN_FALSE;
  2242. }
  2243. if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
  2244. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
  2245. return;
  2246. }
  2247. if (zend_hash_str_exists(&phar_obj->archive->manifest, fname, (uint32_t) fname_len)) {
  2248. if (NULL != (entry = zend_hash_str_find_ptr(&phar_obj->archive->manifest, fname, (uint32_t) fname_len))) {
  2249. if (entry->is_deleted) {
  2250. /* entry is deleted, but has not been flushed to disk yet */
  2251. RETURN_TRUE;
  2252. } else {
  2253. entry->is_deleted = 1;
  2254. entry->is_modified = 1;
  2255. phar_obj->archive->is_modified = 1;
  2256. }
  2257. }
  2258. } else {
  2259. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Entry %s does not exist and cannot be deleted", fname);
  2260. RETURN_FALSE;
  2261. }
  2262. phar_flush(phar_obj->archive, NULL, 0, 0, &error);
  2263. if (error) {
  2264. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  2265. efree(error);
  2266. }
  2267. RETURN_TRUE;
  2268. }
  2269. /* }}} */
  2270. /* {{{ proto int Phar::getAlias()
  2271. * Returns the alias for the Phar or NULL.
  2272. */
  2273. PHP_METHOD(Phar, getAlias)
  2274. {
  2275. PHAR_ARCHIVE_OBJECT();
  2276. if (zend_parse_parameters_none() == FAILURE) {
  2277. return;
  2278. }
  2279. if (phar_obj->archive->alias && phar_obj->archive->alias != phar_obj->archive->fname) {
  2280. RETURN_STRINGL(phar_obj->archive->alias, phar_obj->archive->alias_len);
  2281. }
  2282. }
  2283. /* }}} */
  2284. /* {{{ proto int Phar::getPath()
  2285. * Returns the real path to the phar archive on disk
  2286. */
  2287. PHP_METHOD(Phar, getPath)
  2288. {
  2289. PHAR_ARCHIVE_OBJECT();
  2290. if (zend_parse_parameters_none() == FAILURE) {
  2291. return;
  2292. }
  2293. RETURN_STRINGL(phar_obj->archive->fname, phar_obj->archive->fname_len);
  2294. }
  2295. /* }}} */
  2296. /* {{{ proto bool Phar::setAlias(string alias)
  2297. * Sets the alias for a Phar archive. The default value is the full path
  2298. * to the archive.
  2299. */
  2300. PHP_METHOD(Phar, setAlias)
  2301. {
  2302. char *alias, *error, *oldalias;
  2303. phar_archive_data *fd_ptr;
  2304. size_t alias_len, oldalias_len;
  2305. int old_temp, readd = 0;
  2306. PHAR_ARCHIVE_OBJECT();
  2307. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  2308. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2309. "Cannot write out phar archive, phar is read-only");
  2310. RETURN_FALSE;
  2311. }
  2312. /* invalidate phar cache */
  2313. PHAR_G(last_phar) = NULL;
  2314. PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;
  2315. if (phar_obj->archive->is_data) {
  2316. if (phar_obj->archive->is_tar) {
  2317. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2318. "A Phar alias cannot be set in a plain tar archive");
  2319. } else {
  2320. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2321. "A Phar alias cannot be set in a plain zip archive");
  2322. }
  2323. RETURN_FALSE;
  2324. }
  2325. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &alias, &alias_len) == SUCCESS) {
  2326. if (alias_len == phar_obj->archive->alias_len && memcmp(phar_obj->archive->alias, alias, alias_len) == 0) {
  2327. RETURN_TRUE;
  2328. }
  2329. if (alias_len && NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len))) {
  2330. spprintf(&error, 0, "alias \"%s\" is already used for archive \"%s\" and cannot be used for other archives", alias, fd_ptr->fname);
  2331. if (SUCCESS == phar_free_alias(fd_ptr, alias, alias_len)) {
  2332. efree(error);
  2333. goto valid_alias;
  2334. }
  2335. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  2336. efree(error);
  2337. RETURN_FALSE;
  2338. }
  2339. if (!phar_validate_alias(alias, alias_len)) {
  2340. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2341. "Invalid alias \"%s\" specified for phar \"%s\"", alias, phar_obj->archive->fname);
  2342. RETURN_FALSE;
  2343. }
  2344. valid_alias:
  2345. if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
  2346. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
  2347. return;
  2348. }
  2349. if (phar_obj->archive->alias_len && NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), phar_obj->archive->alias, phar_obj->archive->alias_len))) {
  2350. zend_hash_str_del(&(PHAR_G(phar_alias_map)), phar_obj->archive->alias, phar_obj->archive->alias_len);
  2351. readd = 1;
  2352. }
  2353. oldalias = phar_obj->archive->alias;
  2354. oldalias_len = phar_obj->archive->alias_len;
  2355. old_temp = phar_obj->archive->is_temporary_alias;
  2356. if (alias_len) {
  2357. phar_obj->archive->alias = estrndup(alias, alias_len);
  2358. } else {
  2359. phar_obj->archive->alias = NULL;
  2360. }
  2361. phar_obj->archive->alias_len = alias_len;
  2362. phar_obj->archive->is_temporary_alias = 0;
  2363. phar_flush(phar_obj->archive, NULL, 0, 0, &error);
  2364. if (error) {
  2365. phar_obj->archive->alias = oldalias;
  2366. phar_obj->archive->alias_len = oldalias_len;
  2367. phar_obj->archive->is_temporary_alias = old_temp;
  2368. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  2369. if (readd) {
  2370. zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), oldalias, oldalias_len, phar_obj->archive);
  2371. }
  2372. efree(error);
  2373. RETURN_FALSE;
  2374. }
  2375. zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len, phar_obj->archive);
  2376. if (oldalias) {
  2377. efree(oldalias);
  2378. }
  2379. RETURN_TRUE;
  2380. }
  2381. RETURN_FALSE;
  2382. }
  2383. /* }}} */
  2384. /* {{{ proto string Phar::getVersion()
  2385. * Return version info of Phar archive
  2386. */
  2387. PHP_METHOD(Phar, getVersion)
  2388. {
  2389. PHAR_ARCHIVE_OBJECT();
  2390. if (zend_parse_parameters_none() == FAILURE) {
  2391. return;
  2392. }
  2393. RETURN_STRING(phar_obj->archive->version);
  2394. }
  2395. /* }}} */
  2396. /* {{{ proto void Phar::startBuffering()
  2397. * Do not flush a writeable phar (save its contents) until explicitly requested
  2398. */
  2399. PHP_METHOD(Phar, startBuffering)
  2400. {
  2401. PHAR_ARCHIVE_OBJECT();
  2402. if (zend_parse_parameters_none() == FAILURE) {
  2403. return;
  2404. }
  2405. phar_obj->archive->donotflush = 1;
  2406. }
  2407. /* }}} */
  2408. /* {{{ proto bool Phar::isBuffering()
  2409. * Returns whether write operations are flushing to disk immediately.
  2410. */
  2411. PHP_METHOD(Phar, isBuffering)
  2412. {
  2413. PHAR_ARCHIVE_OBJECT();
  2414. if (zend_parse_parameters_none() == FAILURE) {
  2415. return;
  2416. }
  2417. RETURN_BOOL(phar_obj->archive->donotflush);
  2418. }
  2419. /* }}} */
  2420. /* {{{ proto bool Phar::stopBuffering()
  2421. * Saves the contents of a modified archive to disk.
  2422. */
  2423. PHP_METHOD(Phar, stopBuffering)
  2424. {
  2425. char *error;
  2426. PHAR_ARCHIVE_OBJECT();
  2427. if (zend_parse_parameters_none() == FAILURE) {
  2428. return;
  2429. }
  2430. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  2431. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2432. "Cannot write out phar archive, phar is read-only");
  2433. return;
  2434. }
  2435. phar_obj->archive->donotflush = 0;
  2436. phar_flush(phar_obj->archive, 0, 0, 0, &error);
  2437. if (error) {
  2438. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  2439. efree(error);
  2440. }
  2441. }
  2442. /* }}} */
  2443. /* {{{ proto bool Phar::setStub(string|stream stub [, int len])
  2444. * Change the stub in a phar, phar.tar or phar.zip archive to something other
  2445. * than the default. The stub *must* end with a call to __HALT_COMPILER().
  2446. */
  2447. PHP_METHOD(Phar, setStub)
  2448. {
  2449. zval *zstub;
  2450. char *stub, *error;
  2451. size_t stub_len;
  2452. zend_long len = -1;
  2453. php_stream *stream;
  2454. PHAR_ARCHIVE_OBJECT();
  2455. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  2456. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2457. "Cannot change stub, phar is read-only");
  2458. return;
  2459. }
  2460. if (phar_obj->archive->is_data) {
  2461. if (phar_obj->archive->is_tar) {
  2462. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2463. "A Phar stub cannot be set in a plain tar archive");
  2464. } else {
  2465. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2466. "A Phar stub cannot be set in a plain zip archive");
  2467. }
  2468. return;
  2469. }
  2470. if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "r|l", &zstub, &len) == SUCCESS) {
  2471. if ((php_stream_from_zval_no_verify(stream, zstub)) != NULL) {
  2472. if (len > 0) {
  2473. len = -len;
  2474. } else {
  2475. len = -1;
  2476. }
  2477. if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
  2478. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
  2479. return;
  2480. }
  2481. phar_flush(phar_obj->archive, (char *) zstub, len, 0, &error);
  2482. if (error) {
  2483. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  2484. efree(error);
  2485. }
  2486. RETURN_TRUE;
  2487. } else {
  2488. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2489. "Cannot change stub, unable to read from input stream");
  2490. }
  2491. } else if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &stub, &stub_len) == SUCCESS) {
  2492. if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
  2493. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
  2494. return;
  2495. }
  2496. phar_flush(phar_obj->archive, stub, stub_len, 0, &error);
  2497. if (error) {
  2498. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  2499. efree(error);
  2500. }
  2501. RETURN_TRUE;
  2502. }
  2503. RETURN_FALSE;
  2504. }
  2505. /* }}} */
  2506. /* {{{ proto bool Phar::setDefaultStub([string index[, string webindex]])
  2507. * In a pure phar archive, sets a stub that can be used to run the archive
  2508. * regardless of whether the phar extension is available. The first parameter
  2509. * is the CLI startup filename, which defaults to "index.php". The second
  2510. * parameter is the web startup filename and also defaults to "index.php"
  2511. * (falling back to CLI behaviour).
  2512. * Both parameters are optional.
  2513. * In a phar.zip or phar.tar archive, the default stub is used only to
  2514. * identify the archive to the extension as a Phar object. This allows the
  2515. * extension to treat phar.zip and phar.tar types as honorary phars. Since
  2516. * files cannot be loaded via this kind of stub, no parameters are accepted
  2517. * when the Phar object is zip- or tar-based.
  2518. */
  2519. PHP_METHOD(Phar, setDefaultStub)
  2520. {
  2521. char *index = NULL, *webindex = NULL, *error = NULL;
  2522. zend_string *stub = NULL;
  2523. size_t index_len = 0, webindex_len = 0;
  2524. int created_stub = 0;
  2525. PHAR_ARCHIVE_OBJECT();
  2526. if (phar_obj->archive->is_data) {
  2527. if (phar_obj->archive->is_tar) {
  2528. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2529. "A Phar stub cannot be set in a plain tar archive");
  2530. } else {
  2531. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2532. "A Phar stub cannot be set in a plain zip archive");
  2533. }
  2534. return;
  2535. }
  2536. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s!s", &index, &index_len, &webindex, &webindex_len) == FAILURE) {
  2537. RETURN_FALSE;
  2538. }
  2539. if (ZEND_NUM_ARGS() > 0 && (phar_obj->archive->is_tar || phar_obj->archive->is_zip)) {
  2540. php_error_docref(NULL, E_WARNING, "method accepts no arguments for a tar- or zip-based phar stub, %d given", ZEND_NUM_ARGS());
  2541. RETURN_FALSE;
  2542. }
  2543. if (PHAR_G(readonly)) {
  2544. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2545. "Cannot change stub: phar.readonly=1");
  2546. RETURN_FALSE;
  2547. }
  2548. if (!phar_obj->archive->is_tar && !phar_obj->archive->is_zip) {
  2549. stub = phar_create_default_stub(index, webindex, &error);
  2550. if (error) {
  2551. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "%s", error);
  2552. efree(error);
  2553. if (stub) {
  2554. zend_string_free(stub);
  2555. }
  2556. RETURN_FALSE;
  2557. }
  2558. created_stub = 1;
  2559. }
  2560. if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
  2561. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
  2562. return;
  2563. }
  2564. phar_flush(phar_obj->archive, stub ? ZSTR_VAL(stub) : 0, stub ? ZSTR_LEN(stub) : 0, 1, &error);
  2565. if (created_stub) {
  2566. zend_string_free(stub);
  2567. }
  2568. if (error) {
  2569. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  2570. efree(error);
  2571. RETURN_FALSE;
  2572. }
  2573. RETURN_TRUE;
  2574. }
  2575. /* }}} */
  2576. /* {{{ proto array Phar::setSignatureAlgorithm(int sigtype[, string privatekey])
  2577. * Sets the signature algorithm for a phar and applies it. The signature
  2578. * algorithm must be one of Phar::MD5, Phar::SHA1, Phar::SHA256,
  2579. * Phar::SHA512, or Phar::OPENSSL. Note that zip- based phar archives
  2580. * cannot support signatures.
  2581. */
  2582. PHP_METHOD(Phar, setSignatureAlgorithm)
  2583. {
  2584. zend_long algo;
  2585. char *error, *key = NULL;
  2586. size_t key_len = 0;
  2587. PHAR_ARCHIVE_OBJECT();
  2588. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  2589. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2590. "Cannot set signature algorithm, phar is read-only");
  2591. return;
  2592. }
  2593. if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "l|s", &algo, &key, &key_len) != SUCCESS) {
  2594. return;
  2595. }
  2596. switch (algo) {
  2597. case PHAR_SIG_SHA256:
  2598. case PHAR_SIG_SHA512:
  2599. #ifndef PHAR_HASH_OK
  2600. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2601. "SHA-256 and SHA-512 signatures are only supported if the hash extension is enabled and built non-shared");
  2602. return;
  2603. #endif
  2604. case PHAR_SIG_MD5:
  2605. case PHAR_SIG_SHA1:
  2606. case PHAR_SIG_OPENSSL:
  2607. if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
  2608. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
  2609. return;
  2610. }
  2611. phar_obj->archive->sig_flags = (php_uint32)algo;
  2612. phar_obj->archive->is_modified = 1;
  2613. PHAR_G(openssl_privatekey) = key;
  2614. PHAR_G(openssl_privatekey_len) = key_len;
  2615. phar_flush(phar_obj->archive, 0, 0, 0, &error);
  2616. if (error) {
  2617. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  2618. efree(error);
  2619. }
  2620. break;
  2621. default:
  2622. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2623. "Unknown signature algorithm specified");
  2624. }
  2625. }
  2626. /* }}} */
  2627. /* {{{ proto array|false Phar::getSignature()
  2628. * Returns a hash signature, or FALSE if the archive is unsigned.
  2629. */
  2630. PHP_METHOD(Phar, getSignature)
  2631. {
  2632. PHAR_ARCHIVE_OBJECT();
  2633. if (zend_parse_parameters_none() == FAILURE) {
  2634. return;
  2635. }
  2636. if (phar_obj->archive->signature) {
  2637. zend_string *unknown;
  2638. array_init(return_value);
  2639. add_assoc_stringl(return_value, "hash", phar_obj->archive->signature, phar_obj->archive->sig_len);
  2640. switch(phar_obj->archive->sig_flags) {
  2641. case PHAR_SIG_MD5:
  2642. add_assoc_stringl(return_value, "hash_type", "MD5", 3);
  2643. break;
  2644. case PHAR_SIG_SHA1:
  2645. add_assoc_stringl(return_value, "hash_type", "SHA-1", 5);
  2646. break;
  2647. case PHAR_SIG_SHA256:
  2648. add_assoc_stringl(return_value, "hash_type", "SHA-256", 7);
  2649. break;
  2650. case PHAR_SIG_SHA512:
  2651. add_assoc_stringl(return_value, "hash_type", "SHA-512", 7);
  2652. break;
  2653. case PHAR_SIG_OPENSSL:
  2654. add_assoc_stringl(return_value, "hash_type", "OpenSSL", 7);
  2655. break;
  2656. default:
  2657. unknown = strpprintf(0, "Unknown (%u)", phar_obj->archive->sig_flags);
  2658. add_assoc_str(return_value, "hash_type", unknown);
  2659. break;
  2660. }
  2661. } else {
  2662. RETURN_FALSE;
  2663. }
  2664. }
  2665. /* }}} */
  2666. /* {{{ proto bool Phar::getModified()
  2667. * Return whether phar was modified
  2668. */
  2669. PHP_METHOD(Phar, getModified)
  2670. {
  2671. PHAR_ARCHIVE_OBJECT();
  2672. if (zend_parse_parameters_none() == FAILURE) {
  2673. return;
  2674. }
  2675. RETURN_BOOL(phar_obj->archive->is_modified);
  2676. }
  2677. /* }}} */
  2678. static int phar_set_compression(zval *zv, void *argument) /* {{{ */
  2679. {
  2680. phar_entry_info *entry = (phar_entry_info *)Z_PTR_P(zv);
  2681. uint32_t compress = *(uint32_t *)argument;
  2682. if (entry->is_deleted) {
  2683. return ZEND_HASH_APPLY_KEEP;
  2684. }
  2685. entry->old_flags = entry->flags;
  2686. entry->flags &= ~PHAR_ENT_COMPRESSION_MASK;
  2687. entry->flags |= compress;
  2688. entry->is_modified = 1;
  2689. return ZEND_HASH_APPLY_KEEP;
  2690. }
  2691. /* }}} */
  2692. static int phar_test_compression(zval *zv, void *argument) /* {{{ */
  2693. {
  2694. phar_entry_info *entry = (phar_entry_info *)Z_PTR_P(zv);
  2695. if (entry->is_deleted) {
  2696. return ZEND_HASH_APPLY_KEEP;
  2697. }
  2698. if (!PHAR_G(has_bz2)) {
  2699. if (entry->flags & PHAR_ENT_COMPRESSED_BZ2) {
  2700. *(int *) argument = 0;
  2701. }
  2702. }
  2703. if (!PHAR_G(has_zlib)) {
  2704. if (entry->flags & PHAR_ENT_COMPRESSED_GZ) {
  2705. *(int *) argument = 0;
  2706. }
  2707. }
  2708. return ZEND_HASH_APPLY_KEEP;
  2709. }
  2710. /* }}} */
  2711. static void pharobj_set_compression(HashTable *manifest, uint32_t compress) /* {{{ */
  2712. {
  2713. zend_hash_apply_with_argument(manifest, phar_set_compression, &compress);
  2714. }
  2715. /* }}} */
  2716. static int pharobj_cancompress(HashTable *manifest) /* {{{ */
  2717. {
  2718. int test;
  2719. test = 1;
  2720. zend_hash_apply_with_argument(manifest, phar_test_compression, &test);
  2721. return test;
  2722. }
  2723. /* }}} */
  2724. /* {{{ proto object Phar::compress(int method[, string extension])
  2725. * Compress a .tar, or .phar.tar with whole-file compression
  2726. * The parameter can be one of Phar::GZ or Phar::BZ2 to specify
  2727. * the kind of compression desired
  2728. */
  2729. PHP_METHOD(Phar, compress)
  2730. {
  2731. zend_long method;
  2732. char *ext = NULL;
  2733. size_t ext_len = 0;
  2734. uint32_t flags;
  2735. zend_object *ret;
  2736. PHAR_ARCHIVE_OBJECT();
  2737. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|s", &method, &ext, &ext_len) == FAILURE) {
  2738. return;
  2739. }
  2740. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  2741. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2742. "Cannot compress phar archive, phar is read-only");
  2743. return;
  2744. }
  2745. if (phar_obj->archive->is_zip) {
  2746. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2747. "Cannot compress zip-based archives with whole-archive compression");
  2748. return;
  2749. }
  2750. switch (method) {
  2751. case 0:
  2752. flags = PHAR_FILE_COMPRESSED_NONE;
  2753. break;
  2754. case PHAR_ENT_COMPRESSED_GZ:
  2755. if (!PHAR_G(has_zlib)) {
  2756. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2757. "Cannot compress entire archive with gzip, enable ext/zlib in php.ini");
  2758. return;
  2759. }
  2760. flags = PHAR_FILE_COMPRESSED_GZ;
  2761. break;
  2762. case PHAR_ENT_COMPRESSED_BZ2:
  2763. if (!PHAR_G(has_bz2)) {
  2764. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2765. "Cannot compress entire archive with bz2, enable ext/bz2 in php.ini");
  2766. return;
  2767. }
  2768. flags = PHAR_FILE_COMPRESSED_BZ2;
  2769. break;
  2770. default:
  2771. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2772. "Unknown compression specified, please pass one of Phar::GZ or Phar::BZ2");
  2773. return;
  2774. }
  2775. if (phar_obj->archive->is_tar) {
  2776. ret = phar_convert_to_other(phar_obj->archive, PHAR_FORMAT_TAR, ext, flags);
  2777. } else {
  2778. ret = phar_convert_to_other(phar_obj->archive, PHAR_FORMAT_PHAR, ext, flags);
  2779. }
  2780. if (ret) {
  2781. ZVAL_OBJ(return_value, ret);
  2782. } else {
  2783. RETURN_NULL();
  2784. }
  2785. }
  2786. /* }}} */
  2787. /* {{{ proto object Phar::decompress([string extension])
  2788. * Decompress a .tar, or .phar.tar with whole-file compression
  2789. */
  2790. PHP_METHOD(Phar, decompress)
  2791. {
  2792. char *ext = NULL;
  2793. size_t ext_len = 0;
  2794. zend_object *ret;
  2795. PHAR_ARCHIVE_OBJECT();
  2796. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s", &ext, &ext_len) == FAILURE) {
  2797. return;
  2798. }
  2799. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  2800. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2801. "Cannot decompress phar archive, phar is read-only");
  2802. return;
  2803. }
  2804. if (phar_obj->archive->is_zip) {
  2805. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2806. "Cannot decompress zip-based archives with whole-archive compression");
  2807. return;
  2808. }
  2809. if (phar_obj->archive->is_tar) {
  2810. ret = phar_convert_to_other(phar_obj->archive, PHAR_FORMAT_TAR, ext, PHAR_FILE_COMPRESSED_NONE);
  2811. } else {
  2812. ret = phar_convert_to_other(phar_obj->archive, PHAR_FORMAT_PHAR, ext, PHAR_FILE_COMPRESSED_NONE);
  2813. }
  2814. if (ret) {
  2815. ZVAL_OBJ(return_value, ret);
  2816. } else {
  2817. RETURN_NULL();
  2818. }
  2819. }
  2820. /* }}} */
  2821. /* {{{ proto object Phar::compressFiles(int method)
  2822. * Compress all files within a phar or zip archive using the specified compression
  2823. * The parameter can be one of Phar::GZ or Phar::BZ2 to specify
  2824. * the kind of compression desired
  2825. */
  2826. PHP_METHOD(Phar, compressFiles)
  2827. {
  2828. char *error;
  2829. uint32_t flags;
  2830. zend_long method;
  2831. PHAR_ARCHIVE_OBJECT();
  2832. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &method) == FAILURE) {
  2833. return;
  2834. }
  2835. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  2836. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2837. "Phar is readonly, cannot change compression");
  2838. return;
  2839. }
  2840. switch (method) {
  2841. case PHAR_ENT_COMPRESSED_GZ:
  2842. if (!PHAR_G(has_zlib)) {
  2843. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2844. "Cannot compress files within archive with gzip, enable ext/zlib in php.ini");
  2845. return;
  2846. }
  2847. flags = PHAR_ENT_COMPRESSED_GZ;
  2848. break;
  2849. case PHAR_ENT_COMPRESSED_BZ2:
  2850. if (!PHAR_G(has_bz2)) {
  2851. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2852. "Cannot compress files within archive with bz2, enable ext/bz2 in php.ini");
  2853. return;
  2854. }
  2855. flags = PHAR_ENT_COMPRESSED_BZ2;
  2856. break;
  2857. default:
  2858. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2859. "Unknown compression specified, please pass one of Phar::GZ or Phar::BZ2");
  2860. return;
  2861. }
  2862. if (phar_obj->archive->is_tar) {
  2863. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2864. "Cannot compress with Gzip compression, tar archives cannot compress individual files, use compress() to compress the whole archive");
  2865. return;
  2866. }
  2867. if (!pharobj_cancompress(&phar_obj->archive->manifest)) {
  2868. if (flags == PHAR_FILE_COMPRESSED_GZ) {
  2869. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2870. "Cannot compress all files as Gzip, some are compressed as bzip2 and cannot be decompressed");
  2871. } else {
  2872. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2873. "Cannot compress all files as Bzip2, some are compressed as gzip and cannot be decompressed");
  2874. }
  2875. return;
  2876. }
  2877. if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
  2878. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
  2879. return;
  2880. }
  2881. pharobj_set_compression(&phar_obj->archive->manifest, flags);
  2882. phar_obj->archive->is_modified = 1;
  2883. phar_flush(phar_obj->archive, 0, 0, 0, &error);
  2884. if (error) {
  2885. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "%s", error);
  2886. efree(error);
  2887. }
  2888. }
  2889. /* }}} */
  2890. /* {{{ proto bool Phar::decompressFiles()
  2891. * decompress every file
  2892. */
  2893. PHP_METHOD(Phar, decompressFiles)
  2894. {
  2895. char *error;
  2896. PHAR_ARCHIVE_OBJECT();
  2897. if (zend_parse_parameters_none() == FAILURE) {
  2898. return;
  2899. }
  2900. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  2901. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2902. "Phar is readonly, cannot change compression");
  2903. return;
  2904. }
  2905. if (!pharobj_cancompress(&phar_obj->archive->manifest)) {
  2906. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2907. "Cannot decompress all files, some are compressed as bzip2 or gzip and cannot be decompressed");
  2908. return;
  2909. }
  2910. if (phar_obj->archive->is_tar) {
  2911. RETURN_TRUE;
  2912. } else {
  2913. if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
  2914. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
  2915. return;
  2916. }
  2917. pharobj_set_compression(&phar_obj->archive->manifest, PHAR_ENT_COMPRESSED_NONE);
  2918. }
  2919. phar_obj->archive->is_modified = 1;
  2920. phar_flush(phar_obj->archive, 0, 0, 0, &error);
  2921. if (error) {
  2922. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "%s", error);
  2923. efree(error);
  2924. }
  2925. RETURN_TRUE;
  2926. }
  2927. /* }}} */
  2928. /* {{{ proto bool Phar::copy(string oldfile, string newfile)
  2929. * copy a file internal to the phar archive to another new file within the phar
  2930. */
  2931. PHP_METHOD(Phar, copy)
  2932. {
  2933. char *oldfile, *newfile, *error;
  2934. const char *pcr_error;
  2935. size_t oldfile_len, newfile_len;
  2936. phar_entry_info *oldentry, newentry = {0}, *temp;
  2937. size_t tmp_len = 0;
  2938. PHAR_ARCHIVE_OBJECT();
  2939. if (zend_parse_parameters(ZEND_NUM_ARGS(), "pp", &oldfile, &oldfile_len, &newfile, &newfile_len) == FAILURE) {
  2940. return;
  2941. }
  2942. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  2943. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2944. "Cannot copy \"%s\" to \"%s\", phar is read-only", oldfile, newfile);
  2945. RETURN_FALSE;
  2946. }
  2947. if (oldfile_len >= sizeof(".phar")-1 && !memcmp(oldfile, ".phar", sizeof(".phar")-1)) {
  2948. /* can't copy a meta file */
  2949. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2950. "file \"%s\" cannot be copied to file \"%s\", cannot copy Phar meta-file in %s", oldfile, newfile, phar_obj->archive->fname);
  2951. RETURN_FALSE;
  2952. }
  2953. if (newfile_len >= sizeof(".phar")-1 && !memcmp(newfile, ".phar", sizeof(".phar")-1)) {
  2954. /* can't copy a meta file */
  2955. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2956. "file \"%s\" cannot be copied to file \"%s\", cannot copy to Phar meta-file in %s", oldfile, newfile, phar_obj->archive->fname);
  2957. RETURN_FALSE;
  2958. }
  2959. if (!zend_hash_str_exists(&phar_obj->archive->manifest, oldfile, (uint32_t) oldfile_len) || NULL == (oldentry = zend_hash_str_find_ptr(&phar_obj->archive->manifest, oldfile, (uint32_t) oldfile_len)) || oldentry->is_deleted) {
  2960. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2961. "file \"%s\" cannot be copied to file \"%s\", file does not exist in %s", oldfile, newfile, phar_obj->archive->fname);
  2962. RETURN_FALSE;
  2963. }
  2964. if (zend_hash_str_exists(&phar_obj->archive->manifest, newfile, (uint32_t) newfile_len)) {
  2965. if (NULL != (temp = zend_hash_str_find_ptr(&phar_obj->archive->manifest, newfile, (uint32_t) newfile_len)) || !temp->is_deleted) {
  2966. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2967. "file \"%s\" cannot be copied to file \"%s\", file must not already exist in phar %s", oldfile, newfile, phar_obj->archive->fname);
  2968. RETURN_FALSE;
  2969. }
  2970. }
  2971. tmp_len = newfile_len;
  2972. if (phar_path_check(&newfile, &tmp_len, &pcr_error) > pcr_is_ok) {
  2973. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2974. "file \"%s\" contains invalid characters %s, cannot be copied from \"%s\" in phar %s", newfile, pcr_error, oldfile, phar_obj->archive->fname);
  2975. RETURN_FALSE;
  2976. }
  2977. newfile_len = tmp_len;
  2978. if (phar_obj->archive->is_persistent) {
  2979. if (FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
  2980. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
  2981. return;
  2982. }
  2983. /* re-populate with copied-on-write entry */
  2984. oldentry = zend_hash_str_find_ptr(&phar_obj->archive->manifest, oldfile, (uint32_t) oldfile_len);
  2985. }
  2986. memcpy((void *) &newentry, oldentry, sizeof(phar_entry_info));
  2987. if (Z_TYPE(newentry.metadata) != IS_UNDEF) {
  2988. zval_copy_ctor(&newentry.metadata);
  2989. newentry.metadata_str.s = NULL;
  2990. }
  2991. newentry.filename = estrndup(newfile, newfile_len);
  2992. newentry.filename_len = newfile_len;
  2993. newentry.fp_refcount = 0;
  2994. if (oldentry->fp_type != PHAR_FP) {
  2995. if (FAILURE == phar_copy_entry_fp(oldentry, &newentry, &error)) {
  2996. efree(newentry.filename);
  2997. php_stream_close(newentry.fp);
  2998. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  2999. efree(error);
  3000. return;
  3001. }
  3002. }
  3003. zend_hash_str_add_mem(&oldentry->phar->manifest, newfile, newfile_len, &newentry, sizeof(phar_entry_info));
  3004. phar_obj->archive->is_modified = 1;
  3005. phar_flush(phar_obj->archive, 0, 0, 0, &error);
  3006. if (error) {
  3007. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  3008. efree(error);
  3009. }
  3010. RETURN_TRUE;
  3011. }
  3012. /* }}} */
  3013. /* {{{ proto int Phar::offsetExists(string entry)
  3014. * determines whether a file exists in the phar
  3015. */
  3016. PHP_METHOD(Phar, offsetExists)
  3017. {
  3018. char *fname;
  3019. size_t fname_len;
  3020. phar_entry_info *entry;
  3021. PHAR_ARCHIVE_OBJECT();
  3022. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &fname, &fname_len) == FAILURE) {
  3023. return;
  3024. }
  3025. if (zend_hash_str_exists(&phar_obj->archive->manifest, fname, (uint32_t) fname_len)) {
  3026. if (NULL != (entry = zend_hash_str_find_ptr(&phar_obj->archive->manifest, fname, (uint32_t) fname_len))) {
  3027. if (entry->is_deleted) {
  3028. /* entry is deleted, but has not been flushed to disk yet */
  3029. RETURN_FALSE;
  3030. }
  3031. }
  3032. if (fname_len >= sizeof(".phar")-1 && !memcmp(fname, ".phar", sizeof(".phar")-1)) {
  3033. /* none of these are real files, so they don't exist */
  3034. RETURN_FALSE;
  3035. }
  3036. RETURN_TRUE;
  3037. } else {
  3038. if (zend_hash_str_exists(&phar_obj->archive->virtual_dirs, fname, (uint32_t) fname_len)) {
  3039. RETURN_TRUE;
  3040. }
  3041. RETURN_FALSE;
  3042. }
  3043. }
  3044. /* }}} */
  3045. /* {{{ proto int Phar::offsetGet(string entry)
  3046. * get a PharFileInfo object for a specific file
  3047. */
  3048. PHP_METHOD(Phar, offsetGet)
  3049. {
  3050. char *fname, *error;
  3051. size_t fname_len;
  3052. zval zfname;
  3053. phar_entry_info *entry;
  3054. zend_string *sfname;
  3055. PHAR_ARCHIVE_OBJECT();
  3056. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &fname, &fname_len) == FAILURE) {
  3057. return;
  3058. }
  3059. /* security is 0 here so that we can get a better error message than "entry doesn't exist" */
  3060. if (!(entry = phar_get_entry_info_dir(phar_obj->archive, fname, fname_len, 1, &error, 0))) {
  3061. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Entry %s does not exist%s%s", fname, error?", ":"", error?error:"");
  3062. } else {
  3063. if (fname_len == sizeof(".phar/stub.php")-1 && !memcmp(fname, ".phar/stub.php", sizeof(".phar/stub.php")-1)) {
  3064. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot get stub \".phar/stub.php\" directly in phar \"%s\", use getStub", phar_obj->archive->fname);
  3065. return;
  3066. }
  3067. if (fname_len == sizeof(".phar/alias.txt")-1 && !memcmp(fname, ".phar/alias.txt", sizeof(".phar/alias.txt")-1)) {
  3068. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot get alias \".phar/alias.txt\" directly in phar \"%s\", use getAlias", phar_obj->archive->fname);
  3069. return;
  3070. }
  3071. if (fname_len >= sizeof(".phar")-1 && !memcmp(fname, ".phar", sizeof(".phar")-1)) {
  3072. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot directly get any files or directories in magic \".phar\" directory");
  3073. return;
  3074. }
  3075. if (entry->is_temp_dir) {
  3076. efree(entry->filename);
  3077. efree(entry);
  3078. }
  3079. sfname = strpprintf(0, "phar://%s/%s", phar_obj->archive->fname, fname);
  3080. ZVAL_NEW_STR(&zfname, sfname);
  3081. spl_instantiate_arg_ex1(phar_obj->spl.info_class, return_value, &zfname);
  3082. zval_ptr_dtor(&zfname);
  3083. }
  3084. }
  3085. /* }}} */
  3086. /* {{{ add a file within the phar archive from a string or resource
  3087. */
  3088. static void phar_add_file(phar_archive_data **pphar, char *filename, size_t filename_len, char *cont_str, size_t cont_len, zval *zresource)
  3089. {
  3090. size_t start_pos=0;
  3091. char *error;
  3092. size_t contents_len;
  3093. phar_entry_data *data;
  3094. php_stream *contents_file = NULL;
  3095. php_stream_statbuf ssb;
  3096. if (filename_len >= sizeof(".phar")-1) {
  3097. start_pos = ('/' == filename[0] ? 1 : 0); /* account for any leading slash: multiple-leads handled elsewhere */
  3098. if (!memcmp(&filename[start_pos], ".phar", sizeof(".phar")-1) && (filename[start_pos+5] == '/' || filename[start_pos+5] == '\\' || filename[start_pos+5] == '\0')) {
  3099. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot create any files in magic \".phar\" directory");
  3100. return;
  3101. }
  3102. }
  3103. if (!(data = phar_get_or_create_entry_data((*pphar)->fname, (*pphar)->fname_len, filename, filename_len, "w+b", 0, &error, 1))) {
  3104. if (error) {
  3105. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Entry %s does not exist and cannot be created: %s", filename, error);
  3106. efree(error);
  3107. } else {
  3108. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Entry %s does not exist and cannot be created", filename);
  3109. }
  3110. return;
  3111. } else {
  3112. if (error) {
  3113. efree(error);
  3114. }
  3115. if (!data->internal_file->is_dir) {
  3116. if (cont_str) {
  3117. contents_len = php_stream_write(data->fp, cont_str, cont_len);
  3118. if (contents_len != cont_len) {
  3119. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Entry %s could not be written to", filename);
  3120. return;
  3121. }
  3122. } else {
  3123. if (!(php_stream_from_zval_no_verify(contents_file, zresource))) {
  3124. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Entry %s could not be written to", filename);
  3125. return;
  3126. }
  3127. php_stream_copy_to_stream_ex(contents_file, data->fp, PHP_STREAM_COPY_ALL, &contents_len);
  3128. }
  3129. data->internal_file->compressed_filesize = data->internal_file->uncompressed_filesize = contents_len;
  3130. }
  3131. if (contents_file != NULL && php_stream_stat(contents_file, &ssb) != -1) {
  3132. data->internal_file->flags = ssb.sb.st_mode & PHAR_ENT_PERM_MASK ;
  3133. } else {
  3134. #ifndef _WIN32
  3135. mode_t mask;
  3136. mask = umask(0);
  3137. umask(mask);
  3138. data->internal_file->flags &= ~mask;
  3139. #endif
  3140. }
  3141. /* check for copy-on-write */
  3142. if (pphar[0] != data->phar) {
  3143. *pphar = data->phar;
  3144. }
  3145. phar_entry_delref(data);
  3146. phar_flush(*pphar, 0, 0, 0, &error);
  3147. if (error) {
  3148. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  3149. efree(error);
  3150. }
  3151. }
  3152. }
  3153. /* }}} */
  3154. /* {{{ create a directory within the phar archive
  3155. */
  3156. static void phar_mkdir(phar_archive_data **pphar, char *dirname, size_t dirname_len)
  3157. {
  3158. char *error;
  3159. phar_entry_data *data;
  3160. if (!(data = phar_get_or_create_entry_data((*pphar)->fname, (*pphar)->fname_len, dirname, dirname_len, "w+b", 2, &error, 1))) {
  3161. if (error) {
  3162. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Directory %s does not exist and cannot be created: %s", dirname, error);
  3163. efree(error);
  3164. } else {
  3165. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Directory %s does not exist and cannot be created", dirname);
  3166. }
  3167. return;
  3168. } else {
  3169. if (error) {
  3170. efree(error);
  3171. }
  3172. /* check for copy on write */
  3173. if (data->phar != *pphar) {
  3174. *pphar = data->phar;
  3175. }
  3176. phar_entry_delref(data);
  3177. phar_flush(*pphar, 0, 0, 0, &error);
  3178. if (error) {
  3179. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  3180. efree(error);
  3181. }
  3182. }
  3183. }
  3184. /* }}} */
  3185. /* {{{ proto int Phar::offsetSet(string entry, string value)
  3186. * set the contents of an internal file to those of an external file
  3187. */
  3188. PHP_METHOD(Phar, offsetSet)
  3189. {
  3190. char *fname, *cont_str = NULL;
  3191. size_t fname_len, cont_len;
  3192. zval *zresource;
  3193. PHAR_ARCHIVE_OBJECT();
  3194. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  3195. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Write operations disabled by the php.ini setting phar.readonly");
  3196. return;
  3197. }
  3198. if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "pr", &fname, &fname_len, &zresource) == FAILURE
  3199. && zend_parse_parameters(ZEND_NUM_ARGS(), "ps", &fname, &fname_len, &cont_str, &cont_len) == FAILURE) {
  3200. return;
  3201. }
  3202. if (fname_len == sizeof(".phar/stub.php")-1 && !memcmp(fname, ".phar/stub.php", sizeof(".phar/stub.php")-1)) {
  3203. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot set stub \".phar/stub.php\" directly in phar \"%s\", use setStub", phar_obj->archive->fname);
  3204. return;
  3205. }
  3206. if (fname_len == sizeof(".phar/alias.txt")-1 && !memcmp(fname, ".phar/alias.txt", sizeof(".phar/alias.txt")-1)) {
  3207. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot set alias \".phar/alias.txt\" directly in phar \"%s\", use setAlias", phar_obj->archive->fname);
  3208. return;
  3209. }
  3210. if (fname_len >= sizeof(".phar")-1 && !memcmp(fname, ".phar", sizeof(".phar")-1)) {
  3211. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot set any files or directories in magic \".phar\" directory");
  3212. return;
  3213. }
  3214. phar_add_file(&(phar_obj->archive), fname, fname_len, cont_str, cont_len, zresource);
  3215. }
  3216. /* }}} */
  3217. /* {{{ proto int Phar::offsetUnset(string entry)
  3218. * remove a file from a phar
  3219. */
  3220. PHP_METHOD(Phar, offsetUnset)
  3221. {
  3222. char *fname, *error;
  3223. size_t fname_len;
  3224. phar_entry_info *entry;
  3225. PHAR_ARCHIVE_OBJECT();
  3226. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  3227. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Write operations disabled by the php.ini setting phar.readonly");
  3228. return;
  3229. }
  3230. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &fname, &fname_len) == FAILURE) {
  3231. return;
  3232. }
  3233. if (zend_hash_str_exists(&phar_obj->archive->manifest, fname, (uint32_t) fname_len)) {
  3234. if (NULL != (entry = zend_hash_str_find_ptr(&phar_obj->archive->manifest, fname, (uint32_t) fname_len))) {
  3235. if (entry->is_deleted) {
  3236. /* entry is deleted, but has not been flushed to disk yet */
  3237. return;
  3238. }
  3239. if (phar_obj->archive->is_persistent) {
  3240. if (FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
  3241. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
  3242. return;
  3243. }
  3244. /* re-populate entry after copy on write */
  3245. entry = zend_hash_str_find_ptr(&phar_obj->archive->manifest, fname, (uint32_t) fname_len);
  3246. }
  3247. entry->is_modified = 0;
  3248. entry->is_deleted = 1;
  3249. /* we need to "flush" the stream to save the newly deleted file on disk */
  3250. phar_flush(phar_obj->archive, 0, 0, 0, &error);
  3251. if (error) {
  3252. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  3253. efree(error);
  3254. }
  3255. RETURN_TRUE;
  3256. }
  3257. } else {
  3258. RETURN_FALSE;
  3259. }
  3260. }
  3261. /* }}} */
  3262. /* {{{ proto string Phar::addEmptyDir(string dirname)
  3263. * Adds an empty directory to the phar archive
  3264. */
  3265. PHP_METHOD(Phar, addEmptyDir)
  3266. {
  3267. char *dirname;
  3268. size_t dirname_len;
  3269. PHAR_ARCHIVE_OBJECT();
  3270. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &dirname, &dirname_len) == FAILURE) {
  3271. return;
  3272. }
  3273. if (dirname_len >= sizeof(".phar")-1 && !memcmp(dirname, ".phar", sizeof(".phar")-1)) {
  3274. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot create a directory in magic \".phar\" directory");
  3275. return;
  3276. }
  3277. phar_mkdir(&phar_obj->archive, dirname, dirname_len);
  3278. }
  3279. /* }}} */
  3280. /* {{{ proto string Phar::addFile(string filename[, string localname])
  3281. * Adds a file to the archive using the filename, or the second parameter as the name within the archive
  3282. */
  3283. PHP_METHOD(Phar, addFile)
  3284. {
  3285. char *fname, *localname = NULL;
  3286. size_t fname_len, localname_len = 0;
  3287. php_stream *resource;
  3288. zval zresource;
  3289. PHAR_ARCHIVE_OBJECT();
  3290. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|s", &fname, &fname_len, &localname, &localname_len) == FAILURE) {
  3291. return;
  3292. }
  3293. if (!strstr(fname, "://") && php_check_open_basedir(fname)) {
  3294. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "phar error: unable to open file \"%s\" to add to phar archive, open_basedir restrictions prevent this", fname);
  3295. return;
  3296. }
  3297. if (!(resource = php_stream_open_wrapper(fname, "rb", 0, NULL))) {
  3298. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "phar error: unable to open file \"%s\" to add to phar archive", fname);
  3299. return;
  3300. }
  3301. if (localname) {
  3302. fname = localname;
  3303. fname_len = localname_len;
  3304. }
  3305. php_stream_to_zval(resource, &zresource);
  3306. phar_add_file(&(phar_obj->archive), fname, fname_len, NULL, 0, &zresource);
  3307. zval_ptr_dtor(&zresource);
  3308. }
  3309. /* }}} */
  3310. /* {{{ proto string Phar::addFromString(string localname, string contents)
  3311. * Adds a file to the archive using its contents as a string
  3312. */
  3313. PHP_METHOD(Phar, addFromString)
  3314. {
  3315. char *localname, *cont_str;
  3316. size_t localname_len, cont_len;
  3317. PHAR_ARCHIVE_OBJECT();
  3318. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ps", &localname, &localname_len, &cont_str, &cont_len) == FAILURE) {
  3319. return;
  3320. }
  3321. phar_add_file(&(phar_obj->archive), localname, localname_len, cont_str, cont_len, NULL);
  3322. }
  3323. /* }}} */
  3324. /* {{{ proto string Phar::getStub()
  3325. * Returns the stub at the head of a phar archive as a string.
  3326. */
  3327. PHP_METHOD(Phar, getStub)
  3328. {
  3329. size_t len;
  3330. zend_string *buf;
  3331. php_stream *fp;
  3332. php_stream_filter *filter = NULL;
  3333. phar_entry_info *stub;
  3334. PHAR_ARCHIVE_OBJECT();
  3335. if (zend_parse_parameters_none() == FAILURE) {
  3336. return;
  3337. }
  3338. if (phar_obj->archive->is_tar || phar_obj->archive->is_zip) {
  3339. if (NULL != (stub = zend_hash_str_find_ptr(&(phar_obj->archive->manifest), ".phar/stub.php", sizeof(".phar/stub.php")-1))) {
  3340. if (phar_obj->archive->fp && !phar_obj->archive->is_brandnew && !(stub->flags & PHAR_ENT_COMPRESSION_MASK)) {
  3341. fp = phar_obj->archive->fp;
  3342. } else {
  3343. if (!(fp = php_stream_open_wrapper(phar_obj->archive->fname, "rb", 0, NULL))) {
  3344. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "phar error: unable to open phar \"%s\"", phar_obj->archive->fname);
  3345. return;
  3346. }
  3347. if (stub->flags & PHAR_ENT_COMPRESSION_MASK) {
  3348. char *filter_name;
  3349. if ((filter_name = phar_decompress_filter(stub, 0)) != NULL) {
  3350. filter = php_stream_filter_create(filter_name, NULL, php_stream_is_persistent(fp));
  3351. } else {
  3352. filter = NULL;
  3353. }
  3354. if (!filter) {
  3355. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "phar error: unable to read stub of phar \"%s\" (cannot create %s filter)", phar_obj->archive->fname, phar_decompress_filter(stub, 1));
  3356. return;
  3357. }
  3358. php_stream_filter_append(&fp->readfilters, filter);
  3359. }
  3360. }
  3361. if (!fp) {
  3362. zend_throw_exception_ex(spl_ce_RuntimeException, 0,
  3363. "Unable to read stub");
  3364. return;
  3365. }
  3366. php_stream_seek(fp, stub->offset_abs, SEEK_SET);
  3367. len = stub->uncompressed_filesize;
  3368. goto carry_on;
  3369. } else {
  3370. RETURN_EMPTY_STRING();
  3371. }
  3372. }
  3373. len = phar_obj->archive->halt_offset;
  3374. if (phar_obj->archive->fp && !phar_obj->archive->is_brandnew) {
  3375. fp = phar_obj->archive->fp;
  3376. } else {
  3377. fp = php_stream_open_wrapper(phar_obj->archive->fname, "rb", 0, NULL);
  3378. }
  3379. if (!fp) {
  3380. zend_throw_exception_ex(spl_ce_RuntimeException, 0,
  3381. "Unable to read stub");
  3382. return;
  3383. }
  3384. php_stream_rewind(fp);
  3385. carry_on:
  3386. buf = zend_string_alloc(len, 0);
  3387. if (len != php_stream_read(fp, ZSTR_VAL(buf), len)) {
  3388. if (fp != phar_obj->archive->fp) {
  3389. php_stream_close(fp);
  3390. }
  3391. zend_throw_exception_ex(spl_ce_RuntimeException, 0,
  3392. "Unable to read stub");
  3393. zend_string_release_ex(buf, 0);
  3394. return;
  3395. }
  3396. if (filter) {
  3397. php_stream_filter_flush(filter, 1);
  3398. php_stream_filter_remove(filter, 1);
  3399. }
  3400. if (fp != phar_obj->archive->fp) {
  3401. php_stream_close(fp);
  3402. }
  3403. ZSTR_VAL(buf)[len] = '\0';
  3404. ZSTR_LEN(buf) = len;
  3405. RETVAL_STR(buf);
  3406. }
  3407. /* }}}*/
  3408. /* {{{ proto int Phar::hasMetaData()
  3409. * Returns TRUE if the phar has global metadata, FALSE otherwise.
  3410. */
  3411. PHP_METHOD(Phar, hasMetadata)
  3412. {
  3413. PHAR_ARCHIVE_OBJECT();
  3414. RETURN_BOOL(Z_TYPE(phar_obj->archive->metadata) != IS_UNDEF);
  3415. }
  3416. /* }}} */
  3417. /* {{{ proto int Phar::getMetaData()
  3418. * Returns the global metadata of the phar
  3419. */
  3420. PHP_METHOD(Phar, getMetadata)
  3421. {
  3422. PHAR_ARCHIVE_OBJECT();
  3423. if (zend_parse_parameters_none() == FAILURE) {
  3424. return;
  3425. }
  3426. if (Z_TYPE(phar_obj->archive->metadata) != IS_UNDEF) {
  3427. if (phar_obj->archive->is_persistent) {
  3428. char *buf = estrndup((char *) Z_PTR(phar_obj->archive->metadata), phar_obj->archive->metadata_len);
  3429. /* assume success, we would have failed before */
  3430. phar_parse_metadata(&buf, return_value, phar_obj->archive->metadata_len);
  3431. efree(buf);
  3432. } else {
  3433. ZVAL_COPY(return_value, &phar_obj->archive->metadata);
  3434. }
  3435. }
  3436. }
  3437. /* }}} */
  3438. /* {{{ proto int Phar::setMetaData(mixed $metadata)
  3439. * Sets the global metadata of the phar
  3440. */
  3441. PHP_METHOD(Phar, setMetadata)
  3442. {
  3443. char *error;
  3444. zval *metadata;
  3445. PHAR_ARCHIVE_OBJECT();
  3446. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  3447. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Write operations disabled by the php.ini setting phar.readonly");
  3448. return;
  3449. }
  3450. if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &metadata) == FAILURE) {
  3451. return;
  3452. }
  3453. if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
  3454. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
  3455. return;
  3456. }
  3457. if (Z_TYPE(phar_obj->archive->metadata) != IS_UNDEF) {
  3458. zval_ptr_dtor(&phar_obj->archive->metadata);
  3459. ZVAL_UNDEF(&phar_obj->archive->metadata);
  3460. }
  3461. ZVAL_COPY(&phar_obj->archive->metadata, metadata);
  3462. phar_obj->archive->is_modified = 1;
  3463. phar_flush(phar_obj->archive, 0, 0, 0, &error);
  3464. if (error) {
  3465. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  3466. efree(error);
  3467. }
  3468. }
  3469. /* }}} */
  3470. /* {{{ proto int Phar::delMetadata()
  3471. * Deletes the global metadata of the phar
  3472. */
  3473. PHP_METHOD(Phar, delMetadata)
  3474. {
  3475. char *error;
  3476. PHAR_ARCHIVE_OBJECT();
  3477. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  3478. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Write operations disabled by the php.ini setting phar.readonly");
  3479. return;
  3480. }
  3481. if (Z_TYPE(phar_obj->archive->metadata) != IS_UNDEF) {
  3482. zval_ptr_dtor(&phar_obj->archive->metadata);
  3483. ZVAL_UNDEF(&phar_obj->archive->metadata);
  3484. phar_obj->archive->is_modified = 1;
  3485. phar_flush(phar_obj->archive, 0, 0, 0, &error);
  3486. if (error) {
  3487. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  3488. efree(error);
  3489. RETURN_FALSE;
  3490. } else {
  3491. RETURN_TRUE;
  3492. }
  3493. } else {
  3494. RETURN_TRUE;
  3495. }
  3496. }
  3497. /* }}} */
  3498. static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char *dest, size_t dest_len, char **error) /* {{{ */
  3499. {
  3500. php_stream_statbuf ssb;
  3501. size_t len;
  3502. php_stream *fp;
  3503. char *fullpath;
  3504. const char *slash;
  3505. mode_t mode;
  3506. cwd_state new_state;
  3507. char *filename;
  3508. size_t filename_len;
  3509. if (entry->is_mounted) {
  3510. /* silently ignore mounted entries */
  3511. return SUCCESS;
  3512. }
  3513. if (entry->filename_len >= sizeof(".phar")-1 && !memcmp(entry->filename, ".phar", sizeof(".phar")-1)) {
  3514. return SUCCESS;
  3515. }
  3516. /* strip .. from path and restrict it to be under dest directory */
  3517. new_state.cwd = (char*)emalloc(2);
  3518. new_state.cwd[0] = DEFAULT_SLASH;
  3519. new_state.cwd[1] = '\0';
  3520. new_state.cwd_length = 1;
  3521. if (virtual_file_ex(&new_state, entry->filename, NULL, CWD_EXPAND) != 0 ||
  3522. new_state.cwd_length <= 1) {
  3523. if (EINVAL == errno && entry->filename_len > 50) {
  3524. char *tmp = estrndup(entry->filename, 50);
  3525. spprintf(error, 4096, "Cannot extract \"%s...\" to \"%s...\", extracted filename is too long for filesystem", tmp, dest);
  3526. efree(tmp);
  3527. } else {
  3528. spprintf(error, 4096, "Cannot extract \"%s\", internal error", entry->filename);
  3529. }
  3530. efree(new_state.cwd);
  3531. return FAILURE;
  3532. }
  3533. filename = new_state.cwd + 1;
  3534. filename_len = new_state.cwd_length - 1;
  3535. #ifdef PHP_WIN32
  3536. /* unixify the path back, otherwise non zip formats might be broken */
  3537. {
  3538. size_t cnt = 0;
  3539. do {
  3540. if ('\\' == filename[cnt]) {
  3541. filename[cnt] = '/';
  3542. }
  3543. } while (cnt++ < filename_len);
  3544. }
  3545. #endif
  3546. len = spprintf(&fullpath, 0, "%s/%s", dest, filename);
  3547. if (len >= MAXPATHLEN) {
  3548. char *tmp;
  3549. /* truncate for error message */
  3550. fullpath[50] = '\0';
  3551. if (entry->filename_len > 50) {
  3552. tmp = estrndup(entry->filename, 50);
  3553. spprintf(error, 4096, "Cannot extract \"%s...\" to \"%s...\", extracted filename is too long for filesystem", tmp, fullpath);
  3554. efree(tmp);
  3555. } else {
  3556. spprintf(error, 4096, "Cannot extract \"%s\" to \"%s...\", extracted filename is too long for filesystem", entry->filename, fullpath);
  3557. }
  3558. efree(fullpath);
  3559. efree(new_state.cwd);
  3560. return FAILURE;
  3561. }
  3562. if (!len) {
  3563. spprintf(error, 4096, "Cannot extract \"%s\", internal error", entry->filename);
  3564. efree(fullpath);
  3565. efree(new_state.cwd);
  3566. return FAILURE;
  3567. }
  3568. if (php_check_open_basedir(fullpath)) {
  3569. spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", openbasedir/safe mode restrictions in effect", entry->filename, fullpath);
  3570. efree(fullpath);
  3571. efree(new_state.cwd);
  3572. return FAILURE;
  3573. }
  3574. /* let see if the path already exists */
  3575. if (!overwrite && SUCCESS == php_stream_stat_path(fullpath, &ssb)) {
  3576. spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", path already exists", entry->filename, fullpath);
  3577. efree(fullpath);
  3578. efree(new_state.cwd);
  3579. return FAILURE;
  3580. }
  3581. /* perform dirname */
  3582. slash = zend_memrchr(filename, '/', filename_len);
  3583. if (slash) {
  3584. fullpath[dest_len + (slash - filename) + 1] = '\0';
  3585. } else {
  3586. fullpath[dest_len] = '\0';
  3587. }
  3588. if (FAILURE == php_stream_stat_path(fullpath, &ssb)) {
  3589. if (entry->is_dir) {
  3590. if (!php_stream_mkdir(fullpath, entry->flags & PHAR_ENT_PERM_MASK, PHP_STREAM_MKDIR_RECURSIVE, NULL)) {
  3591. spprintf(error, 4096, "Cannot extract \"%s\", could not create directory \"%s\"", entry->filename, fullpath);
  3592. efree(fullpath);
  3593. efree(new_state.cwd);
  3594. return FAILURE;
  3595. }
  3596. } else {
  3597. if (!php_stream_mkdir(fullpath, 0777, PHP_STREAM_MKDIR_RECURSIVE, NULL)) {
  3598. spprintf(error, 4096, "Cannot extract \"%s\", could not create directory \"%s\"", entry->filename, fullpath);
  3599. efree(fullpath);
  3600. efree(new_state.cwd);
  3601. return FAILURE;
  3602. }
  3603. }
  3604. }
  3605. if (slash) {
  3606. fullpath[dest_len + (slash - filename) + 1] = '/';
  3607. } else {
  3608. fullpath[dest_len] = '/';
  3609. }
  3610. filename = NULL;
  3611. efree(new_state.cwd);
  3612. /* it is a standalone directory, job done */
  3613. if (entry->is_dir) {
  3614. efree(fullpath);
  3615. return SUCCESS;
  3616. }
  3617. fp = php_stream_open_wrapper(fullpath, "w+b", REPORT_ERRORS, NULL);
  3618. if (!fp) {
  3619. spprintf(error, 4096, "Cannot extract \"%s\", could not open for writing \"%s\"", entry->filename, fullpath);
  3620. efree(fullpath);
  3621. return FAILURE;
  3622. }
  3623. if (!phar_get_efp(entry, 0)) {
  3624. if (FAILURE == phar_open_entry_fp(entry, error, 1)) {
  3625. if (error) {
  3626. spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", unable to open internal file pointer: %s", entry->filename, fullpath, *error);
  3627. } else {
  3628. spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", unable to open internal file pointer", entry->filename, fullpath);
  3629. }
  3630. efree(fullpath);
  3631. php_stream_close(fp);
  3632. return FAILURE;
  3633. }
  3634. }
  3635. if (FAILURE == phar_seek_efp(entry, 0, SEEK_SET, 0, 0)) {
  3636. spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", unable to seek internal file pointer", entry->filename, fullpath);
  3637. efree(fullpath);
  3638. php_stream_close(fp);
  3639. return FAILURE;
  3640. }
  3641. if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(entry, 0), fp, entry->uncompressed_filesize, NULL)) {
  3642. spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", copying contents failed", entry->filename, fullpath);
  3643. efree(fullpath);
  3644. php_stream_close(fp);
  3645. return FAILURE;
  3646. }
  3647. php_stream_close(fp);
  3648. mode = (mode_t) entry->flags & PHAR_ENT_PERM_MASK;
  3649. if (FAILURE == VCWD_CHMOD(fullpath, mode)) {
  3650. spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", setting file permissions failed", entry->filename, fullpath);
  3651. efree(fullpath);
  3652. return FAILURE;
  3653. }
  3654. efree(fullpath);
  3655. return SUCCESS;
  3656. }
  3657. /* }}} */
  3658. static int extract_helper(phar_archive_data *archive, zend_string *search, char *pathto, size_t pathto_len, zend_bool overwrite, char **error) { /* {{{ */
  3659. int extracted = 0;
  3660. phar_entry_info *entry;
  3661. if (!search) {
  3662. /* nothing to match -- extract all files */
  3663. ZEND_HASH_FOREACH_PTR(&archive->manifest, entry) {
  3664. if (FAILURE == phar_extract_file(overwrite, entry, pathto, pathto_len, error)) return -1;
  3665. extracted++;
  3666. } ZEND_HASH_FOREACH_END();
  3667. } else if ('/' == ZSTR_VAL(search)[ZSTR_LEN(search) - 1]) {
  3668. /* ends in "/" -- extract all entries having that prefix */
  3669. ZEND_HASH_FOREACH_PTR(&archive->manifest, entry) {
  3670. if (0 != strncmp(ZSTR_VAL(search), entry->filename, ZSTR_LEN(search))) continue;
  3671. if (FAILURE == phar_extract_file(overwrite, entry, pathto, pathto_len, error)) return -1;
  3672. extracted++;
  3673. } ZEND_HASH_FOREACH_END();
  3674. } else {
  3675. /* otherwise, looking for an exact match */
  3676. entry = zend_hash_find_ptr(&archive->manifest, search);
  3677. if (NULL == entry) return 0;
  3678. if (FAILURE == phar_extract_file(overwrite, entry, pathto, pathto_len, error)) return -1;
  3679. return 1;
  3680. }
  3681. return extracted;
  3682. }
  3683. /* }}} */
  3684. /* {{{ proto bool Phar::extractTo(string pathto[[, mixed files], bool overwrite])
  3685. * Extract one or more file from a phar archive, optionally overwriting existing files
  3686. */
  3687. PHP_METHOD(Phar, extractTo)
  3688. {
  3689. php_stream *fp;
  3690. php_stream_statbuf ssb;
  3691. char *pathto;
  3692. zend_string *filename;
  3693. size_t pathto_len;
  3694. int ret;
  3695. zval *zval_file;
  3696. zval *zval_files = NULL;
  3697. zend_bool overwrite = 0;
  3698. char *error = NULL;
  3699. PHAR_ARCHIVE_OBJECT();
  3700. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|z!b", &pathto, &pathto_len, &zval_files, &overwrite) == FAILURE) {
  3701. return;
  3702. }
  3703. fp = php_stream_open_wrapper(phar_obj->archive->fname, "rb", IGNORE_URL|STREAM_MUST_SEEK, NULL);
  3704. if (!fp) {
  3705. zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0,
  3706. "Invalid argument, %s cannot be found", phar_obj->archive->fname);
  3707. return;
  3708. }
  3709. php_stream_close(fp);
  3710. if (pathto_len < 1) {
  3711. zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0,
  3712. "Invalid argument, extraction path must be non-zero length");
  3713. return;
  3714. }
  3715. if (pathto_len >= MAXPATHLEN) {
  3716. char *tmp = estrndup(pathto, 50);
  3717. /* truncate for error message */
  3718. zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "Cannot extract to \"%s...\", destination directory is too long for filesystem", tmp);
  3719. efree(tmp);
  3720. return;
  3721. }
  3722. if (php_stream_stat_path(pathto, &ssb) < 0) {
  3723. ret = php_stream_mkdir(pathto, 0777, PHP_STREAM_MKDIR_RECURSIVE, NULL);
  3724. if (!ret) {
  3725. zend_throw_exception_ex(spl_ce_RuntimeException, 0,
  3726. "Unable to create path \"%s\" for extraction", pathto);
  3727. return;
  3728. }
  3729. } else if (!(ssb.sb.st_mode & S_IFDIR)) {
  3730. zend_throw_exception_ex(spl_ce_RuntimeException, 0,
  3731. "Unable to use path \"%s\" for extraction, it is a file, must be a directory", pathto);
  3732. return;
  3733. }
  3734. if (zval_files) {
  3735. switch (Z_TYPE_P(zval_files)) {
  3736. case IS_NULL:
  3737. filename = NULL;
  3738. break;
  3739. case IS_STRING:
  3740. filename = Z_STR_P(zval_files);
  3741. break;
  3742. case IS_ARRAY:
  3743. if (zend_hash_num_elements(Z_ARRVAL_P(zval_files)) == 0) {
  3744. RETURN_FALSE;
  3745. }
  3746. ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(zval_files), zval_file) {
  3747. ZVAL_DEREF(zval_file);
  3748. if (IS_STRING != Z_TYPE_P(zval_file)) {
  3749. zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0,
  3750. "Invalid argument, array of filenames to extract contains non-string value");
  3751. return;
  3752. }
  3753. switch (extract_helper(phar_obj->archive, Z_STR_P(zval_file), pathto, pathto_len, overwrite, &error)) {
  3754. case -1:
  3755. zend_throw_exception_ex(phar_ce_PharException, 0, "Extraction from phar \"%s\" failed: %s",
  3756. phar_obj->archive->fname, error);
  3757. efree(error);
  3758. return;
  3759. case 0:
  3760. zend_throw_exception_ex(phar_ce_PharException, 0,
  3761. "Phar Error: attempted to extract non-existent file or directory \"%s\" from phar \"%s\"",
  3762. ZSTR_VAL(Z_STR_P(zval_file)), phar_obj->archive->fname);
  3763. return;
  3764. }
  3765. } ZEND_HASH_FOREACH_END();
  3766. RETURN_TRUE;
  3767. default:
  3768. zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0,
  3769. "Invalid argument, expected a filename (string) or array of filenames");
  3770. return;
  3771. }
  3772. } else {
  3773. filename = NULL;
  3774. }
  3775. ret = extract_helper(phar_obj->archive, filename, pathto, pathto_len, overwrite, &error);
  3776. if (-1 == ret) {
  3777. zend_throw_exception_ex(phar_ce_PharException, 0, "Extraction from phar \"%s\" failed: %s",
  3778. phar_obj->archive->fname, error);
  3779. efree(error);
  3780. } else if (0 == ret && NULL != filename) {
  3781. zend_throw_exception_ex(phar_ce_PharException, 0,
  3782. "Phar Error: attempted to extract non-existent file or directory \"%s\" from phar \"%s\"",
  3783. ZSTR_VAL(filename), phar_obj->archive->fname);
  3784. } else {
  3785. RETURN_TRUE;
  3786. }
  3787. }
  3788. /* }}} */
  3789. /* {{{ proto PharFileInfo::__construct(string entry)
  3790. * Construct a Phar entry object
  3791. */
  3792. PHP_METHOD(PharFileInfo, __construct)
  3793. {
  3794. char *fname, *arch, *entry, *error;
  3795. size_t fname_len;
  3796. size_t arch_len, entry_len;
  3797. phar_entry_object *entry_obj;
  3798. phar_entry_info *entry_info;
  3799. phar_archive_data *phar_data;
  3800. zval *zobj = getThis(), arg1;
  3801. if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "p", &fname, &fname_len) == FAILURE) {
  3802. return;
  3803. }
  3804. entry_obj = (phar_entry_object*)((char*)Z_OBJ_P(zobj) - Z_OBJ_P(zobj)->handlers->offset);
  3805. if (entry_obj->entry) {
  3806. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot call constructor twice");
  3807. return;
  3808. }
  3809. if (fname_len < 7 || memcmp(fname, "phar://", 7) || phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0) == FAILURE) {
  3810. zend_throw_exception_ex(spl_ce_RuntimeException, 0,
  3811. "'%s' is not a valid phar archive URL (must have at least phar://filename.phar)", fname);
  3812. return;
  3813. }
  3814. if (phar_open_from_filename(arch, arch_len, NULL, 0, REPORT_ERRORS, &phar_data, &error) == FAILURE) {
  3815. efree(arch);
  3816. efree(entry);
  3817. if (error) {
  3818. zend_throw_exception_ex(spl_ce_RuntimeException, 0,
  3819. "Cannot open phar file '%s': %s", fname, error);
  3820. efree(error);
  3821. } else {
  3822. zend_throw_exception_ex(spl_ce_RuntimeException, 0,
  3823. "Cannot open phar file '%s'", fname);
  3824. }
  3825. return;
  3826. }
  3827. if ((entry_info = phar_get_entry_info_dir(phar_data, entry, entry_len, 1, &error, 1)) == NULL) {
  3828. zend_throw_exception_ex(spl_ce_RuntimeException, 0,
  3829. "Cannot access phar file entry '%s' in archive '%s'%s%s", entry, arch, error ? ", " : "", error ? error : "");
  3830. efree(arch);
  3831. efree(entry);
  3832. return;
  3833. }
  3834. efree(arch);
  3835. efree(entry);
  3836. entry_obj->entry = entry_info;
  3837. ZVAL_STRINGL(&arg1, fname, fname_len);
  3838. zend_call_method_with_1_params(zobj, Z_OBJCE_P(zobj),
  3839. &spl_ce_SplFileInfo->constructor, "__construct", NULL, &arg1);
  3840. zval_ptr_dtor(&arg1);
  3841. }
  3842. /* }}} */
  3843. #define PHAR_ENTRY_OBJECT() \
  3844. zval *zobj = getThis(); \
  3845. phar_entry_object *entry_obj = (phar_entry_object*)((char*)Z_OBJ_P(zobj) - Z_OBJ_P(zobj)->handlers->offset); \
  3846. if (!entry_obj->entry) { \
  3847. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
  3848. "Cannot call method on an uninitialized PharFileInfo object"); \
  3849. return; \
  3850. }
  3851. /* {{{ proto PharFileInfo::__destruct()
  3852. * clean up directory-based entry objects
  3853. */
  3854. PHP_METHOD(PharFileInfo, __destruct)
  3855. {
  3856. zval *zobj = getThis();
  3857. phar_entry_object *entry_obj = (phar_entry_object*)((char*)Z_OBJ_P(zobj) - Z_OBJ_P(zobj)->handlers->offset);
  3858. if (entry_obj->entry && entry_obj->entry->is_temp_dir) {
  3859. if (entry_obj->entry->filename) {
  3860. efree(entry_obj->entry->filename);
  3861. entry_obj->entry->filename = NULL;
  3862. }
  3863. efree(entry_obj->entry);
  3864. entry_obj->entry = NULL;
  3865. }
  3866. }
  3867. /* }}} */
  3868. /* {{{ proto int PharFileInfo::getCompressedSize()
  3869. * Returns the compressed size
  3870. */
  3871. PHP_METHOD(PharFileInfo, getCompressedSize)
  3872. {
  3873. PHAR_ENTRY_OBJECT();
  3874. if (zend_parse_parameters_none() == FAILURE) {
  3875. return;
  3876. }
  3877. RETURN_LONG(entry_obj->entry->compressed_filesize);
  3878. }
  3879. /* }}} */
  3880. /* {{{ proto bool PharFileInfo::isCompressed([int compression_type])
  3881. * Returns whether the entry is compressed, and whether it is compressed with Phar::GZ or Phar::BZ2 if specified
  3882. */
  3883. PHP_METHOD(PharFileInfo, isCompressed)
  3884. {
  3885. /* a number that is not Phar::GZ or Phar::BZ2 */
  3886. zend_long method = 9021976;
  3887. PHAR_ENTRY_OBJECT();
  3888. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &method) == FAILURE) {
  3889. return;
  3890. }
  3891. switch (method) {
  3892. case 9021976:
  3893. RETURN_BOOL(entry_obj->entry->flags & PHAR_ENT_COMPRESSION_MASK);
  3894. case PHAR_ENT_COMPRESSED_GZ:
  3895. RETURN_BOOL(entry_obj->entry->flags & PHAR_ENT_COMPRESSED_GZ);
  3896. case PHAR_ENT_COMPRESSED_BZ2:
  3897. RETURN_BOOL(entry_obj->entry->flags & PHAR_ENT_COMPRESSED_BZ2);
  3898. default:
  3899. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
  3900. "Unknown compression type specified"); \
  3901. }
  3902. }
  3903. /* }}} */
  3904. /* {{{ proto int PharFileInfo::getCRC32()
  3905. * Returns CRC32 code or throws an exception if not CRC checked
  3906. */
  3907. PHP_METHOD(PharFileInfo, getCRC32)
  3908. {
  3909. PHAR_ENTRY_OBJECT();
  3910. if (zend_parse_parameters_none() == FAILURE) {
  3911. return;
  3912. }
  3913. if (entry_obj->entry->is_dir) {
  3914. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
  3915. "Phar entry is a directory, does not have a CRC"); \
  3916. return;
  3917. }
  3918. if (entry_obj->entry->is_crc_checked) {
  3919. RETURN_LONG(entry_obj->entry->crc32);
  3920. } else {
  3921. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
  3922. "Phar entry was not CRC checked"); \
  3923. }
  3924. }
  3925. /* }}} */
  3926. /* {{{ proto int PharFileInfo::isCRCChecked()
  3927. * Returns whether file entry is CRC checked
  3928. */
  3929. PHP_METHOD(PharFileInfo, isCRCChecked)
  3930. {
  3931. PHAR_ENTRY_OBJECT();
  3932. if (zend_parse_parameters_none() == FAILURE) {
  3933. return;
  3934. }
  3935. RETURN_BOOL(entry_obj->entry->is_crc_checked);
  3936. }
  3937. /* }}} */
  3938. /* {{{ proto int PharFileInfo::getPharFlags()
  3939. * Returns the Phar file entry flags
  3940. */
  3941. PHP_METHOD(PharFileInfo, getPharFlags)
  3942. {
  3943. PHAR_ENTRY_OBJECT();
  3944. if (zend_parse_parameters_none() == FAILURE) {
  3945. return;
  3946. }
  3947. RETURN_LONG(entry_obj->entry->flags & ~(PHAR_ENT_PERM_MASK|PHAR_ENT_COMPRESSION_MASK));
  3948. }
  3949. /* }}} */
  3950. /* {{{ proto int PharFileInfo::chmod()
  3951. * set the file permissions for the Phar. This only allows setting execution bit, read/write
  3952. */
  3953. PHP_METHOD(PharFileInfo, chmod)
  3954. {
  3955. char *error;
  3956. zend_long perms;
  3957. PHAR_ENTRY_OBJECT();
  3958. if (entry_obj->entry->is_temp_dir) {
  3959. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
  3960. "Phar entry \"%s\" is a temporary directory (not an actual entry in the archive), cannot chmod", entry_obj->entry->filename); \
  3961. return;
  3962. }
  3963. if (PHAR_G(readonly) && !entry_obj->entry->phar->is_data) {
  3964. zend_throw_exception_ex(phar_ce_PharException, 0, "Cannot modify permissions for file \"%s\" in phar \"%s\", write operations are prohibited", entry_obj->entry->filename, entry_obj->entry->phar->fname);
  3965. return;
  3966. }
  3967. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &perms) == FAILURE) {
  3968. return;
  3969. }
  3970. if (entry_obj->entry->is_persistent) {
  3971. phar_archive_data *phar = entry_obj->entry->phar;
  3972. if (FAILURE == phar_copy_on_write(&phar)) {
  3973. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar->fname);
  3974. return;
  3975. }
  3976. /* re-populate after copy-on-write */
  3977. entry_obj->entry = zend_hash_str_find_ptr(&phar->manifest, entry_obj->entry->filename, entry_obj->entry->filename_len);
  3978. }
  3979. /* clear permissions */
  3980. entry_obj->entry->flags &= ~PHAR_ENT_PERM_MASK;
  3981. perms &= 0777;
  3982. entry_obj->entry->flags |= perms;
  3983. entry_obj->entry->old_flags = entry_obj->entry->flags;
  3984. entry_obj->entry->phar->is_modified = 1;
  3985. entry_obj->entry->is_modified = 1;
  3986. /* hackish cache in php_stat needs to be cleared */
  3987. /* if this code fails to work, check main/streams/streams.c, _php_stream_stat_path */
  3988. if (BG(CurrentLStatFile)) {
  3989. efree(BG(CurrentLStatFile));
  3990. }
  3991. if (BG(CurrentStatFile)) {
  3992. efree(BG(CurrentStatFile));
  3993. }
  3994. BG(CurrentLStatFile) = NULL;
  3995. BG(CurrentStatFile) = NULL;
  3996. phar_flush(entry_obj->entry->phar, 0, 0, 0, &error);
  3997. if (error) {
  3998. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  3999. efree(error);
  4000. }
  4001. }
  4002. /* }}} */
  4003. /* {{{ proto int PharFileInfo::hasMetaData()
  4004. * Returns the metadata of the entry
  4005. */
  4006. PHP_METHOD(PharFileInfo, hasMetadata)
  4007. {
  4008. PHAR_ENTRY_OBJECT();
  4009. if (zend_parse_parameters_none() == FAILURE) {
  4010. return;
  4011. }
  4012. RETURN_BOOL(Z_TYPE(entry_obj->entry->metadata) != IS_UNDEF);
  4013. }
  4014. /* }}} */
  4015. /* {{{ proto int PharFileInfo::getMetaData()
  4016. * Returns the metadata of the entry
  4017. */
  4018. PHP_METHOD(PharFileInfo, getMetadata)
  4019. {
  4020. PHAR_ENTRY_OBJECT();
  4021. if (zend_parse_parameters_none() == FAILURE) {
  4022. return;
  4023. }
  4024. if (Z_TYPE(entry_obj->entry->metadata) != IS_UNDEF) {
  4025. if (entry_obj->entry->is_persistent) {
  4026. char *buf = estrndup((char *) Z_PTR(entry_obj->entry->metadata), entry_obj->entry->metadata_len);
  4027. /* assume success, we would have failed before */
  4028. phar_parse_metadata(&buf, return_value, entry_obj->entry->metadata_len);
  4029. efree(buf);
  4030. } else {
  4031. ZVAL_COPY(return_value, &entry_obj->entry->metadata);
  4032. }
  4033. }
  4034. }
  4035. /* }}} */
  4036. /* {{{ proto int PharFileInfo::setMetaData(mixed $metadata)
  4037. * Sets the metadata of the entry
  4038. */
  4039. PHP_METHOD(PharFileInfo, setMetadata)
  4040. {
  4041. char *error;
  4042. zval *metadata;
  4043. PHAR_ENTRY_OBJECT();
  4044. if (PHAR_G(readonly) && !entry_obj->entry->phar->is_data) {
  4045. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Write operations disabled by the php.ini setting phar.readonly");
  4046. return;
  4047. }
  4048. if (entry_obj->entry->is_temp_dir) {
  4049. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
  4050. "Phar entry is a temporary directory (not an actual entry in the archive), cannot set metadata"); \
  4051. return;
  4052. }
  4053. if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &metadata) == FAILURE) {
  4054. return;
  4055. }
  4056. if (entry_obj->entry->is_persistent) {
  4057. phar_archive_data *phar = entry_obj->entry->phar;
  4058. if (FAILURE == phar_copy_on_write(&phar)) {
  4059. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar->fname);
  4060. return;
  4061. }
  4062. /* re-populate after copy-on-write */
  4063. entry_obj->entry = zend_hash_str_find_ptr(&phar->manifest, entry_obj->entry->filename, entry_obj->entry->filename_len);
  4064. }
  4065. if (Z_TYPE(entry_obj->entry->metadata) != IS_UNDEF) {
  4066. zval_ptr_dtor(&entry_obj->entry->metadata);
  4067. ZVAL_UNDEF(&entry_obj->entry->metadata);
  4068. }
  4069. ZVAL_COPY(&entry_obj->entry->metadata, metadata);
  4070. entry_obj->entry->is_modified = 1;
  4071. entry_obj->entry->phar->is_modified = 1;
  4072. phar_flush(entry_obj->entry->phar, 0, 0, 0, &error);
  4073. if (error) {
  4074. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  4075. efree(error);
  4076. }
  4077. }
  4078. /* }}} */
  4079. /* {{{ proto bool PharFileInfo::delMetaData()
  4080. * Deletes the metadata of the entry
  4081. */
  4082. PHP_METHOD(PharFileInfo, delMetadata)
  4083. {
  4084. char *error;
  4085. PHAR_ENTRY_OBJECT();
  4086. if (zend_parse_parameters_none() == FAILURE) {
  4087. return;
  4088. }
  4089. if (PHAR_G(readonly) && !entry_obj->entry->phar->is_data) {
  4090. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Write operations disabled by the php.ini setting phar.readonly");
  4091. return;
  4092. }
  4093. if (entry_obj->entry->is_temp_dir) {
  4094. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
  4095. "Phar entry is a temporary directory (not an actual entry in the archive), cannot delete metadata"); \
  4096. return;
  4097. }
  4098. if (Z_TYPE(entry_obj->entry->metadata) != IS_UNDEF) {
  4099. if (entry_obj->entry->is_persistent) {
  4100. phar_archive_data *phar = entry_obj->entry->phar;
  4101. if (FAILURE == phar_copy_on_write(&phar)) {
  4102. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar->fname);
  4103. return;
  4104. }
  4105. /* re-populate after copy-on-write */
  4106. entry_obj->entry = zend_hash_str_find_ptr(&phar->manifest, entry_obj->entry->filename, entry_obj->entry->filename_len);
  4107. }
  4108. zval_ptr_dtor(&entry_obj->entry->metadata);
  4109. ZVAL_UNDEF(&entry_obj->entry->metadata);
  4110. entry_obj->entry->is_modified = 1;
  4111. entry_obj->entry->phar->is_modified = 1;
  4112. phar_flush(entry_obj->entry->phar, 0, 0, 0, &error);
  4113. if (error) {
  4114. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  4115. efree(error);
  4116. RETURN_FALSE;
  4117. } else {
  4118. RETURN_TRUE;
  4119. }
  4120. } else {
  4121. RETURN_TRUE;
  4122. }
  4123. }
  4124. /* }}} */
  4125. /* {{{ proto string PharFileInfo::getContent()
  4126. * return the complete file contents of the entry (like file_get_contents)
  4127. */
  4128. PHP_METHOD(PharFileInfo, getContent)
  4129. {
  4130. char *error;
  4131. php_stream *fp;
  4132. phar_entry_info *link;
  4133. zend_string *str;
  4134. PHAR_ENTRY_OBJECT();
  4135. if (zend_parse_parameters_none() == FAILURE) {
  4136. return;
  4137. }
  4138. if (entry_obj->entry->is_dir) {
  4139. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4140. "Phar error: Cannot retrieve contents, \"%s\" in phar \"%s\" is a directory", entry_obj->entry->filename, entry_obj->entry->phar->fname);
  4141. return;
  4142. }
  4143. link = phar_get_link_source(entry_obj->entry);
  4144. if (!link) {
  4145. link = entry_obj->entry;
  4146. }
  4147. if (SUCCESS != phar_open_entry_fp(link, &error, 0)) {
  4148. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4149. "Phar error: Cannot retrieve contents, \"%s\" in phar \"%s\": %s", entry_obj->entry->filename, entry_obj->entry->phar->fname, error);
  4150. efree(error);
  4151. return;
  4152. }
  4153. if (!(fp = phar_get_efp(link, 0))) {
  4154. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4155. "Phar error: Cannot retrieve contents of \"%s\" in phar \"%s\"", entry_obj->entry->filename, entry_obj->entry->phar->fname);
  4156. return;
  4157. }
  4158. phar_seek_efp(link, 0, SEEK_SET, 0, 0);
  4159. str = php_stream_copy_to_mem(fp, link->uncompressed_filesize, 0);
  4160. if (str) {
  4161. RETURN_STR(str);
  4162. } else {
  4163. RETURN_EMPTY_STRING();
  4164. }
  4165. }
  4166. /* }}} */
  4167. /* {{{ proto int PharFileInfo::compress(int compression_type)
  4168. * Instructs the Phar class to compress the current file using zlib or bzip2 compression
  4169. */
  4170. PHP_METHOD(PharFileInfo, compress)
  4171. {
  4172. zend_long method;
  4173. char *error;
  4174. PHAR_ENTRY_OBJECT();
  4175. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &method) == FAILURE) {
  4176. return;
  4177. }
  4178. if (entry_obj->entry->is_tar) {
  4179. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4180. "Cannot compress with Gzip compression, not possible with tar-based phar archives");
  4181. return;
  4182. }
  4183. if (entry_obj->entry->is_dir) {
  4184. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
  4185. "Phar entry is a directory, cannot set compression"); \
  4186. return;
  4187. }
  4188. if (PHAR_G(readonly) && !entry_obj->entry->phar->is_data) {
  4189. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4190. "Phar is readonly, cannot change compression");
  4191. return;
  4192. }
  4193. if (entry_obj->entry->is_deleted) {
  4194. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4195. "Cannot compress deleted file");
  4196. return;
  4197. }
  4198. if (entry_obj->entry->is_persistent) {
  4199. phar_archive_data *phar = entry_obj->entry->phar;
  4200. if (FAILURE == phar_copy_on_write(&phar)) {
  4201. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar->fname);
  4202. return;
  4203. }
  4204. /* re-populate after copy-on-write */
  4205. entry_obj->entry = zend_hash_str_find_ptr(&phar->manifest, entry_obj->entry->filename, entry_obj->entry->filename_len);
  4206. }
  4207. switch (method) {
  4208. case PHAR_ENT_COMPRESSED_GZ:
  4209. if (entry_obj->entry->flags & PHAR_ENT_COMPRESSED_GZ) {
  4210. RETURN_TRUE;
  4211. }
  4212. if ((entry_obj->entry->flags & PHAR_ENT_COMPRESSED_BZ2) != 0) {
  4213. if (!PHAR_G(has_bz2)) {
  4214. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4215. "Cannot compress with gzip compression, file is already compressed with bzip2 compression and bz2 extension is not enabled, cannot decompress");
  4216. return;
  4217. }
  4218. /* decompress this file indirectly */
  4219. if (SUCCESS != phar_open_entry_fp(entry_obj->entry, &error, 1)) {
  4220. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4221. "Phar error: Cannot decompress bzip2-compressed file \"%s\" in phar \"%s\" in order to compress with gzip: %s", entry_obj->entry->filename, entry_obj->entry->phar->fname, error);
  4222. efree(error);
  4223. return;
  4224. }
  4225. }
  4226. if (!PHAR_G(has_zlib)) {
  4227. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4228. "Cannot compress with gzip compression, zlib extension is not enabled");
  4229. return;
  4230. }
  4231. entry_obj->entry->old_flags = entry_obj->entry->flags;
  4232. entry_obj->entry->flags &= ~PHAR_ENT_COMPRESSION_MASK;
  4233. entry_obj->entry->flags |= PHAR_ENT_COMPRESSED_GZ;
  4234. break;
  4235. case PHAR_ENT_COMPRESSED_BZ2:
  4236. if (entry_obj->entry->flags & PHAR_ENT_COMPRESSED_BZ2) {
  4237. RETURN_TRUE;
  4238. }
  4239. if ((entry_obj->entry->flags & PHAR_ENT_COMPRESSED_GZ) != 0) {
  4240. if (!PHAR_G(has_zlib)) {
  4241. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4242. "Cannot compress with bzip2 compression, file is already compressed with gzip compression and zlib extension is not enabled, cannot decompress");
  4243. return;
  4244. }
  4245. /* decompress this file indirectly */
  4246. if (SUCCESS != phar_open_entry_fp(entry_obj->entry, &error, 1)) {
  4247. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4248. "Phar error: Cannot decompress gzip-compressed file \"%s\" in phar \"%s\" in order to compress with bzip2: %s", entry_obj->entry->filename, entry_obj->entry->phar->fname, error);
  4249. efree(error);
  4250. return;
  4251. }
  4252. }
  4253. if (!PHAR_G(has_bz2)) {
  4254. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4255. "Cannot compress with bzip2 compression, bz2 extension is not enabled");
  4256. return;
  4257. }
  4258. entry_obj->entry->old_flags = entry_obj->entry->flags;
  4259. entry_obj->entry->flags &= ~PHAR_ENT_COMPRESSION_MASK;
  4260. entry_obj->entry->flags |= PHAR_ENT_COMPRESSED_BZ2;
  4261. break;
  4262. default:
  4263. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
  4264. "Unknown compression type specified"); \
  4265. }
  4266. entry_obj->entry->phar->is_modified = 1;
  4267. entry_obj->entry->is_modified = 1;
  4268. phar_flush(entry_obj->entry->phar, 0, 0, 0, &error);
  4269. if (error) {
  4270. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  4271. efree(error);
  4272. }
  4273. RETURN_TRUE;
  4274. }
  4275. /* }}} */
  4276. /* {{{ proto int PharFileInfo::decompress()
  4277. * Instructs the Phar class to decompress the current file
  4278. */
  4279. PHP_METHOD(PharFileInfo, decompress)
  4280. {
  4281. char *error;
  4282. char *compression_type;
  4283. PHAR_ENTRY_OBJECT();
  4284. if (zend_parse_parameters_none() == FAILURE) {
  4285. return;
  4286. }
  4287. if (entry_obj->entry->is_dir) {
  4288. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
  4289. "Phar entry is a directory, cannot set compression"); \
  4290. return;
  4291. }
  4292. if ((entry_obj->entry->flags & PHAR_ENT_COMPRESSION_MASK) == 0) {
  4293. RETURN_TRUE;
  4294. }
  4295. if (PHAR_G(readonly) && !entry_obj->entry->phar->is_data) {
  4296. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4297. "Phar is readonly, cannot decompress");
  4298. return;
  4299. }
  4300. if (entry_obj->entry->is_deleted) {
  4301. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4302. "Cannot compress deleted file");
  4303. return;
  4304. }
  4305. if ((entry_obj->entry->flags & PHAR_ENT_COMPRESSED_GZ) != 0 && !PHAR_G(has_zlib)) {
  4306. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4307. "Cannot decompress Gzip-compressed file, zlib extension is not enabled");
  4308. return;
  4309. }
  4310. if ((entry_obj->entry->flags & PHAR_ENT_COMPRESSED_BZ2) != 0 && !PHAR_G(has_bz2)) {
  4311. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4312. "Cannot decompress Bzip2-compressed file, bz2 extension is not enabled");
  4313. return;
  4314. }
  4315. if (entry_obj->entry->is_persistent) {
  4316. phar_archive_data *phar = entry_obj->entry->phar;
  4317. if (FAILURE == phar_copy_on_write(&phar)) {
  4318. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar->fname);
  4319. return;
  4320. }
  4321. /* re-populate after copy-on-write */
  4322. entry_obj->entry = zend_hash_str_find_ptr(&phar->manifest, entry_obj->entry->filename, entry_obj->entry->filename_len);
  4323. }
  4324. switch (entry_obj->entry->flags & PHAR_ENT_COMPRESSION_MASK) {
  4325. case PHAR_ENT_COMPRESSED_GZ:
  4326. compression_type = "gzip";
  4327. break;
  4328. case PHAR_ENT_COMPRESSED_BZ2:
  4329. compression_type = "bz2";
  4330. break;
  4331. default:
  4332. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4333. "Cannot decompress file compressed with unknown compression type");
  4334. return;
  4335. }
  4336. /* decompress this file indirectly */
  4337. if (SUCCESS != phar_open_entry_fp(entry_obj->entry, &error, 1)) {
  4338. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4339. "Phar error: Cannot decompress %s-compressed file \"%s\" in phar \"%s\": %s", compression_type, entry_obj->entry->filename, entry_obj->entry->phar->fname, error);
  4340. efree(error);
  4341. return;
  4342. }
  4343. entry_obj->entry->old_flags = entry_obj->entry->flags;
  4344. entry_obj->entry->flags &= ~PHAR_ENT_COMPRESSION_MASK;
  4345. entry_obj->entry->phar->is_modified = 1;
  4346. entry_obj->entry->is_modified = 1;
  4347. phar_flush(entry_obj->entry->phar, 0, 0, 0, &error);
  4348. if (error) {
  4349. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  4350. efree(error);
  4351. }
  4352. RETURN_TRUE;
  4353. }
  4354. /* }}} */
  4355. /* {{{ phar methods */
  4356. ZEND_BEGIN_ARG_INFO_EX(arginfo_phar___construct, 0, 0, 1)
  4357. ZEND_ARG_INFO(0, filename)
  4358. ZEND_ARG_INFO(0, flags)
  4359. ZEND_ARG_INFO(0, alias)
  4360. ZEND_END_ARG_INFO()
  4361. ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_createDS, 0, 0, 0)
  4362. ZEND_ARG_INFO(0, index)
  4363. ZEND_ARG_INFO(0, webindex)
  4364. ZEND_END_ARG_INFO()
  4365. ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_cancompress, 0, 0, 0)
  4366. ZEND_ARG_INFO(0, method)
  4367. ZEND_END_ARG_INFO()
  4368. ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_isvalidpharfilename, 0, 0, 1)
  4369. ZEND_ARG_INFO(0, filename)
  4370. ZEND_ARG_INFO(0, executable)
  4371. ZEND_END_ARG_INFO()
  4372. ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_loadPhar, 0, 0, 1)
  4373. ZEND_ARG_INFO(0, filename)
  4374. ZEND_ARG_INFO(0, alias)
  4375. ZEND_END_ARG_INFO()
  4376. ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_mapPhar, 0, 0, 0)
  4377. ZEND_ARG_INFO(0, alias)
  4378. ZEND_ARG_INFO(0, offset)
  4379. ZEND_END_ARG_INFO()
  4380. ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_mount, 0, 0, 2)
  4381. ZEND_ARG_INFO(0, inphar)
  4382. ZEND_ARG_INFO(0, externalfile)
  4383. ZEND_END_ARG_INFO()
  4384. ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_mungServer, 0, 0, 1)
  4385. ZEND_ARG_INFO(0, munglist)
  4386. ZEND_END_ARG_INFO()
  4387. ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_webPhar, 0, 0, 0)
  4388. ZEND_ARG_INFO(0, alias)
  4389. ZEND_ARG_INFO(0, index)
  4390. ZEND_ARG_INFO(0, f404)
  4391. ZEND_ARG_INFO(0, mimetypes)
  4392. ZEND_ARG_INFO(0, rewrites)
  4393. ZEND_END_ARG_INFO()
  4394. ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_running, 0, 0, 0)
  4395. ZEND_ARG_INFO(0, retphar)
  4396. ZEND_END_ARG_INFO()
  4397. ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_ua, 0, 0, 1)
  4398. ZEND_ARG_INFO(0, archive)
  4399. ZEND_END_ARG_INFO()
  4400. ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_build, 0, 0, 1)
  4401. ZEND_ARG_INFO(0, iterator)
  4402. ZEND_ARG_INFO(0, base_directory)
  4403. ZEND_END_ARG_INFO()
  4404. ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_conv, 0, 0, 0)
  4405. ZEND_ARG_INFO(0, format)
  4406. ZEND_ARG_INFO(0, compression_type)
  4407. ZEND_ARG_INFO(0, file_ext)
  4408. ZEND_END_ARG_INFO()
  4409. ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_comps, 0, 0, 1)
  4410. ZEND_ARG_INFO(0, compression_type)
  4411. ZEND_ARG_INFO(0, file_ext)
  4412. ZEND_END_ARG_INFO()
  4413. ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_decomp, 0, 0, 0)
  4414. ZEND_ARG_INFO(0, file_ext)
  4415. ZEND_END_ARG_INFO()
  4416. ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_comp, 0, 0, 1)
  4417. ZEND_ARG_INFO(0, compression_type)
  4418. ZEND_END_ARG_INFO()
  4419. ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_compo, 0, 0, 0)
  4420. ZEND_ARG_INFO(0, compression_type)
  4421. ZEND_END_ARG_INFO()
  4422. ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_copy, 0, 0, 2)
  4423. ZEND_ARG_INFO(0, newfile)
  4424. ZEND_ARG_INFO(0, oldfile)
  4425. ZEND_END_ARG_INFO()
  4426. ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_delete, 0, 0, 1)
  4427. ZEND_ARG_INFO(0, entry)
  4428. ZEND_END_ARG_INFO()
  4429. ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_fromdir, 0, 0, 1)
  4430. ZEND_ARG_INFO(0, base_dir)
  4431. ZEND_ARG_INFO(0, regex)
  4432. ZEND_END_ARG_INFO()
  4433. ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_offsetExists, 0, 0, 1)
  4434. ZEND_ARG_INFO(0, entry)
  4435. ZEND_END_ARG_INFO()
  4436. ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_offsetSet, 0, 0, 2)
  4437. ZEND_ARG_INFO(0, entry)
  4438. ZEND_ARG_INFO(0, value)
  4439. ZEND_END_ARG_INFO()
  4440. ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_setAlias, 0, 0, 1)
  4441. ZEND_ARG_INFO(0, alias)
  4442. ZEND_END_ARG_INFO()
  4443. ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_setMetadata, 0, 0, 1)
  4444. ZEND_ARG_INFO(0, metadata)
  4445. ZEND_END_ARG_INFO()
  4446. ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_setSigAlgo, 0, 0, 1)
  4447. ZEND_ARG_INFO(0, algorithm)
  4448. ZEND_ARG_INFO(0, privatekey)
  4449. ZEND_END_ARG_INFO()
  4450. ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_setStub, 0, 0, 1)
  4451. ZEND_ARG_INFO(0, newstub)
  4452. ZEND_ARG_INFO(0, maxlen)
  4453. ZEND_END_ARG_INFO()
  4454. ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_emptydir, 0, 0, 0)
  4455. ZEND_ARG_INFO(0, dirname)
  4456. ZEND_END_ARG_INFO()
  4457. ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_extract, 0, 0, 1)
  4458. ZEND_ARG_INFO(0, pathto)
  4459. ZEND_ARG_INFO(0, files)
  4460. ZEND_ARG_INFO(0, overwrite)
  4461. ZEND_END_ARG_INFO()
  4462. ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_addfile, 0, 0, 1)
  4463. ZEND_ARG_INFO(0, filename)
  4464. ZEND_ARG_INFO(0, localname)
  4465. ZEND_END_ARG_INFO()
  4466. ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_fromstring, 0, 0, 1)
  4467. ZEND_ARG_INFO(0, localname)
  4468. ZEND_ARG_INFO(0, contents)
  4469. ZEND_END_ARG_INFO()
  4470. ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_isff, 0, 0, 1)
  4471. ZEND_ARG_INFO(0, fileformat)
  4472. ZEND_END_ARG_INFO()
  4473. ZEND_BEGIN_ARG_INFO(arginfo_phar__void, 0)
  4474. ZEND_END_ARG_INFO()
  4475. static const zend_function_entry php_archive_methods[] = {
  4476. PHP_ME(Phar, __construct, arginfo_phar___construct, ZEND_ACC_PUBLIC)
  4477. PHP_ME(Phar, __destruct, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4478. PHP_ME(Phar, addEmptyDir, arginfo_phar_emptydir, ZEND_ACC_PUBLIC)
  4479. PHP_ME(Phar, addFile, arginfo_phar_addfile, ZEND_ACC_PUBLIC)
  4480. PHP_ME(Phar, addFromString, arginfo_phar_fromstring, ZEND_ACC_PUBLIC)
  4481. PHP_ME(Phar, buildFromDirectory, arginfo_phar_fromdir, ZEND_ACC_PUBLIC)
  4482. PHP_ME(Phar, buildFromIterator, arginfo_phar_build, ZEND_ACC_PUBLIC)
  4483. PHP_ME(Phar, compressFiles, arginfo_phar_comp, ZEND_ACC_PUBLIC)
  4484. PHP_ME(Phar, decompressFiles, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4485. PHP_ME(Phar, compress, arginfo_phar_comps, ZEND_ACC_PUBLIC)
  4486. PHP_ME(Phar, decompress, arginfo_phar_decomp, ZEND_ACC_PUBLIC)
  4487. PHP_ME(Phar, convertToExecutable, arginfo_phar_conv, ZEND_ACC_PUBLIC)
  4488. PHP_ME(Phar, convertToData, arginfo_phar_conv, ZEND_ACC_PUBLIC)
  4489. PHP_ME(Phar, copy, arginfo_phar_copy, ZEND_ACC_PUBLIC)
  4490. PHP_ME(Phar, count, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4491. PHP_ME(Phar, delete, arginfo_phar_delete, ZEND_ACC_PUBLIC)
  4492. PHP_ME(Phar, delMetadata, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4493. PHP_ME(Phar, extractTo, arginfo_phar_extract, ZEND_ACC_PUBLIC)
  4494. PHP_ME(Phar, getAlias, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4495. PHP_ME(Phar, getPath, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4496. PHP_ME(Phar, getMetadata, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4497. PHP_ME(Phar, getModified, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4498. PHP_ME(Phar, getSignature, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4499. PHP_ME(Phar, getStub, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4500. PHP_ME(Phar, getVersion, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4501. PHP_ME(Phar, hasMetadata, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4502. PHP_ME(Phar, isBuffering, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4503. PHP_ME(Phar, isCompressed, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4504. PHP_ME(Phar, isFileFormat, arginfo_phar_isff, ZEND_ACC_PUBLIC)
  4505. PHP_ME(Phar, isWritable, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4506. PHP_ME(Phar, offsetExists, arginfo_phar_offsetExists, ZEND_ACC_PUBLIC)
  4507. PHP_ME(Phar, offsetGet, arginfo_phar_offsetExists, ZEND_ACC_PUBLIC)
  4508. PHP_ME(Phar, offsetSet, arginfo_phar_offsetSet, ZEND_ACC_PUBLIC)
  4509. PHP_ME(Phar, offsetUnset, arginfo_phar_offsetExists, ZEND_ACC_PUBLIC)
  4510. PHP_ME(Phar, setAlias, arginfo_phar_setAlias, ZEND_ACC_PUBLIC)
  4511. PHP_ME(Phar, setDefaultStub, arginfo_phar_createDS, ZEND_ACC_PUBLIC)
  4512. PHP_ME(Phar, setMetadata, arginfo_phar_setMetadata, ZEND_ACC_PUBLIC)
  4513. PHP_ME(Phar, setSignatureAlgorithm, arginfo_phar_setSigAlgo, ZEND_ACC_PUBLIC)
  4514. PHP_ME(Phar, setStub, arginfo_phar_setStub, ZEND_ACC_PUBLIC)
  4515. PHP_ME(Phar, startBuffering, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4516. PHP_ME(Phar, stopBuffering, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4517. /* static member functions */
  4518. PHP_ME(Phar, apiVersion, arginfo_phar__void, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
  4519. PHP_ME(Phar, canCompress, arginfo_phar_cancompress, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
  4520. PHP_ME(Phar, canWrite, arginfo_phar__void, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
  4521. PHP_ME(Phar, createDefaultStub, arginfo_phar_createDS, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
  4522. PHP_ME(Phar, getSupportedCompression,arginfo_phar__void, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
  4523. PHP_ME(Phar, getSupportedSignatures,arginfo_phar__void, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
  4524. PHP_ME(Phar, interceptFileFuncs, arginfo_phar__void, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
  4525. PHP_ME(Phar, isValidPharFilename, arginfo_phar_isvalidpharfilename, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
  4526. PHP_ME(Phar, loadPhar, arginfo_phar_loadPhar, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
  4527. PHP_ME(Phar, mapPhar, arginfo_phar_mapPhar, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
  4528. PHP_ME(Phar, running, arginfo_phar_running, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
  4529. PHP_ME(Phar, mount, arginfo_phar_mount, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
  4530. PHP_ME(Phar, mungServer, arginfo_phar_mungServer, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
  4531. PHP_ME(Phar, unlinkArchive, arginfo_phar_ua, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
  4532. PHP_ME(Phar, webPhar, arginfo_phar_webPhar, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
  4533. PHP_FE_END
  4534. };
  4535. ZEND_BEGIN_ARG_INFO_EX(arginfo_data___construct, 0, 0, 1)
  4536. ZEND_ARG_INFO(0, filename)
  4537. ZEND_ARG_INFO(0, flags)
  4538. ZEND_ARG_INFO(0, alias)
  4539. ZEND_ARG_INFO(0, fileformat)
  4540. ZEND_END_ARG_INFO()
  4541. static const zend_function_entry php_data_methods[] = {
  4542. PHP_ME(Phar, __construct, arginfo_data___construct, ZEND_ACC_PUBLIC)
  4543. PHP_ME(Phar, __destruct, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4544. PHP_ME(Phar, addEmptyDir, arginfo_phar_emptydir, ZEND_ACC_PUBLIC)
  4545. PHP_ME(Phar, addFile, arginfo_phar_addfile, ZEND_ACC_PUBLIC)
  4546. PHP_ME(Phar, addFromString, arginfo_phar_fromstring, ZEND_ACC_PUBLIC)
  4547. PHP_ME(Phar, buildFromDirectory, arginfo_phar_fromdir, ZEND_ACC_PUBLIC)
  4548. PHP_ME(Phar, buildFromIterator, arginfo_phar_build, ZEND_ACC_PUBLIC)
  4549. PHP_ME(Phar, compressFiles, arginfo_phar_comp, ZEND_ACC_PUBLIC)
  4550. PHP_ME(Phar, decompressFiles, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4551. PHP_ME(Phar, compress, arginfo_phar_comps, ZEND_ACC_PUBLIC)
  4552. PHP_ME(Phar, decompress, arginfo_phar_decomp, ZEND_ACC_PUBLIC)
  4553. PHP_ME(Phar, convertToExecutable, arginfo_phar_conv, ZEND_ACC_PUBLIC)
  4554. PHP_ME(Phar, convertToData, arginfo_phar_conv, ZEND_ACC_PUBLIC)
  4555. PHP_ME(Phar, copy, arginfo_phar_copy, ZEND_ACC_PUBLIC)
  4556. PHP_ME(Phar, count, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4557. PHP_ME(Phar, delete, arginfo_phar_delete, ZEND_ACC_PUBLIC)
  4558. PHP_ME(Phar, delMetadata, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4559. PHP_ME(Phar, extractTo, arginfo_phar_extract, ZEND_ACC_PUBLIC)
  4560. PHP_ME(Phar, getAlias, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4561. PHP_ME(Phar, getPath, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4562. PHP_ME(Phar, getMetadata, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4563. PHP_ME(Phar, getModified, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4564. PHP_ME(Phar, getSignature, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4565. PHP_ME(Phar, getStub, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4566. PHP_ME(Phar, getVersion, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4567. PHP_ME(Phar, hasMetadata, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4568. PHP_ME(Phar, isBuffering, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4569. PHP_ME(Phar, isCompressed, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4570. PHP_ME(Phar, isFileFormat, arginfo_phar_isff, ZEND_ACC_PUBLIC)
  4571. PHP_ME(Phar, isWritable, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4572. PHP_ME(Phar, offsetExists, arginfo_phar_offsetExists, ZEND_ACC_PUBLIC)
  4573. PHP_ME(Phar, offsetGet, arginfo_phar_offsetExists, ZEND_ACC_PUBLIC)
  4574. PHP_ME(Phar, offsetSet, arginfo_phar_offsetSet, ZEND_ACC_PUBLIC)
  4575. PHP_ME(Phar, offsetUnset, arginfo_phar_offsetExists, ZEND_ACC_PUBLIC)
  4576. PHP_ME(Phar, setAlias, arginfo_phar_setAlias, ZEND_ACC_PUBLIC)
  4577. PHP_ME(Phar, setDefaultStub, arginfo_phar_createDS, ZEND_ACC_PUBLIC)
  4578. PHP_ME(Phar, setMetadata, arginfo_phar_setMetadata, ZEND_ACC_PUBLIC)
  4579. PHP_ME(Phar, setSignatureAlgorithm, arginfo_phar_setSigAlgo, ZEND_ACC_PUBLIC)
  4580. PHP_ME(Phar, setStub, arginfo_phar_setStub, ZEND_ACC_PUBLIC)
  4581. PHP_ME(Phar, startBuffering, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4582. PHP_ME(Phar, stopBuffering, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4583. /* static member functions */
  4584. PHP_ME(Phar, apiVersion, arginfo_phar__void, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
  4585. PHP_ME(Phar, canCompress, arginfo_phar_cancompress, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
  4586. PHP_ME(Phar, canWrite, arginfo_phar__void, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
  4587. PHP_ME(Phar, createDefaultStub, arginfo_phar_createDS, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
  4588. PHP_ME(Phar, getSupportedCompression,arginfo_phar__void, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
  4589. PHP_ME(Phar, getSupportedSignatures,arginfo_phar__void, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
  4590. PHP_ME(Phar, interceptFileFuncs, arginfo_phar__void, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
  4591. PHP_ME(Phar, isValidPharFilename, arginfo_phar_isvalidpharfilename, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
  4592. PHP_ME(Phar, loadPhar, arginfo_phar_loadPhar, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
  4593. PHP_ME(Phar, mapPhar, arginfo_phar_mapPhar, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
  4594. PHP_ME(Phar, running, arginfo_phar_running, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
  4595. PHP_ME(Phar, mount, arginfo_phar_mount, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
  4596. PHP_ME(Phar, mungServer, arginfo_phar_mungServer, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
  4597. PHP_ME(Phar, unlinkArchive, arginfo_phar_ua, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
  4598. PHP_ME(Phar, webPhar, arginfo_phar_webPhar, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
  4599. PHP_FE_END
  4600. };
  4601. ZEND_BEGIN_ARG_INFO_EX(arginfo_entry___construct, 0, 0, 1)
  4602. ZEND_ARG_INFO(0, filename)
  4603. ZEND_END_ARG_INFO()
  4604. ZEND_BEGIN_ARG_INFO_EX(arginfo_entry_chmod, 0, 0, 1)
  4605. ZEND_ARG_INFO(0, perms)
  4606. ZEND_END_ARG_INFO()
  4607. static const zend_function_entry php_entry_methods[] = {
  4608. PHP_ME(PharFileInfo, __construct, arginfo_entry___construct, ZEND_ACC_PUBLIC)
  4609. PHP_ME(PharFileInfo, __destruct, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4610. PHP_ME(PharFileInfo, chmod, arginfo_entry_chmod, ZEND_ACC_PUBLIC)
  4611. PHP_ME(PharFileInfo, compress, arginfo_phar_comp, ZEND_ACC_PUBLIC)
  4612. PHP_ME(PharFileInfo, decompress, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4613. PHP_ME(PharFileInfo, delMetadata, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4614. PHP_ME(PharFileInfo, getCompressedSize, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4615. PHP_ME(PharFileInfo, getCRC32, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4616. PHP_ME(PharFileInfo, getContent, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4617. PHP_ME(PharFileInfo, getMetadata, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4618. PHP_ME(PharFileInfo, getPharFlags, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4619. PHP_ME(PharFileInfo, hasMetadata, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4620. PHP_ME(PharFileInfo, isCompressed, arginfo_phar_compo, ZEND_ACC_PUBLIC)
  4621. PHP_ME(PharFileInfo, isCRCChecked, arginfo_phar__void, ZEND_ACC_PUBLIC)
  4622. PHP_ME(PharFileInfo, setMetadata, arginfo_phar_setMetadata, ZEND_ACC_PUBLIC)
  4623. PHP_FE_END
  4624. };
  4625. static const zend_function_entry phar_exception_methods[] = {
  4626. PHP_FE_END
  4627. };
  4628. /* }}} */
  4629. #define REGISTER_PHAR_CLASS_CONST_LONG(class_name, const_name, value) \
  4630. zend_declare_class_constant_long(class_name, const_name, sizeof(const_name)-1, (zend_long)value);
  4631. void phar_object_init(void) /* {{{ */
  4632. {
  4633. zend_class_entry ce;
  4634. INIT_CLASS_ENTRY(ce, "PharException", phar_exception_methods);
  4635. phar_ce_PharException = zend_register_internal_class_ex(&ce, zend_ce_exception);
  4636. INIT_CLASS_ENTRY(ce, "Phar", php_archive_methods);
  4637. phar_ce_archive = zend_register_internal_class_ex(&ce, spl_ce_RecursiveDirectoryIterator);
  4638. zend_class_implements(phar_ce_archive, 2, zend_ce_countable, zend_ce_arrayaccess);
  4639. INIT_CLASS_ENTRY(ce, "PharData", php_data_methods);
  4640. phar_ce_data = zend_register_internal_class_ex(&ce, spl_ce_RecursiveDirectoryIterator);
  4641. zend_class_implements(phar_ce_data, 2, zend_ce_countable, zend_ce_arrayaccess);
  4642. INIT_CLASS_ENTRY(ce, "PharFileInfo", php_entry_methods);
  4643. phar_ce_entry = zend_register_internal_class_ex(&ce, spl_ce_SplFileInfo);
  4644. REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "BZ2", PHAR_ENT_COMPRESSED_BZ2)
  4645. REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "GZ", PHAR_ENT_COMPRESSED_GZ)
  4646. REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "NONE", PHAR_ENT_COMPRESSED_NONE)
  4647. REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "PHAR", PHAR_FORMAT_PHAR)
  4648. REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "TAR", PHAR_FORMAT_TAR)
  4649. REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "ZIP", PHAR_FORMAT_ZIP)
  4650. REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "COMPRESSED", PHAR_ENT_COMPRESSION_MASK)
  4651. REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "PHP", PHAR_MIME_PHP)
  4652. REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "PHPS", PHAR_MIME_PHPS)
  4653. REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "MD5", PHAR_SIG_MD5)
  4654. REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "OPENSSL", PHAR_SIG_OPENSSL)
  4655. REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "SHA1", PHAR_SIG_SHA1)
  4656. REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "SHA256", PHAR_SIG_SHA256)
  4657. REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "SHA512", PHAR_SIG_SHA512)
  4658. }
  4659. /* }}} */
  4660. /*
  4661. * Local variables:
  4662. * tab-width: 4
  4663. * c-basic-offset: 4
  4664. * End:
  4665. * vim600: noet sw=4 ts=4 fdm=marker
  4666. * vim<600: noet sw=4 ts=4
  4667. */